update vehicle adapter

This commit is contained in:
wait 2025-04-18 11:06:14 +08:00
parent 17c28a5a7f
commit 4882a28c0a
81 changed files with 4660 additions and 4635 deletions

View File

@ -1,40 +0,0 @@
package org.opentcs.kcvehicle;
import com.google.inject.assistedinject.FactoryModuleBuilder;
import org.opentcs.customizations.kernel.KernelInjectionModule;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KcCommAdapterModule extends KernelInjectionModule {
private static final Logger LOG = LoggerFactory.getLogger(KcCommAdapterModule.class);
@Override
protected void configure() {
//
// VirtualVehicleConfiguration configuration
// = getConfigBindingProvider().get(
// VirtualVehicleConfiguration.PREFIX,
// VirtualVehicleConfiguration.class
// );
//
//// KcVehicleConfiguration configuration
//// = getConfigBindingProvider().get(
//// KcVehicleConfiguration.PREFIX,
//// KcVehicleConfiguration.class
//// );
//
// if (!configuration.enable()) {
// LOG.info("KC driver disabled by configuration.");
// return;
// }
//
// bind(VirtualVehicleConfiguration.class)
// .toInstance(configuration);
//
// install(new FactoryModuleBuilder().build(LoopbackAdapterComponentsFactory.class));
//
// vehicleCommAdaptersBinder().addBinding().to(LoopbackCommunicationAdapterFactory.class);
}
}

View File

@ -2,4 +2,3 @@
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
org.opentcs.virtualvehicle.LoopbackCommAdapterModule org.opentcs.virtualvehicle.LoopbackCommAdapterModule
org.opentcs.kcvehicle.KcCommAdapterModule

View File

@ -1,10 +0,0 @@
package org.opentcs.kcvehicle;
import org.opentcs.data.model.Vehicle;
import org.opentcs.kcvehicle.KcCommunicationAdapter;
public interface KcAdapterComponentsFactory {
// KcCommunicationAdapter createKcCommunicationAdapter(Vehicle vehicle);
KcCommunicationAdapter createKcCommunicationAdapter(Vehicle vehicle);
}

View File

@ -1,163 +0,0 @@
package org.opentcs.kcvehicle;
import com.google.inject.assistedinject.Assisted;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import jakarta.inject.Inject;
import java.util.concurrent.ScheduledExecutorService;
import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.BasicVehicleCommAdapter;
import org.opentcs.drivers.vehicle.MovementCommand;
import org.opentcs.drivers.vehicle.VehicleProcessModel;
import org.opentcs.kc.udp.Service.ConfirmRelocation;
import org.opentcs.kc.udp.Service.ManualPosition;
import org.opentcs.kc.udp.Service.QryRobotRunStatus;
import org.opentcs.kc.udp.Service.QryRobotStatus;
import org.opentcs.kc.udp.Service.SubCargoStatus;
import org.opentcs.kc.udp.Service.SubRobotStatue;
import org.opentcs.kc.udp.Service.SwitchAutomaticMode;
import org.opentcs.kc.udp.Service.SwitchManualMode;
import org.opentcs.kc.udp.agv.param.function.af.LocationStatusInfo;
import org.opentcs.kc.udp.agv.param.function.af.QueryRobotStatusRsp;
import org.opentcs.kc.udp.agv.param.function.x17.QueryRobotRunStatusRsp;
import org.opentcs.util.ExplainedBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KcCommunicationAdapter extends BasicVehicleCommAdapter {
private static final Logger LOG = LoggerFactory.getLogger(KcCommunicationAdapter.class);
/**
* This instance's configuration.
*/
private final KcVehicleConfiguration configuration;
/**
* 单个仿真步骤的时间 毫秒
*/
private static final int SIMULATION_PERIOD = 100;
/**
* Creates a new instance.
*/
@Inject
public KcCommunicationAdapter(
KcVehicleConfiguration configuration,
@Assisted
Vehicle vehicle,
@KernelExecutor
ScheduledExecutorService kernelExecutor
) {
super(
new VehicleProcessModel(vehicle),
configuration.commandQueueCapacity(),
configuration.rechargeOperation(),
kernelExecutor
);
this.configuration = configuration;
}
// @Inject
// public KcCommunicationAdapter(Vehicle vehicle) {
// super(new VehicleProcessModel(vehicle), 1, "Recharge");
// }
@Override
public void sendCommand(MovementCommand cmd)
throws IllegalArgumentException {
}
@Override
protected void connectVehicle() {
//initAGV();
getProcessModel().setCommAdapterConnected(true);
}
@Override
protected void disconnectVehicle() {
getProcessModel().setCommAdapterConnected(false);
}
@Override
protected boolean isVehicleConnected() {
return getProcessModel().isCommAdapterConnected();
}
@Nonnull
@Override
public ExplainedBoolean canProcess(
@Nonnull
TransportOrder order
) {
return null;
}
@Override
public void onVehiclePaused(boolean paused) {
}
@Override
public void processMessage(
@Nullable
Object message
) {
}
/**
* 初始化AGV
* 步骤:
* 1调度软件启动机器人启动无顺序要求
* 2等待调度系统以及机器人控制器启动完成调度系统启动即向机器人发送状态查询查询成功即为启动完成
* 3调度软件发送订阅信令至机器人表明订阅机器人状态信息或载货状态机器人接收到订阅信令会依据订阅要求推送订阅信息度软件需要根据订阅信令中上报持续时间提前刷新机器人推送的上报持续时间
* 4调度软件持续监控机器人实时状态
* 5导航初始化
*/
private void initAGV() {
//0xAF获取AGV状态
QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command();
//开启AGV订阅监听 (0xAF & 0xB0)
SubRobotStatue.command();
SubCargoStatus.command();
//1 切换定位为手动模式命令码0x03变量NaviControl 修改为0
SwitchManualMode.command();
LocationStatusInfo locationStatusInfo = qryRobotStatusRsp.locationStatusInfo;
double agvX = locationStatusInfo.globalX;
double agvY = locationStatusInfo.globalY;
double agvAngle = locationStatusInfo.absoluteDirecAngle;
//3 查询机器人运行状态命令码0x17等待机器人定位状态为定位完成
QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command();
if (qryRobotRunStatusRsp.robotLocalizationState == 0) {
//2 执行机器人手动定位 命令码0x14
ManualPosition.command(agvX, agvY, agvAngle);
throw new RuntimeException("AGV定位失败执行手动定位中");
} else if (qryRobotRunStatusRsp.robotLocalizationState == 2) {
throw new RuntimeException("AGV定位中");
}
//4 确认初始位置命令码0x1F
ConfirmRelocation.commnd();
//5 切换成自动模式命令码0x03变量NaviControl 修改为1
SwitchAutomaticMode.command();
//打开通讯适配器连接
getProcessModel().setCommAdapterConnected(true);
}
private int getSimulationTimeStep() {
return (int) (SIMULATION_PERIOD * configuration.simulationTimeFactor());
}
}

View File

@ -1,15 +0,0 @@
package org.opentcs.kcvehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
public class KcCommunicationAdapterDescription extends VehicleCommAdapterDescription {
@Override
public String getDescription() {
return "KC_ADAPTER";
}
@Override
public boolean isSimVehicleCommAdapter() {
return false;
}
}

View File

@ -1,61 +0,0 @@
package org.opentcs.kcvehicle;
import static java.util.Objects.requireNonNull;
import jakarta.annotation.Nonnull;
import jakarta.annotation.Nullable;
import jakarta.inject.Inject;
import org.opentcs.data.model.Vehicle;
import org.opentcs.drivers.vehicle.VehicleCommAdapter;
import org.opentcs.drivers.vehicle.VehicleCommAdapterDescription;
import org.opentcs.drivers.vehicle.VehicleCommAdapterFactory;
import org.opentcs.drivers.vehicle.VehicleProcessModel;
public class KcCommunicationAdapterFactory implements VehicleCommAdapterFactory {
private final KcAdapterComponentsFactory adapterFactory;
@Inject
public KcCommunicationAdapterFactory(KcAdapterComponentsFactory componentsFactory) {
this.adapterFactory = requireNonNull(componentsFactory, "KC_componentsFactory_NULL");
}
@Override
public VehicleCommAdapterDescription getDescription() {
return new KcCommunicationAdapterDescription();
}
@Override
public boolean providesAdapterFor(
@Nonnull
Vehicle vehicle
) {
return false;
}
@Nullable
@Override
public VehicleCommAdapter getAdapterFor(
@Nonnull
Vehicle vehicle
) {
return adapterFactory.createKcCommunicationAdapter(vehicle);
// return adapterFactory.createKcCommunicationAdapter(vehicle);
}
@Override
public void initialize() {
}
@Override
public boolean isInitialized() {
return false;
}
@Override
public void terminate() {
}
}

View File

@ -1,77 +0,0 @@
// SPDX-FileCopyrightText: The openTCS Authors
// SPDX-License-Identifier: MIT
package org.opentcs.kcvehicle;
import org.opentcs.configuration.ConfigurationEntry;
import org.opentcs.configuration.ConfigurationPrefix;
/**
* Provides methods to configure to {@link KcCommunicationAdapter}.
*/
@ConfigurationPrefix(KcVehicleConfiguration.PREFIX)
public interface KcVehicleConfiguration {
/**
* This configuration's prefix.
*/
String PREFIX = "kcvehicle";
@ConfigurationEntry(
type = "Boolean",
description = "Whether to enable to register/enable the loopback driver.",
changesApplied = ConfigurationEntry.ChangesApplied.ON_APPLICATION_START,
orderKey = "0_enable"
)
boolean enable();
@ConfigurationEntry(
type = "Integer",
description = "The adapter's command queue capacity.",
changesApplied = ConfigurationEntry.ChangesApplied.ON_NEW_PLANT_MODEL,
orderKey = "1_attributes_1"
)
int commandQueueCapacity();
@ConfigurationEntry(
type = "String",
description = "The string to be treated as a recharge operation.",
changesApplied = ConfigurationEntry.ChangesApplied.ON_NEW_PLANT_MODEL,
orderKey = "1_attributes_2"
)
String rechargeOperation();
@ConfigurationEntry(
type = "Double",
description = "The rate at which the vehicle recharges in percent per second.",
changesApplied = ConfigurationEntry.ChangesApplied.INSTANTLY,
orderKey = "1_attributes_3"
)
double rechargePercentagePerSecond();
@ConfigurationEntry(
type = "Double",
description = {
"The simulation time factor.",
"1.0 is real time, greater values speed up simulation."
},
changesApplied = ConfigurationEntry.ChangesApplied.INSTANTLY,
orderKey = "2_behaviour_1"
)
double simulationTimeFactor();
@ConfigurationEntry(
type = "Integer",
description = {"The virtual vehicle's length in mm when it's loaded."},
changesApplied = ConfigurationEntry.ChangesApplied.INSTANTLY,
orderKey = "2_behaviour_2"
)
int vehicleLengthLoaded();
@ConfigurationEntry(
type = "Integer",
description = {"The virtual vehicle's length in mm when it's unloaded."},
changesApplied = ConfigurationEntry.ChangesApplied.INSTANTLY,
orderKey = "2_behaviour_3"
)
int vehicleLengthUnloaded();
}

View File

@ -7,6 +7,7 @@ import static java.util.Objects.requireNonNull;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
import jakarta.inject.Inject; import jakarta.inject.Inject;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.time.LocalDateTime;
import java.util.Arrays; import java.util.Arrays;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
@ -14,11 +15,14 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.opentcs.common.LoopbackAdapterConstants; import org.opentcs.common.LoopbackAdapterConstants;
import org.opentcs.customizations.kernel.KernelExecutor; import org.opentcs.customizations.kernel.KernelExecutor;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Pose; import org.opentcs.data.model.Pose;
import org.opentcs.data.model.Triple; import org.opentcs.data.model.Triple;
import org.opentcs.data.model.Vehicle; import org.opentcs.data.model.Vehicle;
@ -44,6 +48,7 @@ import org.opentcs.kc.udp.agv.param.function.af.LocationStatusInfo;
import org.opentcs.kc.udp.agv.param.function.af.QueryRobotStatusRsp; import org.opentcs.kc.udp.agv.param.function.af.QueryRobotStatusRsp;
import org.opentcs.kc.udp.agv.param.function.b0.QueryCargoStatusRsp; import org.opentcs.kc.udp.agv.param.function.b0.QueryCargoStatusRsp;
import org.opentcs.kc.udp.agv.param.function.x17.QueryRobotRunStatusRsp; import org.opentcs.kc.udp.agv.param.function.x17.QueryRobotRunStatusRsp;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.util.ExplainedBoolean; import org.opentcs.util.ExplainedBoolean;
import org.opentcs.virtualvehicle.VelocityController.WayEntry; import org.opentcs.virtualvehicle.VelocityController.WayEntry;
import org.slf4j.Logger; import org.slf4j.Logger;
@ -113,25 +118,32 @@ public class LoopbackCommunicationAdapter
*/ */
private boolean initialized; private boolean initialized;
/** /**
* 上报截止时间 * 0xAF上报截止时间.
*/ */
private long deadline; private long sub0xafDeadline;
/** /**
* 上报间隔时间/ms * 0xB0上报截止时间.
*/ */
private long intervalTime; private long sub0xb0Deadline;
// /** /**
// * AGV IP * 创建线程
// */ */
// private final String IP; private final ExecutorService messageProcessingPool = new ThreadPoolExecutor(
// /** 4,
// * AGV 端口 8,
// */ 60L,
// private final int PORT; TimeUnit.MILLISECONDS,
// /** new LinkedBlockingQueue<>(100),
// * AGV AUTHORIZE_CODE new ThreadPoolExecutor.CallerRunsPolicy()
// */ );
// private final String AUTHORIZE_CODE; /**
* 订阅状态
*/
private static boolean SUBSCRIBE_STATUS;
/**
* 最后经过点位
*/
private static String LAST_PASSED_POINT;
/** /**
* Creates a new instance. * Creates a new instance.
@ -193,41 +205,52 @@ public class LoopbackCommunicationAdapter
@Override @Override
public void propertyChange(PropertyChangeEvent evt) { public void propertyChange(PropertyChangeEvent evt) {
//调用父类的 propertyChange 方法处理事件
super.propertyChange(evt); super.propertyChange(evt);
//如果事件源不是 LoopbackVehicleModel 类型直接返回
if (!((evt.getSource()) instanceof LoopbackVehicleModel)) { if (!((evt.getSource()) instanceof LoopbackVehicleModel)) {
return; return;
} }
//如果事件属性名为 LOAD_HANDLING_DEVICES
if (Objects.equals( if (Objects.equals(
evt.getPropertyName(), evt.getPropertyName(),
VehicleProcessModel.Attribute.LOAD_HANDLING_DEVICES.name() VehicleProcessModel.Attribute.LOAD_HANDLING_DEVICES.name()
)) { )) {
if (!getProcessModel().getLoadHandlingDevices().isEmpty() if (!getProcessModel().getLoadHandlingDevices().isEmpty()
&& getProcessModel().getLoadHandlingDevices().get(0).isFull()) { && getProcessModel().getLoadHandlingDevices().get(0).isFull()) {
//检查负载处理设备是否为空且第一个设备是否满载更新负载状态为 FULL 并设置车辆长度为加载状态下的长度
loadState = LoadState.FULL; loadState = LoadState.FULL;
getProcessModel().setBoundingBox( getProcessModel().setBoundingBox(
getProcessModel().getBoundingBox().withLength(configuration.vehicleLengthLoaded()) getProcessModel().getBoundingBox().withLength(configuration.vehicleLengthLoaded())
); );
} }
else { else {
//否则更新负载状态为 EMPTY 并设置车辆长度为未加载状态下的长度
loadState = LoadState.EMPTY; loadState = LoadState.EMPTY;
getProcessModel().setBoundingBox( getProcessModel().setBoundingBox(
getProcessModel().getBoundingBox().withLength(configuration.vehicleLengthUnloaded()) getProcessModel().getBoundingBox().withLength(configuration.vehicleLengthUnloaded())
); );
} }
} }
//如果事件属性名为 SINGLE_STEP_MODE
if (Objects.equals( if (Objects.equals(
evt.getPropertyName(), evt.getPropertyName(),
LoopbackVehicleModel.Attribute.SINGLE_STEP_MODE.name() LoopbackVehicleModel.Attribute.SINGLE_STEP_MODE.name()
)) { )) {
// When switching from single step mode to automatic mode and there are commands to be // When switching from single step mode to automatic mode and there are commands to be
// processed, ensure that we start/continue processing them. // processed, ensure that we start/continue processing them.
//如果单步模式关闭待处理命令队列非空且模拟未运行则启动车辆模拟
if (!getProcessModel().isSingleStepModeEnabled() if (!getProcessModel().isSingleStepModeEnabled()
&& !getSentCommands().isEmpty() && !getSentCommands().isEmpty()
&& !isSimulationRunning) { && !isSimulationRunning) {
//标记模拟正在运行
isSimulationRunning = true; isSimulationRunning = true;
//提交任务到线程池执行队列中的第一个命令
((ExecutorService) getExecutor()).submit( ((ExecutorService) getExecutor()).submit(
() -> startVehicleSimulation(getSentCommands().peek()) () -> startVehicle(getSentCommands().peek())
); );
} }
} }
@ -261,6 +284,7 @@ public class LoopbackCommunicationAdapter
System.out.println(cmd); System.out.println(cmd);
System.out.println("send cmd print start"); System.out.println("send cmd print start");
// SubRobotStatue.command();
//订单ID //订单ID
String orderName = cmd.getTransportOrder().getName(); String orderName = cmd.getTransportOrder().getName();
@ -283,29 +307,40 @@ public class LoopbackCommunicationAdapter
System.out.println("sourcePoint:" + sourcePoint); System.out.println("sourcePoint:" + sourcePoint);
//下发终点 //下发终点
String destinationPoint = cmd.getStep().getDestinationPoint().getName(); Point destinationPoint = cmd.getStep().getDestinationPoint();
System.out.println("destinationPoint:" + destinationPoint); //获取点类型
String pointProperty = destinationPoint.getProperty(LoopbackAdapterConstants.POINT_TYPE);
System.out.println("destinationPoint_tcs:point:" + pointProperty);
String destinationPointName = cmd.getStep().getDestinationPoint().getName();
System.out.println("destinationPointName:" + destinationPointName);
//拼接起点终点字符串转为Integer类型获取唯一pathID
Integer pathID = Integer.parseInt(sourcePoint + destinationPoint);
System.out.println("pathID:" + pathID);
System.out.println("send cmd print end"); System.out.println("send cmd print end");
//订阅0xAF
// sub0xAF();
//AGV控制器执行命令 //AGV控制器执行命令
HybridNavigation.command("1", sourcePoint, destinationPoint, operation); HybridNavigation.command(orderName, sourcePoint, destinationPointName, operation);
// Start the simulation task if we're not in single step mode and not simulating already. //检查当前车辆模型是否处于单步模式且未运行若满足条件则设置运行状态为true
if (!getProcessModel().isSingleStepModeEnabled() if (!getProcessModel().isSingleStepModeEnabled()
&& !isSimulationRunning) { && !isSimulationRunning) {
isSimulationRunning = true; isSimulationRunning = true;
// The command is added to the sent queue after this method returns. Therefore
// we have to explicitly start the simulation like this. if (LAST_PASSED_POINT == null) {
//设置最后经过点为起点
LAST_PASSED_POINT = sourcePoint;
//设置订阅状态为true
SUBSCRIBE_STATUS = true;
}
sub0xAF();
// 展示模拟车辆
if (getSentCommands().isEmpty()) { if (getSentCommands().isEmpty()) {
((ExecutorService) getExecutor()).submit(() -> startVehicleSimulation(cmd)); ((ExecutorService) getExecutor()).submit(() -> startVehicle(cmd));
} }
else { else {
((ExecutorService) getExecutor()).submit( ((ExecutorService) getExecutor()).submit(
() -> startVehicleSimulation(getSentCommands().peek()) () -> startVehicle(getSentCommands().peek())
); );
} }
} }
@ -318,49 +353,13 @@ public class LoopbackCommunicationAdapter
@Override @Override
public void processMessage(Object message) { public void processMessage(Object message) {
if (message instanceof String) {
//测试使用
getProcessModel().setEnergyLevel(66);
System.out.println(message);
}
else if (message instanceof QueryCargoStatusRsp) {
//0xB0响应结果
QueryCargoStatusRsp queryCargoStatusRsp = (QueryCargoStatusRsp) message;
if (queryCargoStatusRsp.isCargo == 0) { if (message instanceof byte[]) {
this.loadState = LoadState.EMPTY; updateVehicleModel(message);
} else {
this.loadState = LoadState.FULL;
}
}
else if (message instanceof QueryRobotStatusRsp) {
System.out.println("test success");
//0xAF响应结果
QueryRobotStatusRsp queryRobotStatusRsp = (QueryRobotStatusRsp) message;
//电量
float batteryPercentage = queryRobotStatusRsp.batteryStatusInfo.batteryPercentage;
getProcessModel().setEnergyLevel(((int)batteryPercentage * 100));
//充电状态
byte chargingState = queryRobotStatusRsp.batteryStatusInfo.chargingState;
if (chargingState == 1) {
getProcessModel().setState(Vehicle.State.CHARGING);
}
//设置车辆位置(最后一次通过的点)
// String lastPointName = queryRobotStatusRsp.locationStatusInfo.lastPassPointId.toString();
// getProcessModel().setPosition(lastPointName);
////设置车辆姿势(官方弃用设置车辆精确位置)
long positionX = (long)queryRobotStatusRsp.locationStatusInfo.globalX;
long positionY = (long)queryRobotStatusRsp.locationStatusInfo.globalY;
Triple triple = new Triple(positionX, positionY, 0);
double positionAngle = queryRobotStatusRsp.locationStatusInfo.absoluteDirecAngle;
getProcessModel().setPose(new Pose(triple, positionAngle));
} }
else if (message instanceof HashMap<?, ?>) { else if (message instanceof HashMap<?, ?>) {
HashMap<?,?> msg = ((HashMap<?, ?>) message); //todo 测试代码----成功
HashMap<?, ?> msg = (HashMap<?, ?>) message;
getProcessModel().setEnergyLevel((int) msg.get("energy")); getProcessModel().setEnergyLevel((int) msg.get("energy"));
getProcessModel().setState(Vehicle.State.EXECUTING); getProcessModel().setState(Vehicle.State.EXECUTING);
@ -371,21 +370,83 @@ public class LoopbackCommunicationAdapter
double positionAngle = (double) msg.get("positionAngle"); double positionAngle = (double) msg.get("positionAngle");
getProcessModel().setPose(new Pose(triple, positionAngle)); getProcessModel().setPose(new Pose(triple, positionAngle));
} }
}
//上报自动续订操作 private void updateVehicleModel(Object message) {
// renewalSubscribe(); try {
byte[] body = (byte[])message;
RcvEventPackage rcv = new RcvEventPackage(body[22], body);
if (body[21] == (byte) 0xAF) {
System.out.println("0xAF sub success");
//AGV状态订阅
QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
System.out.println();
//电量--目前无电量返回设置一个随机值
float batteryPercentage = queryRobotStatusRsp.batteryStatusInfo.batteryPercentage;
getProcessModel().setEnergyLevel(89);
//设置AGV最后一个点位置,不设置最后经过点opentcs无法调度
String vehicleNowPosition = getProcessModel().getPosition();
String lastPassPointId = (queryRobotStatusRsp.locationStatusInfo.lastPassPointId).toString();
if (vehicleNowPosition == null || !vehicleNowPosition.equals(lastPassPointId)) {
initVehiclePosition(lastPassPointId);
}
//设置车辆姿势(官方弃用设置车辆精确位置)-------------------目前车辆返回位置为固定值
/* long positionX = (long) queryRobotStatusRsp.locationStatusInfo.globalX;
long positionY = (long) queryRobotStatusRsp.locationStatusInfo.globalY;
Triple triple = new Triple(positionX, positionY, 0);
double positionAngle = queryRobotStatusRsp.locationStatusInfo.absoluteDirecAngle;
LocalDateTime now = LocalDateTime.now();
System.out.println(now + "[positionX:" + positionX + "] [positionY:" + positionY + "] [positionAngle:" + positionAngle + "]");
getProcessModel().setPose(new Pose(triple, positionAngle));*/
//到期续订
renewalSubscribe0xAF();
} else if (body[21] == (byte) 0xB0) {
System.out.println("0xB0 sub success");
//载货状态订阅
QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes());
if (queryCargoStatusRsp.isCargo == 0) {
this.loadState = LoadState.EMPTY;
}
else {
this.loadState = LoadState.FULL;
}
//到期续订
renewalSubscribe0xB0();
}
} catch (Exception e) {
throw new RuntimeException("processMessage_messageExecutorPool:" + e);
}
} }
/** /**
* 订阅到期自动续订 * 订阅到期自动续订0xAF.
*/ */
private void renewalSubscribe() { private void renewalSubscribe0xAF() {
Date now = new Date(); Date now = new Date();
if (now.getTime() + intervalTime >= deadline) { if (sub0xafDeadline - now.getTime() <= SubRobotStatue.intervalTime && SUBSCRIBE_STATUS) {
//开启AGV订阅监听 (0xAF & 0xB0) sub0xAF();
SubRobotStatue.command(); }
SubCargoStatus.command(); }
/**
* 订阅到期自动续订0xB0.
*/
private void renewalSubscribe0xB0() {
Date now = new Date();
if (sub0xb0Deadline - now.getTime() <= SubCargoStatus.intervalTime && SUBSCRIBE_STATUS) {
sub0xB0();
} }
} }
@ -446,11 +507,8 @@ public class LoopbackCommunicationAdapter
@Override @Override
protected synchronized void connectVehicle() { protected synchronized void connectVehicle() {
String ip = requireNonNull(vehicle.getProperties().get(LoopbackAdapterConstants.AGV_IP), "AGV IP NOT NULL"); // getProcessModel().setCommAdapterConnected(true);
Integer port = Integer.parseInt(requireNonNull(vehicle.getProperties().get(LoopbackAdapterConstants.AGV_PORT), "AGV PORT NOT NULL")); initAGV();
String authorizeCode = requireNonNull(vehicle.getProperties().get(LoopbackAdapterConstants.AGV_AUTHORIZE_CODE), "AGV AUTHORIZE_CODE NOT NULL");
getProcessModel().setCommAdapterConnected(true);
// initAGV();
} }
@Override @Override
@ -491,6 +549,36 @@ public class LoopbackCommunicationAdapter
} }
} }
/**
* 执行车辆移动指令
*
* @param command 移动指令
*/
private void startVehicle(MovementCommand command) {
LOG.debug("-Starting vehicle for command: {}", command);
Step step = command.getStep();
getProcessModel().setState(Vehicle.State.EXECUTING);
if (step.getPath() == null) {
LOG.debug("-Starting operation...");
//动作执行待完成
operationExec(command);
} else {
getProcessModel().getVelocityController().addWayEntry(
new WayEntry(
step.getPath().getLength(),
maxVelocity(step),
step.getDestinationPoint().getName(),
step.getVehicleOrientation()
)
);
LOG.debug("-Starting movement ...");
movementExec(command);
}
}
private void startVehicleSimulation(MovementCommand command) { private void startVehicleSimulation(MovementCommand command) {
LOG.debug("Starting vehicle simulation for command: {}", command); LOG.debug("Starting vehicle simulation for command: {}", command);
Step step = command.getStep(); Step step = command.getStep();
@ -529,12 +617,54 @@ public class LoopbackCommunicationAdapter
: step.getPath().getMaxVelocity(); : step.getPath().getMaxVelocity();
} }
/**
* 执行运行指令.
*
* @param command 要执行的命令
*/
private void movementExec(MovementCommand command) {
//检查当前车辆模型的速度控制器是否有路径条目若无则直接返回
if (!getProcessModel().getVelocityController().hasWayEntries()) {
return;
}
//获取AGV最终经过点
String currentPoint = getProcessModel().getPosition() != null ? getProcessModel().getPosition() : "";
//获取当前路径条目并推进时间步长检查是否仍处于同一路径条目
if (currentPoint.equals(LAST_PASSED_POINT)) {
//若是则重新调度当前方法以继续模拟
getExecutor().schedule(
() -> movementExec(command),
SIMULATION_PERIOD,
TimeUnit.MILLISECONDS
);
} else {
LAST_PASSED_POINT = currentPoint;
//若否更新车辆位置为上一路径条目的目标点并根据命令是否有操作决定进入操作模拟或完成命令并模拟下一个命令
LOG.debug("-Movement finished.");
if (!command.hasEmptyOperation()) {
//执行AGV动作
LOG.debug("-Starting operation...");
operationExec(command);
} else {
//完成当前命令
finishMoveCmd(command);
//执行下一个命令
nextCommand();
}
}
}
/** /**
* Simulate the movement part of a MovementCommand. * Simulate the movement part of a MovementCommand.
* *
* @param command The command to simulate. * @param command The command to simulate.
*/ */
private void movementSimulation(MovementCommand command) { private void movementSimulation(MovementCommand command) {
//检查当前车辆模型的速度控制器是否有路径条目若无则直接返回
if (!getProcessModel().getVelocityController().hasWayEntries()) { if (!getProcessModel().getVelocityController().hasWayEntries()) {
return; return;
} }
@ -543,7 +673,9 @@ public class LoopbackCommunicationAdapter
getProcessModel().getVelocityController().advanceTime(getSimulationTimeStep()); getProcessModel().getVelocityController().advanceTime(getSimulationTimeStep());
WayEntry currentWayEntry = getProcessModel().getVelocityController().getCurrentWayEntry(); WayEntry currentWayEntry = getProcessModel().getVelocityController().getCurrentWayEntry();
//if we are still on the same way entry then reschedule to do it again //if we are still on the same way entry then reschedule to do it again
//获取当前路径条目并推进时间步长检查是否仍处于同一路径条目
if (prevWayEntry == currentWayEntry) { if (prevWayEntry == currentWayEntry) {
//若是则重新调度当前方法以继续模拟
getExecutor().schedule( getExecutor().schedule(
() -> movementSimulation(command), () -> movementSimulation(command),
SIMULATION_PERIOD, SIMULATION_PERIOD,
@ -553,6 +685,7 @@ public class LoopbackCommunicationAdapter
else { else {
//if the way enties are different then we have finished this step //if the way enties are different then we have finished this step
//and we can move on. //and we can move on.
//若否更新车辆位置为上一路径条目的目标点并根据命令是否有操作决定进入操作模拟或完成命令并模拟下一个命令
getProcessModel().setPosition(prevWayEntry.getDestPointName()); getProcessModel().setPosition(prevWayEntry.getDestPointName());
LOG.debug("Movement simulation finished."); LOG.debug("Movement simulation finished.");
if (!command.hasEmptyOperation()) { if (!command.hasEmptyOperation()) {
@ -570,8 +703,18 @@ public class LoopbackCommunicationAdapter
} }
} }
/**
* 执行移动命令的操作部分
*
* @param command 要执行的命令
*/
private void operationExec(MovementCommand command) {
}
/** /**
* Simulate the operation part of a movement command. * Simulate the operation part of a movement command.
* 模拟移动命令的操作部分
* *
* @param command The command to simulate. * @param command The command to simulate.
* @param timePassed The amount of time passed since starting the simulation. * @param timePassed The amount of time passed since starting the simulation.
@ -626,6 +769,7 @@ public class LoopbackCommunicationAdapter
/** /**
* Simulate recharging the vehicle. * Simulate recharging the vehicle.
* 模拟为车辆充电
* *
* @param rechargePosition The vehicle position where the recharge simulation was started. * @param rechargePosition The vehicle position where the recharge simulation was started.
* @param rechargePercentage The recharge percentage of the vehicle while it is charging. * @param rechargePercentage The recharge percentage of the vehicle while it is charging.
@ -671,14 +815,43 @@ public class LoopbackCommunicationAdapter
+ (float) (configuration.rechargePercentagePerSecond() / 1000.0) * SIMULATION_PERIOD; + (float) (configuration.rechargePercentagePerSecond() / 1000.0) * SIMULATION_PERIOD;
} }
/**
* 结束移动命令
* @param command 指令
*/
private void finishMoveCmd(MovementCommand command) {
//检查已发送命令队列的大小是否小于等于1且未发送命令队列是否为空
if (getSentCommands().size() <= 1 && getUnsentCommands().isEmpty()) {
System.out.println("-getSentCommands <= 1 && getUnsentCommands is null");
getProcessModel().setState(Vehicle.State.IDLE);
//清除订单对应唯一ID
HybridNavigation.delUniqueOrderID(command);
}
//如果传入指令和移动指令队列第一条数据相同
if (Objects.equals(getSentCommands().peek(), command)) {
// 完成当前任务
getProcessModel().commandExecuted(getSentCommands().poll());
} else {
//
LOG.warn(
"-{}: Exec command not oldest in sent queue: {} != {}",
getName(),
command,
getSentCommands().peek()
);
}
}
private void finishMovementCommand(MovementCommand command) { private void finishMovementCommand(MovementCommand command) {
//Set the vehicle state to idle //Set the vehicle state to idle
if (getSentCommands().size() <= 1 && getUnsentCommands().isEmpty()) { if (getSentCommands().size() <= 1 && getUnsentCommands().isEmpty()) {
getProcessModel().setState(Vehicle.State.IDLE); getProcessModel().setState(Vehicle.State.IDLE);
} }
if (Objects.equals(getSentCommands().peek(), command)) { if (Objects.equals(getSentCommands().peek(), command)) {
// Let the comm adapter know we have finished this command. // Let the comm adapter know we have finished this command. 让通信适配器知道我们已经完成了这个命令
getProcessModel().commandExecuted(getSentCommands().poll()); getProcessModel().commandExecuted(getSentCommands().poll());
// HybridNavigation.delUniqueOrderID(command);
} }
else { else {
LOG.warn( LOG.warn(
@ -690,6 +863,22 @@ public class LoopbackCommunicationAdapter
} }
} }
void nextCommand() {
if (getSentCommands().isEmpty() || getProcessModel().isSingleStepModeEnabled()) {
LOG.debug("Vehicle exec is done.");
getProcessModel().setState(Vehicle.State.IDLE);
isSimulationRunning = false;
LAST_PASSED_POINT = null;
SUBSCRIBE_STATUS = false;
}
else {
LOG.debug("Triggering exec for next command: {}", getSentCommands().peek());
((ExecutorService) getExecutor()).submit(
() -> startVehicle(getSentCommands().peek())
);
}
}
void simulateNextCommand() { void simulateNextCommand() {
if (getSentCommands().isEmpty() || getProcessModel().isSingleStepModeEnabled()) { if (getSentCommands().isEmpty() || getProcessModel().isSingleStepModeEnabled()) {
LOG.debug("Vehicle simulation is done."); LOG.debug("Vehicle simulation is done.");
@ -727,47 +916,133 @@ public class LoopbackCommunicationAdapter
*/ */
private void initAGV() { private void initAGV() {
if (true) {
//0xAF获取AGV状态 //0xAF获取AGV状态
System.out.println("=================---initAGV_0xAF");
QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command(); QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command();
if (qryRobotStatusRsp == null) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("initAGV 0xAF response is null");
}
//设置订阅时间和上报间隔 //开启0xAF订阅
Date now = new Date(); sub0xAF();
deadline = now.getTime() + 1000;
intervalTime = 100;
//开启AGV订阅监听 (0xAF & 0xB0)
SubRobotStatue.command(); //开启0xB0订阅
SubCargoStatus.command(); // sub0xB0()
// //设置车辆姿势(官方弃用设置车辆精确位置)-------------------目前车辆返回位置为固定值
// long positionX = (long) qryRobotStatusRsp.locationStatusInfo.globalX;
// long positionY = (long) qryRobotStatusRsp.locationStatusInfo.globalY;
// Triple triple = new Triple(positionX, positionY, 0);
// double positionAngle = qryRobotStatusRsp.locationStatusInfo.absoluteDirecAngle;
// getProcessModel().setPose(new Pose(triple, positionAngle));
//3 查询机器人运行状态命令码0x17等待机器人定位状态为定位完成
System.out.println("=================---initAGV_0x17");
QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command();
if (qryRobotRunStatusRsp == null) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("initAGV 0x17 response is null");
}
if (qryRobotRunStatusRsp.robotLocalizationState == 0) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("AGV定位失败请执行手动定位");
}
else if (qryRobotRunStatusRsp.robotLocalizationState == 2) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("AGV定位中,请稍后再试");
}
//5 切换成自动模式命令码0x03变量NaviControl 修改为1
System.out.println();
System.out.println("=================---initAGV_0x03-----111111");
SwitchAutomaticMode.command();
getProcessModel().setState(Vehicle.State.IDLE);
//打开通讯适配器连接
getProcessModel().setCommAdapterConnected(true);
} else {
//0xAF获取AGV状态
System.out.println("=================---initAGV_0xAF");
QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command();
if (qryRobotStatusRsp == null) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("initAGV 0xAF response is null");
}
//开启0xAF订阅
sub0xAF();
//开启0xB0订阅
sub0xB0();
//1 切换定位为手动模式命令码0x03变量NaviControl 修改为0 //1 切换定位为手动模式命令码0x03变量NaviControl 修改为0
System.out.println();
System.out.println("=================---initAGV_0x03-----000000");
SwitchManualMode.command(); SwitchManualMode.command();
getProcessModel().setState(Vehicle.State.UNAVAILABLE);
//设置AGV最后一个点位置
String lastPassPointId = (qryRobotStatusRsp.locationStatusInfo.lastPassPointId).toString();
initVehiclePosition(lastPassPointId);
//2 执行机器人手动定位 命令码0x14
System.out.println("=================---initAGV_0x14");
LocationStatusInfo locationStatusInfo = qryRobotStatusRsp.locationStatusInfo; LocationStatusInfo locationStatusInfo = qryRobotStatusRsp.locationStatusInfo;
double agvX = locationStatusInfo.globalX; double agvX = locationStatusInfo.globalX;
double agvY = locationStatusInfo.globalY; double agvY = locationStatusInfo.globalY;
double agvAngle = locationStatusInfo.absoluteDirecAngle; double agvAngle = locationStatusInfo.absoluteDirecAngle;
//3 查询机器人运行状态命令码0x17等待机器人定位状态为定位完成
QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command();
if (qryRobotRunStatusRsp.robotLocalizationState == 0) {
//2 执行机器人手动定位 命令码0x14
ManualPosition.command(agvX, agvY, agvAngle); ManualPosition.command(agvX, agvY, agvAngle);
throw new RuntimeException("AGV定位失败执行手动定位中"); //3 查询机器人运行状态命令码0x17等待机器人定位状态为定位完成
System.out.println("=================---initAGV_0x17");
QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command();
} else if (qryRobotRunStatusRsp.robotLocalizationState == 2) { if (qryRobotRunStatusRsp == null) {
throw new RuntimeException("AGV定位中"); getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("initAGV 0x17 response is null");
}
if (qryRobotRunStatusRsp.robotLocalizationState == 0) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("AGV定位失败执行手动定位中");
}
else if (qryRobotRunStatusRsp.robotLocalizationState == 2) {
getProcessModel().setCommAdapterConnected(false);
throw new RuntimeException("AGV定位中,请稍后再试");
} }
//4 确认初始位置命令码0x1F //4 确认初始位置命令码0x1F
System.out.println("=================---initAGV_0x1F");
ConfirmRelocation.commnd(); ConfirmRelocation.commnd();
//5 切换成自动模式命令码0x03变量NaviControl 修改为1 //5 切换成自动模式命令码0x03变量NaviControl 修改为1
System.out.println("=================---initAGV_0x03-----111111");
SwitchAutomaticMode.command(); SwitchAutomaticMode.command();
getProcessModel().setState(Vehicle.State.IDLE);
//打开通讯适配器连接 //打开通讯适配器连接
getProcessModel().setCommAdapterConnected(true); getProcessModel().setCommAdapterConnected(true);
} }
} }
private void sub0xAF(){
messageProcessingPool.submit(() -> {
Date now = new Date();
sub0xafDeadline = now.getTime() + 10000;
SubRobotStatue.command();
});
}
private void sub0xB0(){
messageProcessingPool.submit(() -> {
Date now = new Date();
sub0xb0Deadline = now.getTime() + 10000;
SubCargoStatus.command();
});
}
}

View File

@ -58,6 +58,11 @@ public class LoopbackVehicleModelTO
return singleStepModeEnabled; return singleStepModeEnabled;
} }
/**
* 设置单步模式已启用.
* @param singleStepModeEnabled 启用单步模式
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setSingleStepModeEnabled(boolean singleStepModeEnabled) { public LoopbackVehicleModelTO setSingleStepModeEnabled(boolean singleStepModeEnabled) {
this.singleStepModeEnabled = singleStepModeEnabled; this.singleStepModeEnabled = singleStepModeEnabled;
return this; return this;
@ -67,6 +72,11 @@ public class LoopbackVehicleModelTO
return loadOperation; return loadOperation;
} }
/**
* 设置装载操作.
* @param loadOperation 状态
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setLoadOperation(String loadOperation) { public LoopbackVehicleModelTO setLoadOperation(String loadOperation) {
this.loadOperation = loadOperation; this.loadOperation = loadOperation;
return this; return this;
@ -76,6 +86,11 @@ public class LoopbackVehicleModelTO
return unloadOperation; return unloadOperation;
} }
/**
* 设置卸载操作.
* @param unloadOperation 状态
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setUnloadOperation(String unloadOperation) { public LoopbackVehicleModelTO setUnloadOperation(String unloadOperation) {
this.unloadOperation = unloadOperation; this.unloadOperation = unloadOperation;
return this; return this;
@ -85,6 +100,11 @@ public class LoopbackVehicleModelTO
return operatingTime; return operatingTime;
} }
/**
* 设置运行时间.
* @param operatingTime 时间戳
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setOperatingTime(int operatingTime) { public LoopbackVehicleModelTO setOperatingTime(int operatingTime) {
this.operatingTime = operatingTime; this.operatingTime = operatingTime;
return this; return this;
@ -94,6 +114,11 @@ public class LoopbackVehicleModelTO
return maxAcceleration; return maxAcceleration;
} }
/**
* 设置最大加速度.
* @param maxAcceleration
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setMaxAcceleration(int maxAcceleration) { public LoopbackVehicleModelTO setMaxAcceleration(int maxAcceleration) {
this.maxAcceleration = maxAcceleration; this.maxAcceleration = maxAcceleration;
return this; return this;
@ -103,6 +128,11 @@ public class LoopbackVehicleModelTO
return maxDeceleration; return maxDeceleration;
} }
/**
* 设置最大减速.
* @param maxDeceleration
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setMaxDeceleration(int maxDeceleration) { public LoopbackVehicleModelTO setMaxDeceleration(int maxDeceleration) {
this.maxDeceleration = maxDeceleration; this.maxDeceleration = maxDeceleration;
return this; return this;
@ -112,6 +142,11 @@ public class LoopbackVehicleModelTO
return maxFwdVelocity; return maxFwdVelocity;
} }
/**
* 设置最大前驱速度.
* @param maxFwdVelocity
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setMaxFwdVelocity(int maxFwdVelocity) { public LoopbackVehicleModelTO setMaxFwdVelocity(int maxFwdVelocity) {
this.maxFwdVelocity = maxFwdVelocity; this.maxFwdVelocity = maxFwdVelocity;
return this; return this;
@ -121,6 +156,11 @@ public class LoopbackVehicleModelTO
return maxRevVelocity; return maxRevVelocity;
} }
/**
* 设置最大速度.
* @param maxRevVelocity
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setMaxRevVelocity(int maxRevVelocity) { public LoopbackVehicleModelTO setMaxRevVelocity(int maxRevVelocity) {
this.maxRevVelocity = maxRevVelocity; this.maxRevVelocity = maxRevVelocity;
return this; return this;
@ -130,6 +170,11 @@ public class LoopbackVehicleModelTO
return vehiclePaused; return vehiclePaused;
} }
/**
* 将车辆设置为暂停.
* @param vehiclePaused
* @return LoopbackVehicleModelTO
*/
public LoopbackVehicleModelTO setVehiclePaused(boolean vehiclePaused) { public LoopbackVehicleModelTO setVehiclePaused(boolean vehiclePaused) {
this.vehiclePaused = vehiclePaused; this.vehiclePaused = vehiclePaused;
return this; return this;

View File

@ -18,7 +18,7 @@ public interface GuestUserCredentials {
/** /**
* 主机IP * 主机IP
*/ */
String IP = "192.168.0.106"; String IP = "192.168.124.111";
/** /**
* 内核开放端口 * 内核开放端口
*/ */

View File

@ -53,5 +53,9 @@ public interface LoopbackAdapterConstants {
* AGV 端口 * AGV 端口
*/ */
String AGV_PORT = "AGV:PORT"; String AGV_PORT = "AGV:PORT";
/**
* 定制点位类型1=WMS请求点位
*/
String POINT_TYPE = "tcs:point";
} }

View File

@ -56,18 +56,19 @@ public class CaffeineUtil {
} }
public static synchronized byte[] getUUID() { public static synchronized byte[] getUUID() {
AtomicInteger uuid = cacheUUID.getIfPresent("UUID"); AtomicInteger uuid = cacheUUID.getIfPresent("UUID");
if (uuid == null) { if (uuid == null) {
//transationId 从1 开始0留给心跳变量这样就固定报文了 //transationId 从1 开始0留给心跳变量这样就固定报文了
cacheUUID.put("UUID", new AtomicInteger(1)); cacheUUID.put("UUID", new AtomicInteger(1));
return ByteUtils.intToBytes(1); return ByteUtils.intToBytes(1);
}else { }
else {
if (uuid.get() >= 32000) { if (uuid.get() >= 32000) {
cacheUUID.put("UUID", new AtomicInteger(1)); cacheUUID.put("UUID", new AtomicInteger(1));
return ByteUtils.intToBytes(1); return ByteUtils.intToBytes(1);
}else { }
else {
return ByteUtils.intToBytes(uuid.incrementAndGet()); return ByteUtils.intToBytes(uuid.incrementAndGet());
} }
} }
@ -79,11 +80,13 @@ public class CaffeineUtil {
//transationId 从1 开始0留给心跳变量这样就固定报文了 //transationId 从1 开始0留给心跳变量这样就固定报文了
cacheUUID.put("AGVUUID", new AtomicInteger(1)); cacheUUID.put("AGVUUID", new AtomicInteger(1));
return ByteUtils.intToBytesS(1); return ByteUtils.intToBytesS(1);
}else { }
else {
if (agvuuid.get() >= 32000) { if (agvuuid.get() >= 32000) {
cacheUUID.put("AGVUUID", new AtomicInteger(1)); cacheUUID.put("AGVUUID", new AtomicInteger(1));
return ByteUtils.intToBytesS(1); return ByteUtils.intToBytesS(1);
}else { }
else {
return ByteUtils.intToBytesS(agvuuid.incrementAndGet()); return ByteUtils.intToBytesS(agvuuid.incrementAndGet());
} }
} }

View File

@ -12,7 +12,8 @@ public interface Const {
public static final String SERVER = "127.0.0.1"; public static final String SERVER = "127.0.0.1";
public static void main(String[] args) { public static void main(String[] args) {
String s = "123, 34, 104, 101, 97, 100, 101, 114, 34, 58, 123, 34, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 73, 100, 34, 58, 34, 50, 48, 50, 52, 48, 49, 48, 50, 49, 53, 52, 48, 50, 55, 95, 51, 100, 56, 49, 99, 34, 44, 34, 109, 101, 115, 115, 97, 103, 101, 84, 121, 112, 101, 34, 58, 51, 44, 34, 109, 101, 115, 115, 97, 103, 101, 78, 97, 109, 101, 34, 58, 34, 72, 101, 97, 114, 116, 66, 101, 97, 116, 34, 44, 34, 115, 101, 110, 100, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 58, 34, 50, 48, 50, 52, 45, 48, 49, 45, 48, 50, 32, 49, 53, 58, 52, 48, 58, 50, 55, 34, 125, 44, 34, 98, 111, 100, 121, 34, 58, 34, 49, 34, 44, 34, 114, 101, 116, 117, 114, 110, 115, 34, 58, 110, 117, 108, 108, 125"; String s
= "123, 34, 104, 101, 97, 100, 101, 114, 34, 58, 123, 34, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 73, 100, 34, 58, 34, 50, 48, 50, 52, 48, 49, 48, 50, 49, 53, 52, 48, 50, 55, 95, 51, 100, 56, 49, 99, 34, 44, 34, 109, 101, 115, 115, 97, 103, 101, 84, 121, 112, 101, 34, 58, 51, 44, 34, 109, 101, 115, 115, 97, 103, 101, 78, 97, 109, 101, 34, 58, 34, 72, 101, 97, 114, 116, 66, 101, 97, 116, 34, 44, 34, 115, 101, 110, 100, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 58, 34, 50, 48, 50, 52, 45, 48, 49, 45, 48, 50, 32, 49, 53, 58, 52, 48, 58, 50, 55, 34, 125, 44, 34, 98, 111, 100, 121, 34, 58, 34, 49, 34, 44, 34, 114, 101, 116, 117, 114, 110, 115, 34, 58, 110, 117, 108, 108, 125";
String[] split = s.split(","); String[] split = s.split(",");
System.out.println(split.length); System.out.println(split.length);
} }

View File

@ -3,11 +3,6 @@ package org.opentcs.kc.common;
import java.util.Arrays; import java.util.Arrays;
/**
* @Desc: "通用的数据传输底层类"
* @Author: caixiang
* @DATE: 2022/10/18 16:22
*/
public class Package { public class Package {
private byte[] body; private byte[] body;

View File

@ -1,24 +1,26 @@
/* /*
Copyright 2016 S7connector members (github.com/s7connector) * Copyright 2016 S7connector members (github.com/s7connector)
*
Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
You may obtain a copy of the License at * You may obtain a copy of the License at
*
http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
*
Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
limitations under the License. * limitations under the License.
*/ */
package org.opentcs.kc.common; package org.opentcs.kc.common;
/** /**
* The Class S7Exception is an exception related to S7 Communication * The Class S7Exception is an exception related to S7 Communication
*/ */
public final class ParseDataException extends RuntimeException { public final class ParseDataException
extends
RuntimeException {
/** The Constant serialVersionUID. */ /** The Constant serialVersionUID. */
private static final long serialVersionUID = -4761415733559374116L; private static final long serialVersionUID = -4761415733559374116L;

View File

@ -1,11 +1,6 @@
package org.opentcs.kc.common; package org.opentcs.kc.common;
/**
* @Desc: "通用的数据传输底层类"
* @Author: caixiang
* @DATE: 2022/10/18 16:22
*/
public class RcvPackage { public class RcvPackage {
private boolean isOk; private boolean isOk;
@ -17,6 +12,7 @@ public class RcvPackage {
this.value = value; this.value = value;
this.content = content; this.content = content;
} }
public RcvPackage() { public RcvPackage() {
} }
@ -37,7 +33,6 @@ public class RcvPackage {
} }
@Override @Override
public String toString() { public String toString() {
return "RcvPackage{" + return "RcvPackage{" +

View File

@ -6,16 +6,8 @@ import java.time.format.DateTimeFormatter;
import java.util.Random; import java.util.Random;
import java.util.UUID; import java.util.UUID;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/10/24 16:27
*/
public class Utils { public class Utils {
/**
* java生成随机数字15位数
* @return
*/
public static String getTransationId() { public static String getTransationId() {
String val = String.valueOf(System.currentTimeMillis()); String val = String.valueOf(System.currentTimeMillis());
Random random = new Random(); Random random = new Random();
@ -31,18 +23,15 @@ public class Utils {
* *
* @return * @return
*/ */
public static String getUUID(int len) public static String getUUID(int len) {
{ if (0 >= len) {
if(0 >= len)
{
return null; return null;
} }
String uuid = getUUID(); String uuid = getUUID();
StringBuffer str = new StringBuffer(); StringBuffer str = new StringBuffer();
for (int i = 0; i < len; i++) for (int i = 0; i < len; i++) {
{
str.append(uuid.charAt(i)); str.append(uuid.charAt(i));
} }
@ -55,23 +44,21 @@ public class Utils {
* *
* @return * @return
*/ */
public static String getUUID() public static String getUUID() {
{
return UUID.randomUUID().toString().replace("-", ""); return UUID.randomUUID().toString().replace("-", "");
} }
/* /*
type: * type:
1.返回的是这种格式2021-08-16 15:00:05 * 1.返回的是这种格式2021-08-16 15:00:05
2.返回的是这种格式20210816150021 * 2.返回的是这种格式20210816150021
*/ */
public static String getNowDate(Integer type) { public static String getNowDate(Integer type) {
if (type == 1) { if (type == 1) {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")); return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}else { }
else {
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
} }
} }

View File

@ -4,11 +4,6 @@ import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/4/1 17:32
*/
// 对数字和字节进行转换 假设数据存储是以大端模式存储的 // 对数字和字节进行转换 假设数据存储是以大端模式存储的
// byte: 字节类型 占8位二进制 00000000 // byte: 字节类型 占8位二进制 00000000
// char: 字符类型 占2个字节 16位二进制 byte[0] byte[1] // char: 字符类型 占2个字节 16位二进制 byte[0] byte[1]
@ -52,7 +47,7 @@ public class ByteUtil {
/** /**
* *
* 字符串转成16个字节的byte[] 不足16个字节前面填充0 * 字符串转成16个字节的byte[] 不足16个字节前面填充0
* */ */
public static byte[] stringTo16Byte(String input) { public static byte[] stringTo16Byte(String input) {
byte[] originalBytes = input.getBytes(StandardCharsets.UTF_8); byte[] originalBytes = input.getBytes(StandardCharsets.UTF_8);
ByteBuffer buffer = ByteBuffer.allocate(16); ByteBuffer buffer = ByteBuffer.allocate(16);
@ -84,7 +79,8 @@ public class ByteUtil {
if (ByteOrder.LITTLE_ENDIAN == byteOrder) { if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
//小端模式数据的高字节保存在内存的高地址中而数据的低字节保存在内存的低地址中 //小端模式数据的高字节保存在内存的高地址中而数据的低字节保存在内存的低地址中
return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE); return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE);
} else { }
else {
return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE); return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE);
} }
} }
@ -113,7 +109,8 @@ public class ByteUtil {
if (ByteOrder.LITTLE_ENDIAN == byteOrder) { if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
b[0] = (byte) (shortValue & 0xff); b[0] = (byte) (shortValue & 0xff);
b[1] = (byte) ((shortValue >> Byte.SIZE) & 0xff); b[1] = (byte) ((shortValue >> Byte.SIZE) & 0xff);
} else { }
else {
b[1] = (byte) (shortValue & 0xff); b[1] = (byte) (shortValue & 0xff);
b[0] = (byte) ((shortValue >> Byte.SIZE) & 0xff); b[0] = (byte) ((shortValue >> Byte.SIZE) & 0xff);
} }
@ -145,7 +142,8 @@ public class ByteUtil {
(bytes[1] & 0xFF) << 8 | // (bytes[1] & 0xFF) << 8 | //
(bytes[2] & 0xFF) << 16 | // (bytes[2] & 0xFF) << 16 | //
(bytes[3] & 0xFF) << 24; // (bytes[3] & 0xFF) << 24; //
} else { }
else {
return bytes[3] & 0xFF | // return bytes[3] & 0xFF | //
(bytes[2] & 0xFF) << 8 | // (bytes[2] & 0xFF) << 8 | //
(bytes[1] & 0xFF) << 16 | // (bytes[1] & 0xFF) << 16 | //
@ -183,7 +181,8 @@ public class ByteUtil {
(byte) ((intValue >> 24) & 0xFF) // (byte) ((intValue >> 24) & 0xFF) //
}; };
} else { }
else {
return new byte[]{ // return new byte[]{ //
(byte) ((intValue >> 24) & 0xFF), // (byte) ((intValue >> 24) & 0xFF), //
(byte) ((intValue >> 16) & 0xFF), // (byte) ((intValue >> 16) & 0xFF), //
@ -197,7 +196,8 @@ public class ByteUtil {
/** /**
* long转byte数组<br> * long转byte数组<br>
* 默认以小端序转换<br> * 默认以小端序转换<br>
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * from:
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
* *
* @param longValue long值 * @param longValue long值
* @return byte数组 * @return byte数组
@ -209,7 +209,8 @@ public class ByteUtil {
/** /**
* long转byte数组<br> * long转byte数组<br>
* 自定义端序<br> * 自定义端序<br>
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * from:
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
* *
* @param longValue long值 * @param longValue long值
* @param byteOrder 端序 * @param byteOrder 端序
@ -222,7 +223,8 @@ public class ByteUtil {
result[i] = (byte) (longValue & 0xFF); result[i] = (byte) (longValue & 0xFF);
longValue >>= Byte.SIZE; longValue >>= Byte.SIZE;
} }
} else { }
else {
for (int i = (result.length - 1); i >= 0; i--) { for (int i = (result.length - 1); i >= 0; i--) {
result[i] = (byte) (longValue & 0xFF); result[i] = (byte) (longValue & 0xFF);
longValue >>= Byte.SIZE; longValue >>= Byte.SIZE;
@ -234,7 +236,8 @@ public class ByteUtil {
/** /**
* byte数组转long<br> * byte数组转long<br>
* 默认以小端序转换<br> * 默认以小端序转换<br>
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * from:
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
* *
* @param bytes byte数组 * @param bytes byte数组
* @return long值 * @return long值
@ -246,7 +249,8 @@ public class ByteUtil {
/** /**
* byte数组转long<br> * byte数组转long<br>
* 自定义端序<br> * 自定义端序<br>
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * from:
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
* *
* @param bytes byte数组 * @param bytes byte数组
* @param byteOrder 端序 * @param byteOrder 端序
@ -259,7 +263,8 @@ public class ByteUtil {
values <<= Byte.SIZE; values <<= Byte.SIZE;
values |= (bytes[i] & 0xff); values |= (bytes[i] & 0xff);
} }
} else { }
else {
for (int i = 0; i < Long.BYTES; i++) { for (int i = 0; i < Long.BYTES; i++) {
values <<= Byte.SIZE; values <<= Byte.SIZE;
values |= (bytes[i] & 0xff); values |= (bytes[i] & 0xff);
@ -283,7 +288,8 @@ public class ByteUtil {
/** /**
* double转byte数组<br> * double转byte数组<br>
* 自定义端序<br> * 自定义端序<br>
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java * from:
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
* *
* @param doubleValue double值 * @param doubleValue double值
* @param byteOrder 端序 * @param byteOrder 端序
@ -336,13 +342,17 @@ public class ByteUtil {
public static byte[] numberToBytes(Number number, ByteOrder byteOrder) { public static byte[] numberToBytes(Number number, ByteOrder byteOrder) {
if (number instanceof Double) { if (number instanceof Double) {
return doubleToBytes((Double) number, byteOrder); return doubleToBytes((Double) number, byteOrder);
} else if (number instanceof Long) { }
else if (number instanceof Long) {
return longToBytes((Long) number, byteOrder); return longToBytes((Long) number, byteOrder);
} else if (number instanceof Integer) { }
else if (number instanceof Integer) {
return intToBytes((Integer) number, byteOrder); return intToBytes((Integer) number, byteOrder);
} else if (number instanceof Short) { }
else if (number instanceof Short) {
return shortToBytes((Short) number, byteOrder); return shortToBytes((Short) number, byteOrder);
} else { }
else {
return doubleToBytes(number.doubleValue(), byteOrder); return doubleToBytes(number.doubleValue(), byteOrder);
} }
} }

View File

@ -26,8 +26,10 @@ public class ByteUtils {
System.arraycopy(src, start, dest, 0, length); System.arraycopy(src, start, dest, 0, length);
return dest; return dest;
} }
/** /**
* float 类型的数值按照小端模式转换为字节数组 * float 类型的数值按照小端模式转换为字节数组
*
* @param value 要转换的 float * @param value 要转换的 float
* @return 转换后的字节数组 * @return 转换后的字节数组
*/ */
@ -41,8 +43,10 @@ public class ByteUtils {
} }
return bytes; return bytes;
} }
/** /**
* 将字节数组中从指定偏移位置开始的指定长度的字节转换为字符串 * 将字节数组中从指定偏移位置开始的指定长度的字节转换为字符串
*
* @param src 字节数组 * @param src 字节数组
* @param offset 起始偏移量 * @param offset 起始偏移量
* @param length 要转换的字节长度 * @param length 要转换的字节长度
@ -64,7 +68,8 @@ public class ByteUtils {
System.arraycopy(src, offset, subArray, 0, length); System.arraycopy(src, offset, subArray, 0, length);
// 使用 UTF-8 编码将字节数组转换为字符串 // 使用 UTF-8 编码将字节数组转换为字符串
return new String(subArray, "UTF-8"); return new String(subArray, "UTF-8");
} catch (Exception e) { }
catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return ""; return "";
} }
@ -117,6 +122,7 @@ public class ByteUtils {
/** /**
* 将字节数组按照小端模式转换为 short 类型 * 将字节数组按照小端模式转换为 short 类型
*
* @param src 字节数组 * @param src 字节数组
* @param offset 起始偏移量 * @param offset 起始偏移量
* @return 转换后的 short * @return 转换后的 short
@ -161,6 +167,7 @@ public class ByteUtils {
} }
return invert(arr); return invert(arr);
} }
public static Boolean toBoolean(byte[] bytes) { public static Boolean toBoolean(byte[] bytes) {
if (bytes.length == 0) { if (bytes.length == 0) {
return null; return null;
@ -169,7 +176,8 @@ public class ByteUtils {
byte[] byteArrayAndInvert = toByteArrayAndInvert(bytes[0]); byte[] byteArrayAndInvert = toByteArrayAndInvert(bytes[0]);
if (byteArrayAndInvert[0] == 1) { if (byteArrayAndInvert[0] == 1) {
return true; return true;
}else { }
else {
return false; return false;
} }
} }
@ -177,7 +185,8 @@ public class ByteUtils {
public static Boolean toBoolean(byte bytes) { public static Boolean toBoolean(byte bytes) {
if (bytes == 1) { if (bytes == 1) {
return true; return true;
}else { }
else {
return false; return false;
} }
} }
@ -187,7 +196,8 @@ public class ByteUtils {
Date date = null; Date date = null;
try { try {
date = dateFormat.parse(timeParam); // 指定日期 date = dateFormat.parse(timeParam); // 指定日期
}catch (Exception e){ }
catch (Exception e) {
throw new ParseDataException("ByteUtils.addDate error:", e); throw new ParseDataException("ByteUtils.addDate error:", e);
} }
@ -214,13 +224,14 @@ public class ByteUtils {
/** /**
* 1个字节byte[] 转成有符号的Integer * 1个字节byte[] 转成有符号的Integer
* */ */
public static Integer toInt(byte bytes) { public static Integer toInt(byte bytes) {
return Integer.valueOf(Byte.toString(bytes)); return Integer.valueOf(Byte.toString(bytes));
} }
/** /**
* 1个字节byte[] 转成无符号的Integer * 1个字节byte[] 转成无符号的Integer
* */ */
public static Integer toUInt(byte bytes) { public static Integer toUInt(byte bytes) {
int i = Byte.toUnsignedInt(bytes); int i = Byte.toUnsignedInt(bytes);
return Integer.valueOf(i); return Integer.valueOf(i);
@ -230,7 +241,7 @@ public class ByteUtils {
/** /**
* 2个字节byte[] 转成有符号的Integer * 2个字节byte[] 转成有符号的Integer
* 默认大端 * 默认大端
* */ */
public static Integer toInt(byte byte1, byte byte2) { public static Integer toInt(byte byte1, byte byte2) {
byte[] bytes = new byte[2]; byte[] bytes = new byte[2];
bytes[0] = byte1; bytes[0] = byte1;
@ -238,10 +249,11 @@ public class ByteUtils {
return Integer.valueOf(Short.toString(ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN))); return Integer.valueOf(Short.toString(ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN)));
} }
/** /**
* 2个字节byte[] 转成无符号的Integer * 2个字节byte[] 转成无符号的Integer
* 默认大端 * 默认大端
* */ */
public static Integer toUInt(byte byte1, byte byte2) { public static Integer toUInt(byte byte1, byte byte2) {
byte[] bytes = new byte[2]; byte[] bytes = new byte[2];
bytes[0] = byte1; bytes[0] = byte1;
@ -254,7 +266,7 @@ public class ByteUtils {
/** /**
* 4个字节byte[] 转成有符号的Integer * 4个字节byte[] 转成有符号的Integer
* 默认大端 * 默认大端
* */ */
public static Integer toInt(byte byte1, byte byte2, byte byte3, byte byte4) { public static Integer toInt(byte byte1, byte byte2, byte byte3, byte byte4) {
byte[] bytes = new byte[4]; byte[] bytes = new byte[4];
bytes[0] = byte1; bytes[0] = byte1;
@ -263,10 +275,11 @@ public class ByteUtils {
bytes[3] = byte4; bytes[3] = byte4;
return ByteUtil.bytesToInt(bytes, ByteOrder.BIG_ENDIAN); return ByteUtil.bytesToInt(bytes, ByteOrder.BIG_ENDIAN);
} }
/** /**
* 4个字节byte[] 转成无符号的Long因为如果首位为1 Integer就不满足长度了 * 4个字节byte[] 转成无符号的Long因为如果首位为1 Integer就不满足长度了
* 默认大端 * 默认大端
* */ */
public static Long toUInt(byte byte1, byte byte2, byte byte3, byte byte4) { public static Long toUInt(byte byte1, byte byte2, byte byte3, byte byte4) {
byte[] bytes = new byte[8]; byte[] bytes = new byte[8];
bytes[0] = 0; bytes[0] = 0;
@ -285,15 +298,16 @@ public class ByteUtils {
* *
* 4个字节byte[] 转成有符号的Double * 4个字节byte[] 转成有符号的Double
* 默认大端 * 默认大端
* */ */
public static Float forReal(byte[] bytes) { public static Float forReal(byte[] bytes) {
return Float.intBitsToFloat(toInt(bytes[0], bytes[1], bytes[2], bytes[3])); return Float.intBitsToFloat(toInt(bytes[0], bytes[1], bytes[2], bytes[3]));
} }
/** /**
* *
* 8个字节byte[] 转成有符号的Double * 8个字节byte[] 转成有符号的Double
* 默认大端 * 默认大端
* */ */
public static Double forLReal(byte[] bytes) { public static Double forLReal(byte[] bytes) {
return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN); return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN);
} }
@ -302,10 +316,11 @@ public class ByteUtils {
* *
* 8个字节byte[] 转成有符号的Double * 8个字节byte[] 转成有符号的Double
* 默认大端 * 默认大端
* */ */
public static Double lrealbytesToDouble(byte[] bytes) { public static Double lrealbytesToDouble(byte[] bytes) {
return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN); return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN);
} }
public static List<Double> toLrealArray(byte[] bytes) { public static List<Double> toLrealArray(byte[] bytes) {
List<Double> list = new ArrayList<>(); List<Double> list = new ArrayList<>();
int i = 0; int i = 0;
@ -315,10 +330,12 @@ public class ByteUtils {
} }
return list; return list;
} }
public static byte[] lrealToBytes(double doubleValue) { public static byte[] lrealToBytes(double doubleValue) {
return ByteUtil.doubleToBytes(doubleValue, ByteOrder.BIG_ENDIAN); return ByteUtil.doubleToBytes(doubleValue, ByteOrder.BIG_ENDIAN);
//return double2Bytes(doubleValue); //return double2Bytes(doubleValue);
} }
public static byte[] lrealArrayToBytes(List<Double> doubleValue) { public static byte[] lrealArrayToBytes(List<Double> doubleValue) {
List<Byte> bytes = new ArrayList<>(); List<Byte> bytes = new ArrayList<>();
for (Double b : doubleValue) { for (Double b : doubleValue) {
@ -344,6 +361,7 @@ public class ByteUtils {
} }
return byteToChar(b); return byteToChar(b);
} }
public static Character toChar(byte b) { public static Character toChar(byte b) {
return byteToChar(b); return byteToChar(b);
} }
@ -356,7 +374,7 @@ public class ByteUtils {
/** /**
* return null 代表返回传入参数不正确str 取的length太小 * return null 代表返回传入参数不正确str 取的length太小
* */ */
// public static String toStr(byte[] b) { // public static String toStr(byte[] b) {
// Integer length = Byte.toUnsignedInt(b[1]); // Integer length = Byte.toUnsignedInt(b[1]);
// if(length>(b.length-2)){ // if(length>(b.length-2)){
@ -446,6 +464,7 @@ public class ByteUtils {
return array; return array;
} }
/** /**
* desc : 获取字节 最高位的符号位 * desc : 获取字节 最高位的符号位
* return * return
@ -518,8 +537,6 @@ public class ByteUtils {
//bool array to byte array //bool array to byte array
// public st atic List<Boolean> toBoolArray(byte[] b) throws UnsupportedEncodingException { // public st atic List<Boolean> toBoolArray(byte[] b) throws UnsupportedEncodingException {
// List<Boolean> res = new ArrayList<>(); // List<Boolean> res = new ArrayList<>();
// for(int i=0;i<b.length;i++){ // for(int i=0;i<b.length;i++){
@ -547,7 +564,7 @@ public class ByteUtils {
//toWord //toWord
/** /**
* 默认word => 有符号的整形 * 默认word => 有符号的整形
* */ */
public static List<Integer> toWordArray(byte[] b) { public static List<Integer> toWordArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
int i = 0; int i = 0;
@ -563,7 +580,7 @@ public class ByteUtils {
//toDWord //toDWord
/** /**
* 默认dword => 有符号的整形 * 默认dword => 有符号的整形
* */ */
public static List<Integer> toDWordArray(byte[] b) { public static List<Integer> toDWordArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
int i = 0; int i = 0;
@ -575,15 +592,17 @@ public class ByteUtils {
} }
return res; return res;
} }
/** /**
* *
* 4个字节byte[] 转成有符号的Double * 4个字节byte[] 转成有符号的Double
* 默认大端 * 默认大端
* */ */
public static Float realbytesToFloat(byte[] bytes) { public static Float realbytesToFloat(byte[] bytes) {
return Float.intBitsToFloat(toInt(bytes[0], bytes[1], bytes[2], bytes[3])); return Float.intBitsToFloat(toInt(bytes[0], bytes[1], bytes[2], bytes[3]));
} }
public static List<Float> toRealArray(byte[] bytes) { public static List<Float> toRealArray(byte[] bytes) {
List<Float> res = new ArrayList<>(); List<Float> res = new ArrayList<>();
int i = 0; int i = 0;
@ -598,6 +617,7 @@ public class ByteUtils {
public static byte[] realToBytes(Float f) { public static byte[] realToBytes(Float f) {
return invert(float2byte(f)); return invert(float2byte(f));
} }
public static byte[] realArrayToBytes(List<Float> list) { public static byte[] realArrayToBytes(List<Float> list) {
List<Byte> res = new ArrayList<>(); List<Byte> res = new ArrayList<>();
for (Float f : list) { for (Float f : list) {
@ -650,7 +670,7 @@ public class ByteUtils {
//toUInt //toUInt
/** /**
* USInt 无符号整形 1个字节 = Integer * USInt 无符号整形 1个字节 = Integer
* */ */
public static List<Integer> toUSIntArray(byte[] b) { public static List<Integer> toUSIntArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
for (int i = 0; i < b.length; i++) { for (int i = 0; i < b.length; i++) {
@ -658,9 +678,10 @@ public class ByteUtils {
} }
return res; return res;
} }
/** /**
* UInt 无符号整形 2个字节 = Integer * UInt 无符号整形 2个字节 = Integer
* */ */
public static List<Integer> toUIntArray(byte[] b) { public static List<Integer> toUIntArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
int i = 0; int i = 0;
@ -672,9 +693,10 @@ public class ByteUtils {
} }
return res; return res;
} }
/** /**
* UDInt 无符号整形 4个字节 = Long * UDInt 无符号整形 4个字节 = Long
* */ */
public static List<Long> toUDIntArray(byte[] b) { public static List<Long> toUDIntArray(byte[] b) {
List<Long> res = new ArrayList<>(); List<Long> res = new ArrayList<>();
int i = 0; int i = 0;
@ -689,7 +711,7 @@ public class ByteUtils {
/** /**
* SInt 无符号整形 1个字节 = Integer * SInt 无符号整形 1个字节 = Integer
* */ */
public static List<Integer> toSIntArray(byte[] b) { public static List<Integer> toSIntArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
for (int i = 0; i < b.length; i++) { for (int i = 0; i < b.length; i++) {
@ -697,9 +719,10 @@ public class ByteUtils {
} }
return res; return res;
} }
/** /**
* Int 无符号整形 2个字节 = Integer * Int 无符号整形 2个字节 = Integer
* */ */
public static List<Integer> toIntArray(byte[] b) { public static List<Integer> toIntArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
int i = 0; int i = 0;
@ -711,9 +734,10 @@ public class ByteUtils {
} }
return res; return res;
} }
/** /**
* DInt 无符号整形 4个字节 = Integer * DInt 无符号整形 4个字节 = Integer
* */ */
public static List<Integer> toDIntArray(byte[] b) { public static List<Integer> toDIntArray(byte[] b) {
List<Integer> res = new ArrayList<>(); List<Integer> res = new ArrayList<>();
int i = 0; int i = 0;
@ -729,16 +753,17 @@ public class ByteUtils {
/** /**
* sint(1个字节) = byte[] * sint(1个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] sintToBytes(Integer i) { public static byte[] sintToBytes(Integer i) {
byte[] res = new byte[1]; byte[] res = new byte[1];
res[0] = Byte.valueOf(i.toString()); res[0] = Byte.valueOf(i.toString());
return res; return res;
} }
/** /**
* sintArray(1个字节) = byte[] * sintArray(1个字节) = byte[]
* *
* */ */
public static byte[] sintArrayToBytes(int[] sintArray) { public static byte[] sintArrayToBytes(int[] sintArray) {
byte[] res = new byte[sintArray.length]; byte[] res = new byte[sintArray.length];
for (int i = 0; i < sintArray.length; i++) { for (int i = 0; i < sintArray.length; i++) {
@ -751,7 +776,7 @@ public class ByteUtils {
/** /**
* int(2个字节) = byte[] * int(2个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] intToBytes(Integer i) { public static byte[] intToBytes(Integer i) {
Number shortNumber = Short.valueOf(i.toString()); Number shortNumber = Short.valueOf(i.toString());
return ByteUtil.numberToBytes(shortNumber, ByteOrder.BIG_ENDIAN); return ByteUtil.numberToBytes(shortNumber, ByteOrder.BIG_ENDIAN);
@ -777,10 +802,9 @@ public class ByteUtils {
} }
/** /**
* intArray(2个字节) = byte[] * intArray(2个字节) = byte[]
* */ */
public static byte[] intArrayToBytes(int[] intArray) { public static byte[] intArrayToBytes(int[] intArray) {
byte[] res = new byte[intArray.length * 2]; byte[] res = new byte[intArray.length * 2];
for (int i = 0; i < intArray.length; i++) { for (int i = 0; i < intArray.length; i++) {
@ -794,7 +818,7 @@ public class ByteUtils {
/** /**
* int(2个字节) = byte[] * int(2个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] dintToBytes(Integer i) { public static byte[] dintToBytes(Integer i) {
Number intNumber = i; Number intNumber = i;
return ByteUtil.numberToBytes(intNumber, ByteOrder.BIG_ENDIAN); return ByteUtil.numberToBytes(intNumber, ByteOrder.BIG_ENDIAN);
@ -802,7 +826,7 @@ public class ByteUtils {
/** /**
* intArray(2个字节) = byte[] * intArray(2个字节) = byte[]
* */ */
public static byte[] dintArrayToBytes(int[] dintArray) { public static byte[] dintArrayToBytes(int[] dintArray) {
byte[] res = new byte[dintArray.length * 4]; byte[] res = new byte[dintArray.length * 4];
for (int i = 0; i < dintArray.length; i++) { for (int i = 0; i < dintArray.length; i++) {
@ -819,7 +843,7 @@ public class ByteUtils {
/** /**
* sint(1个字节) = byte[] * sint(1个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] usintToBytes(Integer i) { public static byte[] usintToBytes(Integer i) {
if (i < 0) { if (i < 0) {
return null; return null;
@ -828,6 +852,7 @@ public class ByteUtils {
res[0] = Byte.valueOf(i.toString()); res[0] = Byte.valueOf(i.toString());
return res; return res;
} }
public static byte usintTo1Byte(Integer i) { public static byte usintTo1Byte(Integer i) {
if (i < 0 || i >= 256) { if (i < 0 || i >= 256) {
return 0x00; return 0x00;
@ -838,7 +863,7 @@ public class ByteUtils {
/** /**
* usintArrayToBytes = byte[] * usintArrayToBytes = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] usintArrayToBytes(int[] usintArray) { public static byte[] usintArrayToBytes(int[] usintArray) {
byte[] res = new byte[usintArray.length]; byte[] res = new byte[usintArray.length];
for (int i = 0; i < usintArray.length; i++) { for (int i = 0; i < usintArray.length; i++) {
@ -855,7 +880,7 @@ public class ByteUtils {
/** /**
* int(2个字节) = byte[] * int(2个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] uintToBytes(Integer i) { public static byte[] uintToBytes(Integer i) {
if (i < 0) { if (i < 0) {
return null; return null;
@ -869,7 +894,8 @@ public class ByteUtils {
ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN);
buffer.putInt(value); buffer.putInt(value);
return buffer.array(); return buffer.array();
}else { }
else {
ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(value); buffer.putInt(value);
return buffer.array(); return buffer.array();
@ -893,7 +919,7 @@ public class ByteUtils {
/** /**
* int(2个字节) = byte[] * int(2个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] udintToBytes(Integer i) { public static byte[] udintToBytes(Integer i) {
if (i < 0) { if (i < 0) {
return null; return null;
@ -905,13 +931,14 @@ public class ByteUtils {
/** /**
* long(8个字节) = byte[] * long(8个字节) = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] longToBytes(Long i) { public static byte[] longToBytes(Long i) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
buffer.putLong(i); buffer.putLong(i);
byte[] array = buffer.array(); byte[] array = buffer.array();
return array; return array;
} }
public static byte[] longArrayToBytes(List<Long> longs) { public static byte[] longArrayToBytes(List<Long> longs) {
ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES * longs.size()); ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES * longs.size());
for (Long i : longs) { for (Long i : longs) {
@ -931,11 +958,10 @@ public class ByteUtils {
} }
return buffer.getLong(); return buffer.getLong();
} }
/** /**
* byte[] ==> List<Long>(8个字节) * @param source 来源
* @param source
* @param littleEndian 输入数组是否小端模式 * @param littleEndian 输入数组是否小端模式
* @return
*/ */
public static List<Long> toLongArray(byte[] source, boolean littleEndian) { public static List<Long> toLongArray(byte[] source, boolean littleEndian) {
List<Long> res = new ArrayList<>(); List<Long> res = new ArrayList<>();
@ -954,7 +980,6 @@ public class ByteUtils {
} }
public static byte[] udintArrayToBytes(int[] udintArray) { public static byte[] udintArrayToBytes(int[] udintArray) {
byte[] res = new byte[udintArray.length * 4]; byte[] res = new byte[udintArray.length * 4];
for (int i = 0; i < udintArray.length; i++) { for (int i = 0; i < udintArray.length; i++) {
@ -973,7 +998,7 @@ public class ByteUtils {
/** /**
* boolean = byte[] * boolean = byte[]
* 默认大端模式 * 默认大端模式
* */ */
public static byte[] boolToBytes(Boolean bool) { public static byte[] boolToBytes(Boolean bool) {
byte[] res = new byte[2]; byte[] res = new byte[2];
//之所以这样是为了撑大 newValue数组因为 modbus tcp 最小单元 就是1个word(2 byte). //之所以这样是为了撑大 newValue数组因为 modbus tcp 最小单元 就是1个word(2 byte).
@ -981,21 +1006,24 @@ public class ByteUtils {
if (bool) { if (bool) {
res[0] = 1; res[0] = 1;
return res; return res;
}else { }
else {
res[0] = 0; res[0] = 0;
return res; return res;
} }
} }
/** /**
* booleanArray = byte[] * booleanArray = byte[]
* */ */
public static byte[] booleanArrayToBytes(boolean[] boolArray) { public static byte[] booleanArrayToBytes(boolean[] boolArray) {
byte[] res = new byte[boolArray.length]; byte[] res = new byte[boolArray.length];
for (int i = 0; i < boolArray.length; i++) { for (int i = 0; i < boolArray.length; i++) {
boolean b = boolArray[i]; boolean b = boolArray[i];
if (b) { if (b) {
res[i] = 1; res[i] = 1;
}else { }
else {
res[i] = 0; res[i] = 0;
} }
} }
@ -1025,7 +1053,8 @@ public class ByteUtils {
Byte aByte = fromBooleanArray(reverse(input)); Byte aByte = fromBooleanArray(reverse(input));
res[z] = aByte; res[z] = aByte;
z++; z++;
}else { }
else {
for (int i = 0; i < boolLength; i++) { for (int i = 0; i < boolLength; i++) {
input[i] = queue.poll(); input[i] = queue.poll();
} }
@ -1040,14 +1069,15 @@ public class ByteUtils {
/** /**
* charArray = byte[] * charArray = byte[]
* */ */
public static byte[] charArrayToBytes(char[] charArray) { public static byte[] charArrayToBytes(char[] charArray) {
byte[] res = new byte[charArray.length]; byte[] res = new byte[charArray.length];
for (int i = 0; i < charArray.length; i++) { for (int i = 0; i < charArray.length; i++) {
byte[] bytes = charToByte(charArray[i]); byte[] bytes = charToByte(charArray[i]);
if (bytes[0] != 0) { if (bytes[0] != 0) {
return null; return null;
}else { }
else {
res[i] = bytes[1]; res[i] = bytes[1];
} }
} }
@ -1055,13 +1085,10 @@ public class ByteUtils {
} }
/** /**
* byte = byte[] * byte = byte[]
* 默认大端模式 * 默认大端模式
* */ */
// public static byte[] setbytes(Byte bytes) { // public static byte[] setbytes(Byte bytes) {
// byte[] res = new byte[1]; // byte[] res = new byte[1];
// res[0] = bytes; // res[0] = bytes;
@ -1078,14 +1105,14 @@ public class ByteUtils {
* word = byte[] * word = byte[]
* 默认大端模式 * 默认大端模式
* tip: 目前只支持 带符号的十进制 == word(2个字节) * tip: 目前只支持 带符号的十进制 == word(2个字节)
* */ */
public static byte[] wordToBytes(Short word) { public static byte[] wordToBytes(Short word) {
return ByteUtil.shortToBytes(word, ByteOrder.BIG_ENDIAN); return ByteUtil.shortToBytes(word, ByteOrder.BIG_ENDIAN);
} }
/** /**
* wordArray = byte[] * wordArray = byte[]
* */ */
public static byte[] wordArrayToBytes(short[] shortArray) { public static byte[] wordArrayToBytes(short[] shortArray) {
byte[] res = new byte[shortArray.length * 2]; byte[] res = new byte[shortArray.length * 2];
for (int i = 0; i < shortArray.length; i++) { for (int i = 0; i < shortArray.length; i++) {
@ -1100,14 +1127,14 @@ public class ByteUtils {
* dword = byte[] * dword = byte[]
* 默认大端模式 * 默认大端模式
* tip: 目前只支持 带符号的十进制 == word(4个字节) * tip: 目前只支持 带符号的十进制 == word(4个字节)
* */ */
public static byte[] dwordToBytes(Integer dword) { public static byte[] dwordToBytes(Integer dword) {
return ByteUtil.intToBytes(dword, ByteOrder.BIG_ENDIAN); return ByteUtil.intToBytes(dword, ByteOrder.BIG_ENDIAN);
} }
/** /**
* dwordArray = byte[] * dwordArray = byte[]
* */ */
public static byte[] dwordArrayToBytes(int[] intArray) { public static byte[] dwordArrayToBytes(int[] intArray) {
byte[] res = new byte[intArray.length * 4]; byte[] res = new byte[intArray.length * 4];
for (int i = 0; i < intArray.length; i++) { for (int i = 0; i < intArray.length; i++) {
@ -1123,10 +1150,11 @@ public class ByteUtils {
/** /**
* char(1字节) = byte[] * char(1字节) = byte[]
* *
* */ */
public static byte[] charToBytes(Character c) { public static byte[] charToBytes(Character c) {
return String.valueOf(c).getBytes(); return String.valueOf(c).getBytes();
} }
public static byte[] wcharToBytes(Character c) { public static byte[] wcharToBytes(Character c) {
return charToByte(c); return charToByte(c);
} }
@ -1134,7 +1162,7 @@ public class ByteUtils {
//如果plc中没有设置 strSize,那么 这个字符串变量的 最大长度默认是 254字节就是-2 //如果plc中没有设置 strSize,那么 这个字符串变量的 最大长度默认是 254字节就是-2
/** /**
* 这个函数就用于 非str类型转bytes使用string类型转bytes 用strToBytes(String s,Integer strSize) 这个方法 * 这个函数就用于 非str类型转bytes使用string类型转bytes 用strToBytes(String s,Integer strSize) 这个方法
* */ */
public static byte[] strToBytes(String s) { public static byte[] strToBytes(String s) {
byte[] bytes = s.getBytes(StandardCharsets.UTF_8); byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
byte[] res = new byte[bytes.length + 2]; byte[] res = new byte[bytes.length + 2];
@ -1145,6 +1173,7 @@ public class ByteUtils {
} }
return res; return res;
} }
public static byte[] strArrayToBytes(List<String> strList) { public static byte[] strArrayToBytes(List<String> strList) {
List<Byte> byteList = new ArrayList<>(); List<Byte> byteList = new ArrayList<>();
for (String s : strList) { for (String s : strList) {
@ -1163,6 +1192,7 @@ public class ByteUtils {
/** /**
* 将字符串转换为指定字节长度的字节数组 * 将字符串转换为指定字节长度的字节数组
*
* @param strValue 待转换的字符串 * @param strValue 待转换的字符串
* @param byteSize 指定的字节长度 * @param byteSize 指定的字节长度
* @return 转换后的字节数组 * @return 转换后的字节数组
@ -1191,7 +1221,7 @@ public class ByteUtils {
* 一般来说 plc中 string变量都是会设置 长度的 var1 = String[18],这里的strSize就是18 * 一般来说 plc中 string变量都是会设置 长度的 var1 = String[18],这里的strSize就是18
* 返回 * 返回
* 返回的字节流是包含2个头字节的也就是 strSize+2 个长度的字节流 * 返回的字节流是包含2个头字节的也就是 strSize+2 个长度的字节流
* */ */
public static byte[] strToBytes(String s, Integer strSize) { public static byte[] strToBytes(String s, Integer strSize) {
if (s == null || (strSize <= 0)) { if (s == null || (strSize <= 0)) {
return null; return null;
@ -1205,7 +1235,8 @@ public class ByteUtils {
for (int i = 0; i < strSize; i++) { for (int i = 0; i < strSize; i++) {
res[i + 2] = bytes[i]; res[i + 2] = bytes[i];
} }
}else { }
else {
res[1] = Integer.valueOf(bytes.length).byteValue(); res[1] = Integer.valueOf(bytes.length).byteValue();
for (int i = 0; i < bytes.length; i++) { for (int i = 0; i < bytes.length; i++) {
res[i + 2] = bytes[i]; res[i + 2] = bytes[i];
@ -1224,6 +1255,7 @@ public class ByteUtils {
} }
return intToBytes(a); return intToBytes(a);
} }
public static byte[] remainderForBool(Integer i) { public static byte[] remainderForBool(Integer i) {
int a = i / 16; int a = i / 16;
int z = i % 16; int z = i % 16;
@ -1251,12 +1283,9 @@ public class ByteUtils {
* 参数 * 参数
* desc : 把字符串数组 ==> byte[] [x,x,..,..,..,..,... x,x,..,..,..,..,... ...] * desc : 把字符串数组 ==> byte[] [x,x,..,..,..,..,... x,x,..,..,..,..,... ...]
* array : 就是需要被写入plc的内容,, array.length 就是你要写入数组的长度 注意array.length必须小于plc中设置的 数组变量 length * array : 就是需要被写入plc的内容,, array.length 就是你要写入数组的长度 注意array.length必须小于plc中设置的 数组变量 length
* strSize : 就是数组中某个变量的长度 比如 String str = new String[18] 这里的18就是strSize,但是在博图偏移量地址上可以发现它已经把你+2了,就是你设置最大string长度18 但偏移量=18+2=20;; * strSize : 就是数组中某个变量的长度 比如 String str = new String[18]
* 而上面的array.length是 List<String> list = new ArrayList<>; 的list.length * 这里的18就是strSize,但是在博图偏移量地址上可以发现它已经把你+2了,就是你设置最大string长度18 但偏移量=18+2=20;;
* 返回 */
* byte[] 就是整个数组字符串的 总的字节流
*
* */
public static byte[] strArrayToBytes(String[] array, Integer strSize) { public static byte[] strArrayToBytes(String[] array, Integer strSize) {
//str0 [18, 17, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53] //str0 [18, 17, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53]
//str1 [18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 49] //str1 [18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 49]
@ -1274,7 +1303,6 @@ public class ByteUtils {
} }
//for private //for private
private static byte[] charToByte(char c) { private static byte[] charToByte(char c) {
@ -1283,10 +1311,12 @@ public class ByteUtils {
b[1] = (byte) (c & 0xFF); b[1] = (byte) (c & 0xFF);
return b; return b;
} }
private static char byteToChar(byte[] b) { private static char byteToChar(byte[] b) {
char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF)); char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF));
return c; return c;
} }
private static char byteToChar(byte b) { private static char byteToChar(byte b) {
char c = (char) (b & 0xFF); char c = (char) (b & 0xFF);
return c; return c;
@ -1294,7 +1324,7 @@ public class ByteUtils {
/** /**
* 4个字节 ==> float小端模式 * 4个字节 ==> float小端模式
* */ */
public static float bytesToFloat(byte[] src, int offset) { public static float bytesToFloat(byte[] src, int offset) {
// int i = ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF); // int i = ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF);
// return Float.intBitsToFloat(i); // return Float.intBitsToFloat(i);
@ -1306,7 +1336,7 @@ public class ByteUtils {
/** /**
* 4个字节 ==> int小端模式 * 4个字节 ==> int小端模式
* */ */
public static int bytesToInt(byte[] src, int offset) { public static int bytesToInt(byte[] src, int offset) {
//return ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF); //return ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF);

View File

@ -1,14 +1,9 @@
package org.opentcs.kc.common.byteutils; package org.opentcs.kc.common.byteutils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/12/5 11:11
*/
public class CommonFunctions { public class CommonFunctions {
/** /**
* a 整除 b 如果有余数+1 * a 整除 b 如果有余数+1
* */ */
public static Integer exactDivision(Integer a, Integer b) { public static Integer exactDivision(Integer a, Integer b) {
int c = a / b; int c = a / b;

View File

@ -1,10 +1,5 @@
package org.opentcs.kc.common.byteutils; package org.opentcs.kc.common.byteutils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2024-05-08 11:02
*/
public class StringArrayStruc { public class StringArrayStruc {
private String[] content; private String[] content;
private Integer strSize; private Integer strSize;

View File

@ -5,15 +5,13 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/** /**
* @Author: 蔡翔 * 重点.
* @Date: 2019/11/6 14:11 * AsyncFuture 这个类就是票据 刚拿到这个票据是没有信息的当done == true 的时候这个票据 上就自动有信息了.
* @Version 1.0 * 这个结果类设计的比较神奇.
*
* 重点
* AsyncFuture 这个类就是票据 刚拿到这个票据是没有信息的当done == true 的时候这个票据 上就自动有信息了
* 这个结果类设计的比较神奇
*/ */
public class AsyncFuture<Object> implements Future<Object> { public class AsyncFuture<Object>
implements
Future<Object> {
private static final Logger logger = LoggerFactory.getLogger(AsyncFuture.class); private static final Logger logger = LoggerFactory.getLogger(AsyncFuture.class);
private volatile boolean done = false; private volatile boolean done = false;
@ -23,6 +21,7 @@ public class AsyncFuture<Object> implements Future<Object> {
public AsyncFuture(Object oldRequest) { public AsyncFuture(Object oldRequest) {
this.oldRequest = oldRequest; this.oldRequest = oldRequest;
} }
public AsyncFuture() { public AsyncFuture() {
} }
@ -37,12 +36,14 @@ public class AsyncFuture<Object> implements Future<Object> {
@Override @Override
public Object get(Long timeout) throws Exception { public Object get(Long timeout)
throws Exception {
return null; return null;
} }
@Override @Override
public Object get(Long timeout, String transationId) throws Exception { public Object get(Long timeout, String transationId)
throws Exception {
synchronized (this) { synchronized (this) {
//其实有 synchronize就相当于有一个阻塞队列当有线程执行了wait 方法就会把执行wait的这个线程给加入wait<Thread> 队列 //其实有 synchronize就相当于有一个阻塞队列当有线程执行了wait 方法就会把执行wait的这个线程给加入wait<Thread> 队列
//当有线程执行notify方法的时候就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了 //当有线程执行notify方法的时候就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了

View File

@ -1,14 +1,11 @@
package org.opentcs.kc.syn; package org.opentcs.kc.syn;
/**
* @Author: 蔡翔
* @Date: 2019/11/6 13:49
* @Version 1.0
*/
public interface Future<MQMessage> { public interface Future<MQMessage> {
//别人调用我的时候我先给他们返回一个结果 //别人调用我的时候我先给他们返回一个结果
MQMessage get(Long timeout) throws Exception; MQMessage get(Long timeout)
throws Exception;
MQMessage get(Long timeout, String transationId) throws Exception; MQMessage get(Long timeout, String transationId)
throws Exception;
} }

View File

@ -1,13 +1,6 @@
package org.opentcs.kc.syn; package org.opentcs.kc.syn;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2021/8/17 14:35
*/
public class Main { public class Main {
// public static void main(String[] args) throws Exception { // public static void main(String[] args) throws Exception {

View File

@ -4,12 +4,6 @@ package org.opentcs.kc.syn;
import org.opentcs.kc.common.CaffeineUtil; import org.opentcs.kc.common.CaffeineUtil;
import org.opentcs.kc.common.Package; import org.opentcs.kc.common.Package;
/**
* @Desc: "MES端 发送远程指令列表"
* @Author: caixiang
* @DATE: 2021/8/17 14:14
*/
public class SendedList { public class SendedList {
// private static HashMap<String, AsyncFuture<MBPackage>> list = new HashMap<>(); // private static HashMap<String, AsyncFuture<MBPackage>> list = new HashMap<>();
// public static synchronized AsyncFuture<MQMessage> get(String transitionId){ // public static synchronized AsyncFuture<MQMessage> get(String transitionId){
@ -35,7 +29,9 @@ public class SendedList {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static synchronized Boolean set(String transitionId, Package message) { public static synchronized Boolean set(String transitionId, Package message) {
//AsyncFuture<MBPackage> mqMessageAsyncFuture = list.get(transitionId); //AsyncFuture<MBPackage> mqMessageAsyncFuture = list.get(transitionId);
AsyncFuture<Package> mqMessageAsyncFuture = (AsyncFuture<Package>)CaffeineUtil.get(transitionId); AsyncFuture<Package> mqMessageAsyncFuture = (AsyncFuture<Package>) CaffeineUtil.get(
transitionId
);
if (mqMessageAsyncFuture == null) { if (mqMessageAsyncFuture == null) {
return false; return false;
} }
@ -46,6 +42,4 @@ public class SendedList {
} }
} }

View File

@ -29,6 +29,7 @@ public class LogConst {
"这便,晨光微好,花开静好……"}; "这便,晨光微好,花开静好……"};
private final static Random r = new Random(); private final static Random r = new Random();
public static String getLogInfo() { public static String getLogInfo() {
return LOG_INFOS[r.nextInt(LOG_INFOS.length - 1)]; return LOG_INFOS[r.nextInt(LOG_INFOS.length - 1)];
} }

View File

@ -32,18 +32,24 @@ public class LogEventBroadcaster {
.handler(new LogEventEncoder(remoteAddress)); .handler(new LogEventEncoder(remoteAddress));
} }
public void run() throws Exception { public void run()
throws Exception {
//绑定 Channel //绑定 Channel
Channel ch = bootstrap.bind(0).sync().channel(); Channel ch = bootstrap.bind(0).sync().channel();
long count = 0; long count = 0;
//启动主处理循环模拟日志发送 //启动主处理循环模拟日志发送
for (;;) { for (;;) {
ch.writeAndFlush(new LogMsg(null, ++count, ch.writeAndFlush(
LogConst.getLogInfo())); new LogMsg(
null, ++count,
LogConst.getLogInfo()
)
);
try { try {
//休眠 2 如果被中断则退出循环 //休眠 2 如果被中断则退出循环
Thread.sleep(2000); Thread.sleep(2000);
} catch (InterruptedException e) { }
catch (InterruptedException e) {
Thread.interrupted(); Thread.interrupted();
break; break;
} }
@ -54,15 +60,19 @@ public class LogEventBroadcaster {
group.shutdownGracefully(); group.shutdownGracefully();
} }
public static void main(String[] args) throws Exception { public static void main(String[] args)
throws Exception {
//创建并启动一个新的 UdpQuestionSide 的实例 //创建并启动一个新的 UdpQuestionSide 的实例
LogEventBroadcaster broadcaster = new LogEventBroadcaster( LogEventBroadcaster broadcaster = new LogEventBroadcaster(
//表明本应用发送的报文并没有一个确定的目的地也就是进行广播 //表明本应用发送的报文并没有一个确定的目的地也就是进行广播
//就是往这个网络下 所有主机发送数据往这些主机的 LogConst.MONITOR_SIDE_PORT端口 发送数据 //就是往这个网络下 所有主机发送数据往这些主机的 LogConst.MONITOR_SIDE_PORT端口 发送数据
//todo 这里的设置和 单播是有差异的 //todo 这里的设置和 单播是有差异的
new InetSocketAddress("255.255.255.255", new InetSocketAddress(
LogConst.MONITOR_SIDE_PORT)); "255.255.255.255",
LogConst.MONITOR_SIDE_PORT
)
);
try { try {
System.out.println("广播服务启动"); System.out.println("广播服务启动");
broadcaster.run(); broadcaster.run();

View File

@ -18,11 +18,15 @@ import java.util.List;
* 作者DarkKIng * 作者DarkKIng
* 类说明解码将DatagramPacket解码为实际的日志实体类 * 类说明解码将DatagramPacket解码为实际的日志实体类
*/ */
public class LogEventDecoder extends MessageToMessageDecoder<DatagramPacket> { public class LogEventDecoder
extends
MessageToMessageDecoder<DatagramPacket> {
@Override @Override
protected void decode(ChannelHandlerContext ctx, protected void decode(
DatagramPacket datagramPacket, List<Object> out) ChannelHandlerContext ctx,
DatagramPacket datagramPacket, List<Object> out
)
throws Exception { throws Exception {
//获取对 DatagramPacket 中的数据ByteBuf的引用 //获取对 DatagramPacket 中的数据ByteBuf的引用
ByteBuf data = datagramPacket.content(); ByteBuf data = datagramPacket.content();
@ -36,11 +40,15 @@ public class LogEventDecoder extends MessageToMessageDecoder<DatagramPacket> {
//获取读索引的当前位置就是分隔符的索引+1 //获取读索引的当前位置就是分隔符的索引+1
int idx = data.readerIndex(); int idx = data.readerIndex();
//提取日志消息从读索引开始到最后为日志的信息 //提取日志消息从读索引开始到最后为日志的信息
String sendMsg = data.slice(idx , String sendMsg = data.slice(
data.readableBytes()).toString(CharsetUtil.UTF_8); idx,
data.readableBytes()
).toString(CharsetUtil.UTF_8);
//构建一个新的 LogMsg 对象并且将它添加到已经解码的消息的列表中 //构建一个新的 LogMsg 对象并且将它添加到已经解码的消息的列表中
LogMsg event = new LogMsg(datagramPacket.sender(), LogMsg event = new LogMsg(
msgId, sendMsg); datagramPacket.sender(),
msgId, sendMsg
);
//作为本handler的处理结果交给后面的handler进行处理 //作为本handler的处理结果交给后面的handler进行处理
out.add(event); out.add(event);
} }

View File

@ -18,7 +18,9 @@ import java.util.List;
* 作者DarkKIng * 作者DarkKIng
* 类说明编码将实际的日志实体类编码为DatagramPacket * 类说明编码将实际的日志实体类编码为DatagramPacket
*/ */
public class LogEventEncoder extends MessageToMessageEncoder<LogMsg> { public class LogEventEncoder
extends
MessageToMessageEncoder<LogMsg> {
private final InetSocketAddress remoteAddress; private final InetSocketAddress remoteAddress;
//LogEventEncoder 创建了即将被发送到指定的 InetSocketAddress //LogEventEncoder 创建了即将被发送到指定的 InetSocketAddress
@ -28,8 +30,11 @@ public class LogEventEncoder extends MessageToMessageEncoder<LogMsg> {
} }
@Override @Override
protected void encode(ChannelHandlerContext channelHandlerContext, protected void encode(
LogMsg logMsg, List<Object> out) throws Exception { ChannelHandlerContext channelHandlerContext,
LogMsg logMsg, List<Object> out
)
throws Exception {
byte[] msg = logMsg.getMsg().getBytes(CharsetUtil.UTF_8); byte[] msg = logMsg.getMsg().getBytes(CharsetUtil.UTF_8);
//容量的计算两个long型+消息的内容+分割符 //容量的计算两个long型+消息的内容+分割符
ByteBuf buf = channelHandlerContext.alloc() ByteBuf buf = channelHandlerContext.alloc()

View File

@ -14,19 +14,26 @@ import io.netty.channel.SimpleChannelInboundHandler;
* 类说明日志的业务处理类,实际的业务处理接受日志信息 * 类说明日志的业务处理类,实际的业务处理接受日志信息
*/ */
public class LogEventHandler public class LogEventHandler
extends SimpleChannelInboundHandler<LogMsg> { extends
SimpleChannelInboundHandler<LogMsg> {
@Override @Override
public void exceptionCaught(ChannelHandlerContext ctx, public void exceptionCaught(
Throwable cause) throws Exception { ChannelHandlerContext ctx,
Throwable cause
)
throws Exception {
//当异常发生时打印栈跟踪信息并关闭对应的 Channel //当异常发生时打印栈跟踪信息并关闭对应的 Channel
cause.printStackTrace(); cause.printStackTrace();
ctx.close(); ctx.close();
} }
@Override @Override
public void channelRead0(ChannelHandlerContext ctx, public void channelRead0(
LogMsg event) throws Exception { ChannelHandlerContext ctx,
LogMsg event
)
throws Exception {
//创建 StringBuilder并且构建输出的字符串 //创建 StringBuilder并且构建输出的字符串
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.append(event.getTime()); builder.append(event.getTime());

View File

@ -6,12 +6,6 @@ import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
/**
* @Desc: ""
* @Author: caixiang ( Server 接受消息 )
* @DATE: 2024/12/15 10:57
*/
public class LogEventMonitor { public class LogEventMonitor {
private final EventLoopGroup group; private final EventLoopGroup group;
private final Bootstrap bootstrap; private final Bootstrap bootstrap;
@ -47,16 +41,19 @@ public class LogEventMonitor {
group.shutdownGracefully(); group.shutdownGracefully();
} }
public static void main(String[] args) throws Exception { public static void main(String[] args)
throws Exception {
//构造一个新的 UdpAnswerSide并指明监听端口 //构造一个新的 UdpAnswerSide并指明监听端口
LogEventMonitor monitor = new LogEventMonitor( LogEventMonitor monitor = new LogEventMonitor(
new InetSocketAddress(LogConst.MONITOR_SIDE_PORT)); new InetSocketAddress(LogConst.MONITOR_SIDE_PORT)
);
try { try {
//绑定本地监听端口 //绑定本地监听端口
Channel channel = monitor.bind(); Channel channel = monitor.bind();
System.out.println("UdpAnswerSide running"); System.out.println("UdpAnswerSide running");
channel.closeFuture().sync(); channel.closeFuture().sync();
} finally { }
finally {
monitor.stop(); monitor.stop();
} }
} }

View File

@ -29,8 +29,10 @@ public final class LogMsg {
} }
//用于传出消息的构造函数 //用于传出消息的构造函数
public LogMsg(InetSocketAddress source, long msgId, public LogMsg(
String msg) { InetSocketAddress source, long msgId,
String msg
) {
this(source, msg, msgId, System.currentTimeMillis()); this(source, msg, msgId, System.currentTimeMillis());
} }

View File

@ -3,12 +3,13 @@ package org.opentcs.kc.udp;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
//import org.opentcs.kc.udp.agv.param.AgvEvent;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
import org.opentcs.kc.udp.agv.param.AgvEvent; import org.opentcs.kc.udp.agv.param.AgvEvent;
import org.opentcs.kc.udp.agv.param.AgvEventConstant; import org.opentcs.kc.udp.agv.param.AgvEventConstant;
import org.opentcs.kc.udp.agv.param.function.af.QueryRobotStatusRsp;
import org.opentcs.kc.udp.agv.param.function.b1.SubscribeInfo; import org.opentcs.kc.udp.agv.param.function.b1.SubscribeInfo;
import org.opentcs.kc.udp.agv.param.function.b1.SubscribeParam; import org.opentcs.kc.udp.agv.param.function.b1.SubscribeParam;
import org.opentcs.kc.udp.agv.param.function.b1.SubscribeRsp;
import org.opentcs.kc.udp.agv.param.function.navigation.*; import org.opentcs.kc.udp.agv.param.function.navigation.*;
import org.opentcs.kc.udp.agv.param.function.read.ReadParam; import org.opentcs.kc.udp.agv.param.function.read.ReadParam;
import org.opentcs.kc.udp.agv.param.function.read.ReadStrValue; import org.opentcs.kc.udp.agv.param.function.read.ReadStrValue;
@ -17,12 +18,11 @@ import org.opentcs.kc.udp.agv.param.function.write.WriteParam;
import org.opentcs.kc.udp.agv.param.function.write.WriteStrValue; import org.opentcs.kc.udp.agv.param.function.write.WriteStrValue;
import org.opentcs.kc.udp.agv.param.function.write.WriteValueMember; import org.opentcs.kc.udp.agv.param.function.write.WriteValueMember;
import org.opentcs.kc.udp.agv.param.function.x14.RobotSetPosition; import org.opentcs.kc.udp.agv.param.function.x14.RobotSetPosition;
import org.opentcs.kc.udp.agv.param.function.x17.QueryRobotRunStatusRsp;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
import org.opentcs.kc.udp.agv.param.AgvEvent;
/** /**
*
* AGV启动 * AGV启动
* 0xAF(查询机器人状态) 👌 * 0xAF(查询机器人状态) 👌
* 0xB1(下发订阅信令) 👌 * 0xB1(下发订阅信令) 👌
@ -33,26 +33,27 @@ import org.opentcs.kc.udp.agv.param.AgvEvent;
* 0x1F(确认初始位置) 👌 * 0x1F(确认初始位置) 👌
* 运行 * 运行
* 0xAE(导航控制导航点控制) 👌 * 0xAE(导航控制导航点控制) 👌
*
*
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/17 16:25
*/ */
public class KCCommandDemo { public class KCCommandDemo {
public static void main(String [] args) throws Exception{ public static void main(String[] args)
throws Exception {
// { // {
// //0xAF(查询机器人状态) // //0xAF(查询机器人状态)
// AgvEvent agvEvent = queryStatus(); // AgvEvent agvEvent = queryStatus();
// printInfo(agvEvent); // printInfo(agvEvent);
// RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); // RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
// if(rcv.isOk()){ // if(rcv.isOk()){
// QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
// System.out.println(); // System.out.println();
// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // System.out.println("received transationId : "+ "isok:"+rcv.isOk());
// for (byte b:rcv.getValue()){ // for (byte b:rcv.getValue()){
// System.out.print(byteToHex(b)+" "); // System.out.print(byteToHex(b)+" ");
// } // }
// System.out.println();
// System.out.println("---------------------");
// for (byte c:rcv.getDataBytes()){
// System.out.print(byteToHex(c)+" ");
// }
// QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
// }else { // }else {
// System.out.println(); // System.out.println();
// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // System.out.println("received transationId : "+ "isok:"+rcv.isOk());
@ -86,6 +87,10 @@ public class KCCommandDemo {
// if(rcv.isOk()){ // if(rcv.isOk()){
// System.out.println(); // System.out.println();
// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // System.out.println("received transationId : "+ "isok:"+rcv.isOk());
// for (byte b:rcv.getDataBytes()) {
// System.out.print(byteToHex(b)+" ");
// }
//
// SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes()); // SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes());
// if(subscribeRsp.isOk()){ // if(subscribeRsp.isOk()){
// //... // //...
@ -142,26 +147,26 @@ public class KCCommandDemo {
// } // }
// { {
// //0x14(手动定位) //0x14(手动定位)
// AgvEvent agvEvent = manualLocation(); AgvEvent agvEvent = manualLocation();
// printInfo(agvEvent); printInfo(agvEvent);
// RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
// if(rcv.isOk()){ if(rcv.isOk()){
// System.out.println(); System.out.println();
// System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:"); System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:");
// printInfo(rcv); printInfo(rcv);
// if(rcv.isOk()){ if(rcv.isOk()){
// //get and parse value //get and parse value
// System.out.println("0x14 ok"); System.out.println("0x14 ok");
// }else { }else {
// System.out.println("0x14 failed"); System.out.println("0x14 failed");
// } }
// }else { }else {
// System.out.println(); System.out.println();
// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); System.out.println("received transationId : "+ "isok:"+rcv.isOk());
// } }
// } }
// { // {
@ -170,33 +175,40 @@ public class KCCommandDemo {
// printInfo(agvEvent); // printInfo(agvEvent);
// RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); // RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
// if(rcv.isOk()){ // if(rcv.isOk()){
// //QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes());
// QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp(rcv.getDataBytes());
// System.out.println(queryRobotRunStatusRsp.toString());
// System.out.println(); // System.out.println();
// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // System.out.println("received transationId : "+ "isok:"+rcv.isOk());
// for (byte b:rcv.getValue()){ // for (byte b:rcv.getValue()){
// System.out.print(byteToHex(b)+" "); // System.out.print(byteToHex(b)+" ");
// } // }
// System.out.println();
// System.out.println("print databytes:-----=======");
// for (byte c:rcv.getDataBytes()){
// System.out.print(byteToHex(c)+" ");
// }
// //QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes());
// QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp(rcv.getDataBytes());
// System.out.println(queryRobotRunStatusRsp.toString());
//
// }else { // }else {
// System.out.println(); // System.out.println();
// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // System.out.println("received transationId : "+ "isok:"+rcv.isOk());
// } // }
// } // }
{ // {
//0x1F(确认初始位置) // //0x1F(确认初始位置)
AgvEvent agvEvent = confirmInitialPosition(); // AgvEvent agvEvent = confirmInitialPosition();
printInfo(agvEvent); // printInfo(agvEvent);
RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); // RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
if(rcv.isOk()){ // if (rcv.isOk()) {
System.out.println("0x1F ok"); // System.out.println("0x1F ok");
}else { // }
System.out.println(); // else {
System.out.println("0x1F fail"); // System.out.println();
System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // System.out.println("0x1F fail");
} // System.out.println("received transationId : " + "isok:" + rcv.isOk());
} // }
// }
// { // {
// //0xAE(导航控制导航点控制) // //0xAE(导航控制导航点控制)
@ -246,7 +258,7 @@ public class KCCommandDemo {
* 指令0x02 * 指令0x02
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent readValue() { public static AgvEvent readValue() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_READ); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_READ);
List<ReadValueMember> readValueMemberList = new ArrayList<>(); List<ReadValueMember> readValueMemberList = new ArrayList<>();
@ -268,12 +280,14 @@ public class KCCommandDemo {
* 指令0x03 * 指令0x03
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent writeValue() { public static AgvEvent writeValue() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE);
List<WriteValueMember> valueMemberList = new ArrayList<>(); List<WriteValueMember> valueMemberList = new ArrayList<>();
WriteValueMember valueMember1 = new WriteValueMember(Short.valueOf("0"),Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)); WriteValueMember valueMember1 = new WriteValueMember(
Short.valueOf("0"), Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)
);
valueMemberList.add(valueMember1); valueMemberList.add(valueMember1);
List<WriteStrValue> strValueList = new ArrayList<>(); List<WriteStrValue> strValueList = new ArrayList<>();
@ -287,14 +301,12 @@ public class KCCommandDemo {
} }
/** /**
* decs: 查询机器人状态 * decs: 查询机器人状态
* 指令0xAF * 指令0xAF
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent queryStatus() { public static AgvEvent queryStatus() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
return agvEvent; return agvEvent;
@ -305,7 +317,7 @@ public class KCCommandDemo {
* 指令0xAE * 指令0xAE
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent navigationControl() { public static AgvEvent navigationControl() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
//TODO 构建 //TODO 构建
@ -313,34 +325,69 @@ public class KCCommandDemo {
//构建point //构建point
Action[] pointActions1 = new Action[]{ Action[] pointActions1 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01)) new Action(
ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(
orderId, (byte) 0x01
)
)
//,new Action()... 每一个point 可以绑定一个或者多个 action //,new Action()... 每一个point 可以绑定一个或者多个 action
}; };
Action[] pointActions2 = new Action[]{ Action[] pointActions2 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01)) new Action(
ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(
orderId, (byte) 0x01
)
)
}; };
Action[] pointActions3 = new Action[]{ Action[] pointActions3 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01)) new Action(
ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(
orderId, (byte) 0x01
)
)
}; };
Point[] points = new Point[]{ Point[] points = new Point[]{
new Point(0, 1, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions1.length),pointActions1), new Point(
new Point(2, 2, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions2.length),pointActions2), 0, 1, 1f, (byte) 0x00, ByteUtils.usintTo1Byte(pointActions1.length), pointActions1
new Point(4, 3, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions3.length),pointActions3) ),
new Point(
2, 2, 1f, (byte) 0x00, ByteUtils.usintTo1Byte(pointActions2.length), pointActions2
),
new Point(
4, 3, 1f, (byte) 0x00, ByteUtils.usintTo1Byte(pointActions3.length), pointActions3
)
}; };
//构建path //构建path
Action[] pathActions1 = new Action[]{ Action[] pathActions1 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01)) new Action(
ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(
orderId, (byte) 0x01
)
)
//,new Action()... 每一个path 可以绑定一个或者多个 action //,new Action()... 每一个path 可以绑定一个或者多个 action
}; };
Action[] pathActions2 = new Action[]{ Action[] pathActions2 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01)) new Action(
ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(
orderId, (byte) 0x01
)
)
}; };
Path[] paths = new Path[]{ Path[] paths = new Path[]{
new Path(1,1,1f,(byte)0x00,(byte)0x00,ByteUtils.usintTo1Byte(pathActions1.length),5f,1f,pathActions1) , new Path(
new Path(3,2,1f,(byte)0x00,(byte)0x00,ByteUtils.usintTo1Byte(pathActions2.length),5f,1f,pathActions2) , 1, 1, 1f, (byte) 0x00, (byte) 0x00, ByteUtils.usintTo1Byte(pathActions1.length), 5f, 1f,
pathActions1
),
new Path(
3, 2, 1f, (byte) 0x00, (byte) 0x00, ByteUtils.usintTo1Byte(pathActions2.length), 5f, 1f,
pathActions2
),
}; };
NavigationParam navigationParam = new NavigationParam(1,1,ByteUtils.usintTo1Byte(points.length),ByteUtils.usintTo1Byte(points.length-1),points,paths); NavigationParam navigationParam = new NavigationParam(
1, 1, ByteUtils.usintTo1Byte(points.length), ByteUtils.usintTo1Byte(points.length - 1),
points, paths
);
agvEvent.setBody(navigationParam.toBytes()); agvEvent.setBody(navigationParam.toBytes());
return agvEvent; return agvEvent;
@ -351,7 +398,7 @@ public class KCCommandDemo {
* 指令0x1F * 指令0x1F
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent confirmInitialPosition() { public static AgvEvent confirmInitialPosition() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_CONFIRM_ROBOT_POSITION); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_CONFIRM_ROBOT_POSITION);
return agvEvent; return agvEvent;
@ -362,7 +409,7 @@ public class KCCommandDemo {
* 指令0x17 * 指令0x17
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent queryRobotRunStatus() { public static AgvEvent queryRobotRunStatus() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_RUN_STATUS); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_RUN_STATUS);
return agvEvent; return agvEvent;
@ -382,7 +429,7 @@ public class KCCommandDemo {
* 指令0xB0 * 指令0xB0
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent checkCargoStatus() { public static AgvEvent checkCargoStatus() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_CARRY_STATUS); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_CARRY_STATUS);
return agvEvent; return agvEvent;
@ -393,14 +440,18 @@ public class KCCommandDemo {
* 指令0xB1 * 指令0xB1
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent issueSubscribe() { public static AgvEvent issueSubscribe() {
List<SubscribeInfo> subscribeInfoList = new ArrayList<>(); List<SubscribeInfo> subscribeInfoList = new ArrayList<>();
SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xaf,(byte)0x00}, (short) 100,1000); SubscribeInfo subscribeInfo = new SubscribeInfo(
new byte[]{(byte) 0xaf, (byte) 0x00}, (short) 100, 1000
);
//SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xb0,(byte)0x00}, (short) 100,1000); //SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xb0,(byte)0x00}, (short) 100,1000);
subscribeInfoList.add(subscribeInfo); subscribeInfoList.add(subscribeInfo);
SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList); SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList);
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION,subscribeParam.toBytes()); AgvEvent agvEvent = new AgvEvent(
AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION, subscribeParam.toBytes()
);
return agvEvent; return agvEvent;
} }

View File

@ -3,11 +3,6 @@ package org.opentcs.kc.udp.Service;
import org.opentcs.kc.udp.agv.param.AgvEvent; import org.opentcs.kc.udp.agv.param.AgvEvent;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
/**
* @author xzh
* @date 2025/2/21
* @desc 命令基类
*/
public class BaseCommand { public class BaseCommand {
public static String byteToHex(byte b) { public static String byteToHex(byte b) {

View File

@ -5,19 +5,16 @@ import org.opentcs.kc.udp.agv.param.AgvEventConstant;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class ConfirmRelocation
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 确认位置 0x1F
*/
public class ConfirmRelocation extends BaseCommand{
/** /**
* decs: 确认机器人位置 * decs: 确认机器人位置.
* 指令0x1F * 指令0x1F.
* author: caixiang * author: caixiang.
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25.
* */ */
public static AgvEvent confirmInitialPosition() { public static AgvEvent confirmInitialPosition() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_CONFIRM_ROBOT_POSITION); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_CONFIRM_ROBOT_POSITION);
return agvEvent; return agvEvent;
@ -30,7 +27,8 @@ public class ConfirmRelocation extends BaseCommand{
RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
if (rcv.isOk()) { if (rcv.isOk()) {
System.out.println("0x1F ok"); System.out.println("0x1F ok");
}else { }
else {
System.out.println(); System.out.println();
System.out.println("0x1F fail"); System.out.println("0x1F fail");
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());

View File

@ -1,5 +1,7 @@
package org.opentcs.kc.udp.Service; package org.opentcs.kc.udp.Service;
import java.util.HashMap;
import org.opentcs.drivers.vehicle.MovementCommand;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
import org.opentcs.kc.udp.agv.param.AgvEvent; import org.opentcs.kc.udp.agv.param.AgvEvent;
import org.opentcs.kc.udp.agv.param.AgvEventConstant; import org.opentcs.kc.udp.agv.param.AgvEventConstant;
@ -11,7 +13,9 @@ import org.opentcs.kc.udp.agv.param.function.navigation.Point;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
public class HybridNavigation extends BaseCommand{ public class HybridNavigation
extends
BaseCommand {
/** /**
* 测试模式true=开启测试false=关闭测试 * 测试模式true=开启测试false=关闭测试
@ -38,6 +42,14 @@ public class HybridNavigation extends BaseCommand{
* 用于定位段在整个任务中的位置目的是区分同一个段ID是否在一个任务中出现多次从1开始奇数递增例如1->3->5->7 * 用于定位段在整个任务中的位置目的是区分同一个段ID是否在一个任务中出现多次从1开始奇数递增例如1->3->5->7
*/ */
private static Integer pathSerialNum = 1; private static Integer pathSerialNum = 1;
/**
* 订单名映射int类型数据.
*/
private static HashMap<String, Integer> orderNameMap = new HashMap<>();
/**
* 订单映射最大订单ID.
*/
private static int currentMaxiOrderId = 0;
/** /**
@ -45,45 +57,37 @@ public class HybridNavigation extends BaseCommand{
* 指令0xAE * 指令0xAE
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent navigationControl(Integer sourcePoint, Integer destinationPoint, Integer pathID, String operation) { public static AgvEvent navigationControl(
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS); Integer sourcePoint, Integer destinationPoint, Integer pathID, String operation
) {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_MIXED_ISSUANCE_TASK);
//TODO 构建 //TODO 构建
Integer orderId = orderID;
// Integer orderId = 1;
//构建point
Action[] pointActions1 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
//,new Action()... 每一个point 可以绑定一个或者多个 action
};
Action[] pointActions2 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
};
// Action[] pointActions3 = new Action[]{
// new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
// };
Integer oldPointSerialNum = pointSerialNum; Integer oldPointSerialNum = pointSerialNum;
pointSerialNum += 2; pointSerialNum += 2;
Point[] points = new Point[]{ Point[] points = new Point[]{
new Point(oldPointSerialNum, sourcePoint, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions1.length),pointActions1), new Point(
new Point(pointSerialNum, destinationPoint, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions2.length),pointActions2) oldPointSerialNum, sourcePoint, 0f, (byte) 0x00, ByteUtils.usintTo1Byte(0), null
// new Point(4, 3, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions3.length),pointActions3) ),
new Point(
pointSerialNum, destinationPoint, 0f, (byte) 0x00, ByteUtils.usintTo1Byte(0), null
)
}; };
//构建path
Action[] pathActions1 = new Action[]{
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
//,new Action()... 每一个path 可以绑定一个或者多个 action
};
// Action[] pathActions2 = new Action[]{
// new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
// };
Path[] paths = new Path[]{ Path[] paths = new Path[]{
new Path(pathSerialNum,pathID,1f,(byte)0x00,(byte)0x00,ByteUtils.usintTo1Byte(pathActions1.length),5f,1f,pathActions1) , new Path(
// new Path(3,2,1f,(byte)0x00,(byte)0x00,ByteUtils.usintTo1Byte(pathActions2.length),5f,1f,pathActions2) , pathSerialNum, pathID, 0f, (byte) 0x00, (byte) 0x01, ByteUtils.usintTo1Byte(0), 1f, 1f, null
),
}; };
NavigationParam navigationParam = new NavigationParam(orderID,taskKey,ByteUtils.usintTo1Byte(points.length),ByteUtils.usintTo1Byte(points.length-1),points,paths); pathSerialNum += 2;
NavigationParam navigationParam = new NavigationParam(
orderID, taskKey, ByteUtils.usintTo1Byte(points.length), ByteUtils.usintTo1Byte(
points.length - 1
), points, paths
);
taskKey++;
agvEvent.setBody(navigationParam.toBytes()); agvEvent.setBody(navigationParam.toBytes());
return agvEvent; return agvEvent;
@ -96,16 +100,24 @@ public class HybridNavigation extends BaseCommand{
* @param destinationPoint 下发终点 * @param destinationPoint 下发终点
* @param operation 执行操作 * @param operation 执行操作
*/ */
public static void command(String orderName, String sourcePoint, String destinationPoint, String operation) { public static void command(
if (TEST_MODEL) { String orderName, String sourcePoint, String destinationPoint, String operation
return; ) {
} // if (TEST_MODEL) {
// return;
// }
Integer newOrderName = Integer.parseInt(orderName); Integer newOrderName = getUniqueOrderID(orderName);
Integer newSourcePoint = Integer.parseInt(sourcePoint); Integer newSourcePoint = Integer.parseInt(sourcePoint);
Integer newDestinationPoint = Integer.parseInt(destinationPoint); Integer newDestinationPoint = Integer.parseInt(destinationPoint);
//拼接起点终点字符串转为Integer类型获取唯一pathID //拼接起点终点字符串转为Integer类型获取唯一pathID
Integer pathID = Integer.parseInt(sourcePoint + destinationPoint); Integer pathID;
if (newSourcePoint <= newDestinationPoint) {
pathID = Integer.parseInt(sourcePoint + destinationPoint);
} else {
pathID = Integer.parseInt(destinationPoint + sourcePoint);
}
System.out.println("pathID:" + pathID);
if (!orderID.equals(newOrderName)) { if (!orderID.equals(newOrderName)) {
//切换订单重置参数 //切换订单重置参数
@ -118,7 +130,8 @@ public class HybridNavigation extends BaseCommand{
RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
if (rcv.isOk()) { if (rcv.isOk()) {
System.out.println("0xAE ok"); System.out.println("0xAE ok");
}else { }
else {
System.out.println(); System.out.println();
System.out.println("0xAE fail"); System.out.println("0xAE fail");
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
@ -127,6 +140,7 @@ public class HybridNavigation extends BaseCommand{
/** /**
* 初始化参数 * 初始化参数
*
* @param newOrderName 新的订单ID * @param newOrderName 新的订单ID
*/ */
private static void initParams(Integer newOrderName) { private static void initParams(Integer newOrderName) {
@ -136,4 +150,34 @@ public class HybridNavigation extends BaseCommand{
pathSerialNum = 1; pathSerialNum = 1;
} }
/**
* 维护订单名对应int类型唯一ID
* @param orderName 订单名
* @return Integer
*/
private static Integer getUniqueOrderID(String orderName){
Integer orderId;
if (orderNameMap.containsKey(orderName)) {
//订单名已存在
orderId = orderNameMap.get(orderName);
} else {
//订单名不存在创建对应映射
currentMaxiOrderId = currentMaxiOrderId + 1;
orderId = currentMaxiOrderId;
orderNameMap.put(orderName, orderId);
}
return orderId;
}
/**
* 任务结束删除唯一orderID.
* @param command 订单
*/
public static void delUniqueOrderID(MovementCommand command){
String orderName = command.getTransportOrder().getName();
orderNameMap.remove(orderName);
}
} }

View File

@ -7,12 +7,9 @@ import org.opentcs.kc.udp.agv.param.function.x14.RobotSetPosition;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class ManualPosition
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 手动定位 0x14
*/
public class ManualPosition extends BaseCommand{
public static AgvEvent manualLocation(double agvX, double agvY, double agvAngle) { public static AgvEvent manualLocation(double agvX, double agvY, double agvAngle) {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ROBOT_SET_POSITION); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ROBOT_SET_POSITION);
@ -34,10 +31,12 @@ public class ManualPosition extends BaseCommand{
if (rcv.isOk()) { if (rcv.isOk()) {
//get and parse value //get and parse value
System.out.println("0x14 ok"); System.out.println("0x14 ok");
}else { }
else {
System.out.println("0x14 failed"); System.out.println("0x14 failed");
} }
}else { }
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
throw new RuntimeException("0x14 failed"); throw new RuntimeException("0x14 failed");

View File

@ -6,19 +6,16 @@ import org.opentcs.kc.udp.agv.param.function.x17.QueryRobotRunStatusRsp;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class QryRobotRunStatus
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 获取AGV运行状态
*/
public class QryRobotRunStatus extends BaseCommand{
/** /**
* decs: 查询机器人运行状态 * decs: 查询机器人运行状态.
* 指令0x17 * 指令0x17
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent queryRobotRunStatus() { public static AgvEvent queryRobotRunStatus() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_RUN_STATUS); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_RUN_STATUS);
return agvEvent; return agvEvent;
@ -31,7 +28,9 @@ public class QryRobotRunStatus extends BaseCommand{
RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
if (rcv.isOk()) { if (rcv.isOk()) {
//QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes()); //QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes());
QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp(rcv.getDataBytes()); QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp(
rcv.getDataBytes()
);
System.out.println(queryRobotRunStatusRsp.toString()); System.out.println(queryRobotRunStatusRsp.toString());
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
@ -39,7 +38,8 @@ public class QryRobotRunStatus extends BaseCommand{
System.out.print(byteToHex(b) + " "); System.out.print(byteToHex(b) + " ");
} }
return queryRobotRunStatusRsp; return queryRobotRunStatusRsp;
}else { }
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
throw new RuntimeException("0x17 fail"); throw new RuntimeException("0x17 fail");

View File

@ -6,20 +6,17 @@ import org.opentcs.kc.udp.agv.param.function.af.QueryRobotStatusRsp;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/**
* @author xzh
* @date 2025/2/21
* @desc 查询机器人状态
*/
public class QryRobotStatus public class QryRobotStatus
extends BaseCommand { extends
BaseCommand {
/** /**
* decs: 查询机器人状态 * decs: 查询机器人状态
* 指令0xAF * 指令0xAF
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent queryStatus() { public static AgvEvent queryStatus() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
return agvEvent; return agvEvent;
@ -31,14 +28,20 @@ public class QryRobotStatus
printInfo(agvEvent); printInfo(agvEvent);
RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent);
if(rcv.isOk()){ if(rcv.isOk()){
QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
System.out.println(); System.out.println();
System.out.println("received transationId : "+ "isok:"+rcv.isOk()); for (byte b:rcv.getValue()){
return queryRobotStatusRsp; System.out.print(byteToHex(b)+" ");
// for (byte b:rcv.getValue()){ }
// System.out.print(byteToHex(b)+" "); System.out.println();
System.out.println("0xAF received transationId : "+ "isok:"+rcv.isOk());
// for (byte c:rcv.getDataBytes()){
// System.out.print(byteToHex(c)+" ");
// } // }
}else { QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
return queryRobotStatusRsp;
}
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
throw new RuntimeException("0xAF fail"); throw new RuntimeException("0xAF fail");

View File

@ -13,31 +13,33 @@ import org.opentcs.kc.udp.agv.param.function.b1.SubscribeRsp;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class SubCargoStatus
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 订阅载货状态
*/ public static final int intervalTime = 1000;
public class SubCargoStatus extends BaseCommand{
/** /**
* decs: 下发订阅信息 * decs: 下发订阅信息
* 指令0xB1 * 指令0xB1
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent issueSubscribe() { public static AgvEvent issueSubscribe() {
List<SubscribeInfo> subscribeInfoList = new ArrayList<>(); List<SubscribeInfo> subscribeInfoList = new ArrayList<>();
// SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xaf,(byte)0x00}, (short) 100,1000); // SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xaf,(byte)0x00}, (short) 100,1000);
SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xb0,(byte)0x00}, (short) 100,1000); SubscribeInfo subscribeInfo = new SubscribeInfo(
new byte[]{(byte) 0xb0, (byte) 0x00}, (short) intervalTime, 10000
);
subscribeInfoList.add(subscribeInfo); subscribeInfoList.add(subscribeInfo);
SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList); SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList);
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION,subscribeParam.toBytes()); AgvEvent agvEvent = new AgvEvent(
AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION, subscribeParam.toBytes()
);
return agvEvent; return agvEvent;
} }
public static void command() public static void command() {
{
// 0xB1(订阅信息) // 0xB1(订阅信息)
AgvEvent agvEvent = issueSubscribe(); AgvEvent agvEvent = issueSubscribe();
printInfo(agvEvent); printInfo(agvEvent);
@ -49,24 +51,26 @@ public class SubCargoStatus extends BaseCommand{
SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes()); SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes());
if (subscribeRsp.isOk()) { if (subscribeRsp.isOk()) {
//... //...
}else { }
else {
//... //...
} }
}else { }
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
} }
} }
//订阅执行操作 //订阅执行操作
public void subscribe0xB0Operate(String name,QueryCargoStatusRsp queryCargoStatusRsp) public void subscribe0xB0Operate(String name, QueryCargoStatusRsp queryCargoStatusRsp) {
{
// Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name); // Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
//修改载货状态 //修改载货状态
if (queryCargoStatusRsp.isCargo == 0) { if (queryCargoStatusRsp.isCargo == 0) {
//未载货 //未载货
} else if (queryCargoStatusRsp.isCargo == 1) { }
else if (queryCargoStatusRsp.isCargo == 1) {
//载货 //载货
} }
} }

View File

@ -10,27 +10,29 @@ import org.opentcs.kc.udp.agv.param.function.b1.SubscribeRsp;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class SubRobotStatue
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 订阅机器人状态
*/
public class SubRobotStatue extends BaseCommand {
public static final int intervalTime = 1000;
/** /**
* decs: 下发订阅信息 * decs: 下发订阅信息
* 指令0xB1 * 指令0xB1
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent issueSubscribe() { public static AgvEvent issueSubscribe() {
List<SubscribeInfo> subscribeInfoList = new ArrayList<>(); List<SubscribeInfo> subscribeInfoList = new ArrayList<>();
SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xaf,(byte)0x00}, (short) 100,1000); SubscribeInfo subscribeInfo = new SubscribeInfo(
new byte[]{(byte) 0xaf, (byte) 0x00}, (short) intervalTime, 10000
);
// SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xb0,(byte)0x00}, (short) 100,1000); // SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xb0,(byte)0x00}, (short) 100,1000);
subscribeInfoList.add(subscribeInfo); subscribeInfoList.add(subscribeInfo);
SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList); SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList);
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION,subscribeParam.toBytes()); AgvEvent agvEvent = new AgvEvent(
AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION, subscribeParam.toBytes()
);
return agvEvent; return agvEvent;
} }
@ -46,10 +48,12 @@ public class SubRobotStatue extends BaseCommand {
SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes()); SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes());
if (subscribeRsp.isOk()) { if (subscribeRsp.isOk()) {
//... //...
}else { }
else {
//... //...
} }
}else { }
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
} }

View File

@ -12,24 +12,23 @@ import org.opentcs.kc.udp.agv.param.function.write.WriteValueMember;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class SwitchAutomaticMode
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 切换自动模式
*/
public class SwitchAutomaticMode extends BaseCommand{
/** /**
* decs: write操作 * decs: write操作
* 指令0x03 * 指令0x03
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent writeValue() { public static AgvEvent writeValue() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE);
List<WriteValueMember> valueMemberList = new ArrayList<>(); List<WriteValueMember> valueMemberList = new ArrayList<>();
WriteValueMember valueMember1 = new WriteValueMember(Short.valueOf("1"),Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)); WriteValueMember valueMember1 = new WriteValueMember(
Short.valueOf("1"), Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)
);
valueMemberList.add(valueMember1); valueMemberList.add(valueMember1);
List<WriteStrValue> strValueList = new ArrayList<>(); List<WriteStrValue> strValueList = new ArrayList<>();
@ -54,10 +53,12 @@ public class SwitchAutomaticMode extends BaseCommand{
if (rcv.isOk()) { if (rcv.isOk()) {
//get and parse value //get and parse value
System.out.println("write ok"); System.out.println("write ok");
}else { }
else {
System.out.println("write failed"); System.out.println("write failed");
} }
}else { }
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
} }

View File

@ -12,24 +12,23 @@ import org.opentcs.kc.udp.agv.param.function.write.WriteValueMember;
import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage; import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class SwitchManualMode
* @author xzh extends
* @date 2025/2/21 BaseCommand {
* @desc 切换手动模式
*/
public class SwitchManualMode extends BaseCommand{
/** /**
* decs: write操作 * decs: write操作
* 指令0x03 * 指令0x03
* author: caixiang * author: caixiang
* date: 2025/1/17 16:25 * date: 2025/1/17 16:25
* */ */
public static AgvEvent writeValue() { public static AgvEvent writeValue() {
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE); AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE);
List<WriteValueMember> valueMemberList = new ArrayList<>(); List<WriteValueMember> valueMemberList = new ArrayList<>();
WriteValueMember valueMember1 = new WriteValueMember(Short.valueOf("0"),Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)); WriteValueMember valueMember1 = new WriteValueMember(
Short.valueOf("0"), Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)
);
valueMemberList.add(valueMember1); valueMemberList.add(valueMember1);
List<WriteStrValue> strValueList = new ArrayList<>(); List<WriteStrValue> strValueList = new ArrayList<>();
@ -54,10 +53,12 @@ public class SwitchManualMode extends BaseCommand{
if (rcv.isOk()) { if (rcv.isOk()) {
//get and parse value //get and parse value
System.out.println("write ok"); System.out.println("write ok");
}else { }
else {
System.out.println("write failed"); System.out.println("write failed");
} }
}else { }
else {
System.out.println(); System.out.println();
System.out.println("received transationId : " + "isok:" + rcv.isOk()); System.out.println("received transationId : " + "isok:" + rcv.isOk());
} }

View File

@ -7,7 +7,9 @@ import org.opentcs.kc.udp.io.UDPClient;
/** /**
* 作者蔡翔 * 作者蔡翔
*/ */
public class AgvUdpChannelInitializer extends ChannelInitializer<NioDatagramChannel> { public class AgvUdpChannelInitializer
extends
ChannelInitializer<NioDatagramChannel> {
private UDPClient client; private UDPClient client;
public AgvUdpChannelInitializer(UDPClient client) { public AgvUdpChannelInitializer(UDPClient client) {
@ -17,7 +19,8 @@ public class AgvUdpChannelInitializer extends ChannelInitializer<NioDatagramChan
@Override @Override
protected void initChannel(NioDatagramChannel channel) throws Exception { protected void initChannel(NioDatagramChannel channel)
throws Exception {
// Modbus // Modbus
// 在管道中添加我们自己的接收数据实现方法 // 在管道中添加我们自己的接收数据实现方法
//todo 到时候这里改成 FixedLengthFrameDecoder 资料https://www.cnblogs.com/java-chen-hao/p/11571229.html //todo 到时候这里改成 FixedLengthFrameDecoder 资料https://www.cnblogs.com/java-chen-hao/p/11571229.html

View File

@ -11,12 +11,9 @@ import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.opentcs.kc.udp.io.UDPClient; import org.opentcs.kc.udp.io.UDPClient;
/** public class AgvUdpDecode
* @Desc: "" extends
* @Author: caixiang SimpleChannelInboundHandler<DatagramPacket> {
* @DATE: 2024-06-06 10:45
*/
public class AgvUdpDecode extends SimpleChannelInboundHandler<DatagramPacket> {
private UDPClient client; private UDPClient client;
@ -38,7 +35,9 @@ public class AgvUdpDecode extends SimpleChannelInboundHandler<DatagramPacket> {
int dataLength = in.getShortLE(24); int dataLength = in.getShortLE(24);
if (dataLength < 0) { if (dataLength < 0) {
throw new Exception("bodyLength [" + dataLength + "] is not right, remote:" + ctx.channel().remoteAddress()); throw new Exception(
"bodyLength [" + dataLength + "] is not right, remote:" + ctx.channel().remoteAddress()
);
} }
int neededLength = HEADER_SIZE + dataLength; int neededLength = HEADER_SIZE + dataLength;
@ -49,7 +48,8 @@ public class AgvUdpDecode extends SimpleChannelInboundHandler<DatagramPacket> {
if (isDataEnough < 0) { if (isDataEnough < 0) {
// 不够消息体长度(剩下的buffe组不了消息体),重新去组包 // 不够消息体长度(剩下的buffe组不了消息体),重新去组包
throw new Exception("readed bytes < content length"); throw new Exception("readed bytes < content length");
}else { }
else {
//todo这里重写subscribe 的逻辑,注意要区分是 订阅的还是 主动请求的 //todo这里重写subscribe 的逻辑,注意要区分是 订阅的还是 主动请求的
//组包成功 //组包成功
@ -61,19 +61,18 @@ public class AgvUdpDecode extends SimpleChannelInboundHandler<DatagramPacket> {
byte commandCode = body[21]; byte commandCode = body[21];
if (body[18] == (byte) 0x00 && body[19] == (byte) 0x00) { if (body[18] == (byte) 0x00 && body[19] == (byte) 0x00) {
//获取响应IP //获取响应IP
InetSocketAddress sender = msg.sender(); InetSocketAddress sender = msg.sender();
String hostAddress = sender.getAddress().getHostAddress(); String hostAddress = sender.getAddress().getHostAddress();
if(commandCode == (byte)0xAF ){ if (commandCode == (byte) 0xAF || commandCode == (byte) 0xB0) {
client.subscribe0xAF(new RcvEventPackage(body[22],body)); client.subscribeKC(new RcvEventPackage(body[22], body), body);
}else if(commandCode == (byte)0xB0){ }
client.subscribe0xB0(new RcvEventPackage(body[22],body)); else {
}else {
SendedList.set(uuid, mbPackage); SendedList.set(uuid, mbPackage);
} }
}else { }
else {
SendedList.set(uuid, mbPackage); SendedList.set(uuid, mbPackage);
} }
} }

View File

@ -8,12 +8,12 @@ import org.opentcs.kc.common.byteutils.ByteUtil;
// import org.opentcs.kc.common.byteutils.ByteUtil; // import org.opentcs.kc.common.byteutils.ByteUtil;
// import org.opentcs.kc.common.byteutils.ByteUtil; // import org.opentcs.kc.common.byteutils.ByteUtil;
/** public class AgvEvent
* @Desc: "" extends
* @Author: caixiang AgvEventHeader
* @DATE: 2024/12/27 15:59 implements
*/ IAgvEvent,
public class AgvEvent extends AgvEventHeader implements IAgvEvent, Serializable { Serializable {
private byte[] bodyLength; private byte[] bodyLength;
private byte[] retain; private byte[] retain;
private byte[] body; private byte[] body;
@ -27,6 +27,7 @@ public class AgvEvent extends AgvEventHeader implements IAgvEvent, Serializable
retain = new byte[]{0x00, 0x00}; retain = new byte[]{0x00, 0x00};
body = new byte[]{}; body = new byte[]{};
} }
public AgvEvent(Byte commandCode, byte[] body) { public AgvEvent(Byte commandCode, byte[] body) {
super(commandCode); super(commandCode);
//初始化 //初始化

View File

@ -1,13 +1,10 @@
package org.opentcs.kc.udp.agv.param; package org.opentcs.kc.udp.agv.param;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2024/12/27 10:19
*/
public class AgvEventConstant { public class AgvEventConstant {
public static final byte[] AuthorizationCode = new byte[]{ (byte)0xd4 , (byte)0x97 , (byte)0x44 , (byte)0x9c , (byte)0xcb , (byte)0xcf , (byte)0x0b , (byte)0x4c , (byte)0x95 , (byte)0x51 , (byte)0xd8 , (byte)0x61 , (byte)0x70 , (byte)0xf1 , (byte)0xe7 , (byte)0x94}; public static final byte[] AuthorizationCode = new byte[]{(byte) 0xd4, (byte) 0x97, (byte) 0x44,
(byte) 0x9c, (byte) 0xcb, (byte) 0xcf, (byte) 0x0b, (byte) 0x4c, (byte) 0x95, (byte) 0x51,
(byte) 0xd8, (byte) 0x61, (byte) 0x70, (byte) 0xf1, (byte) 0xe7, (byte) 0x94};
public static final byte VersionNum = 0x01; public static final byte VersionNum = 0x01;

View File

@ -6,11 +6,6 @@ import java.util.List;
import org.opentcs.kc.common.CaffeineUtil; import org.opentcs.kc.common.CaffeineUtil;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2024-06-07 13:29
*/
public class AgvEventHeader { public class AgvEventHeader {

View File

@ -1,10 +1,12 @@
package org.opentcs.kc.udp.agv.param; package org.opentcs.kc.udp.agv.param;
import org.opentcs.kc.common.byteutils.ByteUtil;
import org.opentcs.kc.common.Package; import org.opentcs.kc.common.Package;
import org.opentcs.kc.common.byteutils.ByteUtil;
public interface IAgvEvent { public interface IAgvEvent {
//read sended //read sended
public Package toBytes(); public Package toBytes();
//write sended //write sended
public Package toBytes(Object newValue); public Package toBytes(Object newValue);

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/21 10:03
*/
public class AbnormalEventStatusInfo { public class AbnormalEventStatusInfo {
private byte[] src; private byte[] src;
//事件码,2个字节 //事件码,2个字节

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/21 10:38
*/
public class ActionInfo { public class ActionInfo {
private byte[] src; private byte[] src;
//动作 ID,4个字节 //动作 ID,4个字节

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 16:28
*/
public class BatteryStatusInfo { public class BatteryStatusInfo {
//src //src
private byte[] src; private byte[] src;
@ -20,6 +15,7 @@ public class BatteryStatusInfo {
public byte chargingState; public byte chargingState;
//预留,7个字节 //预留,7个字节
public byte[] remain; public byte[] remain;
public BatteryStatusInfo(byte[] src) { public BatteryStatusInfo(byte[] src) {
this.src = src; this.src = src;
this.batteryPercentage = ByteUtils.bytesToFloat(src, 0); this.batteryPercentage = ByteUtils.bytesToFloat(src, 0);

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 14:56
*/
public class LocationStatusInfo { public class LocationStatusInfo {
private byte[] src; private byte[] src;
//4个字节, 全局x,单位 m //4个字节, 全局x,单位 m

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 15:49
*/
public class PathStateSequence { public class PathStateSequence {
//src //src
private byte[] src; private byte[] src;
@ -14,6 +9,7 @@ public class PathStateSequence {
public Integer serialNumber; public Integer serialNumber;
//序列号 //序列号
public Integer pathId; public Integer pathId;
public PathStateSequence(byte[] src) { public PathStateSequence(byte[] src) {
this.src = src; this.src = src;
this.serialNumber = ByteUtils.bytesToInt(src, 0); this.serialNumber = ByteUtils.bytesToInt(src, 0);

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 15:49
*/
public class PointStateSequence { public class PointStateSequence {
//src //src
private byte[] src; private byte[] src;
@ -14,6 +9,7 @@ public class PointStateSequence {
public Integer serialNumber; public Integer serialNumber;
//序列号 //序列号
public Integer pointId; public Integer pointId;
public PointStateSequence(byte[] src) { public PointStateSequence(byte[] src) {
this.src = src; this.src = src;
this.serialNumber = ByteUtils.bytesToInt(src, 0); this.serialNumber = ByteUtils.bytesToInt(src, 0);

View File

@ -1,13 +1,9 @@
package org.opentcs.kc.udp.agv.param.function.af; package org.opentcs.kc.udp.agv.param.function.af;
import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 14:55
*/
public class QueryRobotStatusRsp { public class QueryRobotStatusRsp {
private byte[] src; private byte[] src;
public byte abnormal_size; public byte abnormal_size;
@ -22,6 +18,9 @@ public class QueryRobotStatusRsp {
public List<ActionInfo> actionInfoList; public List<ActionInfo> actionInfoList;
public QueryRobotStatusRsp(byte[] src) { public QueryRobotStatusRsp(byte[] src) {
if (src == null) {
throw new RuntimeException("method_QueryRobotStatusRsp_params_src_is_NUll");
}
this.src = src; this.src = src;
this.abnormal_size = src[0]; this.abnormal_size = src[0];
this.action_size = src[1]; this.action_size = src[1];
@ -36,13 +35,29 @@ public class QueryRobotStatusRsp {
this.batteryStatusInfo = new BatteryStatusInfo(ByteUtils.copyBytes(src, 56 + taskByteSize, 20)); this.batteryStatusInfo = new BatteryStatusInfo(ByteUtils.copyBytes(src, 56 + taskByteSize, 20));
if (this.abnormal_size > 0) { if (this.abnormal_size > 0) {
if (this.abnormalEventStatusInfoList == null) {
this.abnormalEventStatusInfoList = new ArrayList<>();
}
for (int i = 0; i < this.abnormal_size; i++) { for (int i = 0; i < this.abnormal_size; i++) {
this.abnormalEventStatusInfoList.add(new AbnormalEventStatusInfo(ByteUtils.copyBytes(src,56+taskByteSize+20+12*i,12))); this.abnormalEventStatusInfoList.add(
new AbnormalEventStatusInfo(
ByteUtils.copyBytes(src, 56 + taskByteSize + 20 + 12 * i, 12)
)
);
} }
} }
if (this.action_size > 0) { if (this.action_size > 0) {
if (this.actionInfoList == null) {
this.actionInfoList = new ArrayList<>();
}
for (int i = 0; i < this.action_size; i++) { for (int i = 0; i < this.action_size; i++) {
this.actionInfoList.add(new ActionInfo(ByteUtils.copyBytes(src,56+taskByteSize+20+12*this.abnormal_size+12*i,12))); this.actionInfoList.add(
new ActionInfo(
ByteUtils.copyBytes(
src, 56 + taskByteSize + 20 + 12 * this.abnormal_size + 12 * i, 12
)
)
);
} }
} }

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 15:22
*/
public class RunningStatusInfo { public class RunningStatusInfo {
private byte[] src; private byte[] src;
//4个字节, 轴x 速度,单位 m/s //4个字节, 轴x 速度,单位 m/s

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.af;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/20 15:22
*/
public class TaskStatusInfo { public class TaskStatusInfo {
private byte[] src; private byte[] src;
//订单 ID //订单 ID
@ -41,9 +36,10 @@ public class TaskStatusInfo {
if (edgeStatusNum > 0) { if (edgeStatusNum > 0) {
this.pathStatusInfo = new PathStateSequence[edgeStatusNum]; this.pathStatusInfo = new PathStateSequence[edgeStatusNum];
for (int i = 0; i < edgeStatusNum; i++) { for (int i = 0; i < edgeStatusNum; i++) {
this.pathStatusInfo[i] = new PathStateSequence(ByteUtils.copyBytes(src, 12 + pointStatusNum*8 + 8 * pointStatusNum + 8 * i, 8)); this.pathStatusInfo[i] = new PathStateSequence(
ByteUtils.copyBytes(src, 12 + pointStatusNum * 8 + 8 * pointStatusNum + 8 * i, 8)
);
} }
} }
} }
} }

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.b0;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/23 13:34
*/
public class QueryCargoStatusRsp { public class QueryCargoStatusRsp {
//src //src
private byte[] src; private byte[] src;

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.b1;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/23 14:30
*/
public class SubscribeInfo { public class SubscribeInfo {
//站控协议命令码2个字节 //站控协议命令码2个字节
public byte[] commandCode; public byte[] commandCode;

View File

@ -4,16 +4,12 @@ import java.security.SecureRandom;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/1/23 14:23
*/
public class SubscribeParam { public class SubscribeParam {
private byte[] src; private byte[] src;
private List<SubscribeInfo> subscribeInfoList; private List<SubscribeInfo> subscribeInfoList;
//uuid,64个字节 //uuid,64个字节
private byte[] uuid; private byte[] uuid;
public SubscribeParam(List<SubscribeInfo> subscribeInfoList) { public SubscribeParam(List<SubscribeInfo> subscribeInfoList) {
this.subscribeInfoList = subscribeInfoList; this.subscribeInfoList = subscribeInfoList;
this.uuid = generate64ByteUUID(); this.uuid = generate64ByteUUID();

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.b1;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/5 14:21
*/
public class SubscribeRsp { public class SubscribeRsp {
//源数组 //源数组
private byte[] src; private byte[] src;
@ -16,6 +11,7 @@ public class SubscribeRsp {
private byte errCode; private byte errCode;
//reserved 3个字节 //reserved 3个字节
private byte[] reserved; private byte[] reserved;
public SubscribeRsp(byte[] src) { public SubscribeRsp(byte[] src) {
this.src = src; this.src = src;
this.uuid = ByteUtils.copyOfRange(src, 0, 64); this.uuid = ByteUtils.copyOfRange(src, 0, 64);
@ -26,7 +22,8 @@ public class SubscribeRsp {
public boolean isOk() { public boolean isOk() {
if (this.errCode == 0) { if (this.errCode == 0) {
return true; return true;
}else { }
else {
return false; return false;
} }
} }

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/8 10:05
*/
public class Action { public class Action {
//动作类型,2个字节 //动作类型,2个字节
private byte[] actionType; private byte[] actionType;
@ -26,7 +21,9 @@ public class Action {
private byte[] paramContent; private byte[] paramContent;
public Action(byte actionType, byte actionParallel, Integer actionId, Integer paramSize, byte[] paramContent) { public Action(
byte actionType, byte actionParallel, Integer actionId, Integer paramSize, byte[] paramContent
) {
this.actionType = new byte[]{actionType, (byte) 0x00}; this.actionType = new byte[]{actionType, (byte) 0x00};
this.actionParallel = actionParallel; this.actionParallel = actionParallel;
this.actionRetain = (byte) 0x00; this.actionRetain = (byte) 0x00;

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/10 8:56
*/
public class ActionSet { public class ActionSet {
public static void main(String[] args) { public static void main(String[] args) {
byte[] stop = stop0x01(1, (byte) 0x01); byte[] stop = stop0x01(1, (byte) 0x01);
@ -56,9 +51,11 @@ public class ActionSet {
* desc:叉齿升降 * desc:叉齿升降
* 支持的命令0xAE 0xB2 * 支持的命令0xAE 0xB2
* *
* */ */
public static byte[] forkliftElevation0x12(float lifitingHeight,byte hightMean,byte moveType, byte taskOperationType){ public static byte[] forkliftElevation0x12(
float lifitingHeight, byte hightMean, byte moveType, byte taskOperationType
) {
ByteBuf byteBuf = Unpooled.buffer(8); ByteBuf byteBuf = Unpooled.buffer(8);
byteBuf.writeBytes(ByteUtils.floatToBytes(lifitingHeight)); byteBuf.writeBytes(ByteUtils.floatToBytes(lifitingHeight));
byteBuf.writeByte(hightMean); byteBuf.writeByte(hightMean);

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: "0xAE 导航参数"
* @Author: caixiang
* @DATE: 2024/12/30 15:44
*/
public class NavigationParam { public class NavigationParam {
//订单 ID,4个字节 ,Integer,从1开始依次累加 //订单 ID,4个字节 ,Integer,从1开始依次累加
private byte[] orderId; private byte[] orderId;
@ -25,7 +20,9 @@ public class NavigationParam {
//任务中路径信息结构体长度 pathNum //任务中路径信息结构体长度 pathNum
private Path[] paths; private Path[] paths;
public NavigationParam(Integer orderId, Integer taskKey, byte pointNum, byte pathNum, Point[] points, Path[] paths) { public NavigationParam(
Integer orderId, Integer taskKey, byte pointNum, byte pathNum, Point[] points, Path[] paths
) {
this.orderId = ByteUtils.intToBytes(orderId, 1); this.orderId = ByteUtils.intToBytes(orderId, 1);
this.taskKey = ByteUtils.intToBytes(taskKey, 1); this.taskKey = ByteUtils.intToBytes(taskKey, 1);
this.pointNum = pointNum; this.pointNum = pointNum;

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/8 9:39
*/
public class Path { public class Path {
//序列号,4个字节,Integer,用于定位段在整个任务中的位置 1 开始奇数递增 135......point 2 4 6这样path 和point就可以结合起来了以区分同一个段 ID 在任务中是否多次出现 //序列号,4个字节,Integer,用于定位段在整个任务中的位置 1 开始奇数递增 135......point 2 4 6这样path 和point就可以结合起来了以区分同一个段 ID 在任务中是否多次出现
private byte[] serialNum; private byte[] serialNum;
@ -36,7 +31,10 @@ public class Path {
private Action[] actions; private Action[] actions;
public Path(Integer serialNum, Integer pathId, float angle, byte isSpecifyAngle, byte drivePose, byte pathActionSize, float maxSpeed, float maxAngularSpeed, Action[] actions) { public Path(
Integer serialNum, Integer pathId, float angle, byte isSpecifyAngle, byte drivePose,
byte pathActionSize, float maxSpeed, float maxAngularSpeed, Action[] actions
) {
this.serialNum = ByteUtils.intToBytes(serialNum, 1); this.serialNum = ByteUtils.intToBytes(serialNum, 1);
this.pathId = ByteUtils.intToBytes(pathId, 1); this.pathId = ByteUtils.intToBytes(pathId, 1);
this.angle = ByteUtils.floatToBytes(angle); this.angle = ByteUtils.floatToBytes(angle);
@ -62,9 +60,11 @@ public class Path {
byteBuf.writeBytes(maxSpeed); byteBuf.writeBytes(maxSpeed);
byteBuf.writeBytes(maxAngularSpeed); byteBuf.writeBytes(maxAngularSpeed);
byteBuf.writeBytes(pathRetain2); byteBuf.writeBytes(pathRetain2);
if (actions != null) {
for (Action action : actions) { for (Action action : actions) {
byteBuf.writeBytes(action.toBytes()); byteBuf.writeBytes(action.toBytes());
} }
}
int i = byteBuf.writerIndex(); int i = byteBuf.writerIndex();
byte[] bytes = new byte[i]; byte[] bytes = new byte[i];
byteBuf.readBytes(bytes); byteBuf.readBytes(bytes);

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/8 9:39
*/
public class Point { public class Point {
//序列号,4个字节,Integer,用于定位点在整个任务中的位置 0 开始偶数递增 0246......以区分同一个点 ID 在任务中是否多次出现 //序列号,4个字节,Integer,用于定位点在整个任务中的位置 0 开始偶数递增 0246......以区分同一个点 ID 在任务中是否多次出现
private byte[] serialNum; private byte[] serialNum;
@ -25,13 +20,17 @@ public class Point {
//任务中点上动作结构体,这里数组的长度是 pointActionSize 长度 //任务中点上动作结构体,这里数组的长度是 pointActionSize 长度
private Action[] actions; private Action[] actions;
public Point(Integer serialNum, Integer pointId, float angle, byte isSpecifyAngle, byte pointActionSize, Action[] actions) { public Point(
Integer serialNum, Integer pointId, float angle, byte isSpecifyAngle, byte pointActionSize,
Action[] actions
) {
this.serialNum = ByteUtils.intToBytes(serialNum, 1); this.serialNum = ByteUtils.intToBytes(serialNum, 1);
this.pointId = ByteUtils.intToBytes(pointId, 1); this.pointId = ByteUtils.intToBytes(pointId, 1);
this.angle = ByteUtils.floatToBytes(angle); this.angle = ByteUtils.floatToBytes(angle);
this.isSpecifyAngle = isSpecifyAngle; this.isSpecifyAngle = isSpecifyAngle;
this.pointActionSize = pointActionSize; this.pointActionSize = pointActionSize;
this.pointRetain = new byte[]{(byte)0x00, (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00}; this.pointRetain = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
(byte) 0x00};
this.actions = actions; this.actions = actions;
} }
@ -43,9 +42,11 @@ public class Point {
byteBuf.writeByte(isSpecifyAngle); byteBuf.writeByte(isSpecifyAngle);
byteBuf.writeByte(pointActionSize); byteBuf.writeByte(pointActionSize);
byteBuf.writeBytes(pointRetain); byteBuf.writeBytes(pointRetain);
if (actions != null) {
for (Action action : actions) { for (Action action : actions) {
byteBuf.writeBytes(action.toBytes()); byteBuf.writeBytes(action.toBytes());
} }
}
int i = byteBuf.writerIndex(); int i = byteBuf.writerIndex();
byte[] bytes = new byte[i]; byte[] bytes = new byte[i];
byteBuf.readBytes(bytes); byteBuf.readBytes(bytes);

View File

@ -4,16 +4,12 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.opentcs.kc.common.byteutils.ByteUtil; import org.opentcs.kc.common.byteutils.ByteUtil;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2024/12/30 15:44
*/
public class ReadParam { public class ReadParam {
private byte valueNum; private byte valueNum;
private byte[] retain; private byte[] retain;
private byte[] valueId; private byte[] valueId;
private byte[] readStrValues; private byte[] readStrValues;
public ReadParam(byte[] valueId, List<ReadStrValue> rvalues) { public ReadParam(byte[] valueId, List<ReadStrValue> rvalues) {
// 这里的valueId 也是 header里面的 transationId // 这里的valueId 也是 header里面的 transationId
valueNum = ByteUtil.intTo1Byte(rvalues.size()); valueNum = ByteUtil.intTo1Byte(rvalues.size());

View File

@ -2,11 +2,6 @@ package org.opentcs.kc.udp.agv.param.function.read;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/5 14:55
*/
public class ReadRsp { public class ReadRsp {
//源数组 //源数组
private byte[] src; private byte[] src;
@ -30,7 +25,8 @@ public class ReadRsp {
public boolean isOk() { public boolean isOk() {
if (valueByteLength <= 0) { if (valueByteLength <= 0) {
return false; return false;
}else { }
else {
return true; return true;
} }
} }

View File

@ -4,17 +4,13 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.opentcs.kc.common.byteutils.ByteUtil; import org.opentcs.kc.common.byteutils.ByteUtil;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2024/12/30 15:46
*/
public class ReadStrValue { public class ReadStrValue {
//变量名16个字节( 以这个变量名来定位变量的) //变量名16个字节( 以这个变量名来定位变量的)
private byte[] varName; private byte[] varName;
//成员变量数量4个字节 //成员变量数量4个字节
private byte[] memberVarNum; private byte[] memberVarNum;
private byte[] memberList; private byte[] memberList;
public ReadStrValue(String varName, Integer memberVarNum, List<ReadValueMember> memberList) { public ReadStrValue(String varName, Integer memberVarNum, List<ReadValueMember> memberList) {
this.varName = ByteUtil.stringTo16Byte(varName); this.varName = ByteUtil.stringTo16Byte(varName);
this.memberVarNum = ByteUtil.intToBytes(memberVarNum); this.memberVarNum = ByteUtil.intToBytes(memberVarNum);
@ -27,6 +23,7 @@ public class ReadStrValue {
this.memberList[i] = bytes.get(i); this.memberList[i] = bytes.get(i);
} }
} }
public ReadStrValue(String varName) { public ReadStrValue(String varName) {
this.varName = ByteUtil.stringTo16Byte(varName); this.varName = ByteUtil.stringTo16Byte(varName);
this.memberVarNum = ByteUtil.intToBytes(0); this.memberVarNum = ByteUtil.intToBytes(0);

View File

@ -4,11 +4,6 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.opentcs.kc.common.byteutils.ByteUtil; import org.opentcs.kc.common.byteutils.ByteUtil;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2024/12/30 15:49
*/
public class ReadValueMember { public class ReadValueMember {
//偏移值就是以这个变量的起始点为基准偏移几个字节来读取数组里的后面几个变量基本上用于数组变量单体变量用不着 2个字节 //偏移值就是以这个变量的起始点为基准偏移几个字节来读取数组里的后面几个变量基本上用于数组变量单体变量用不着 2个字节
private byte[] offsetValue; private byte[] offsetValue;

View File

@ -5,11 +5,6 @@ import io.netty.buffer.Unpooled;
import java.util.List; import java.util.List;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/5 16:41
*/
public class WriteParam { public class WriteParam {
//变量数量 1个字节 ,最大只支持 15 个变量 //变量数量 1个字节 ,最大只支持 15 个变量
private byte valueNum; private byte valueNum;
@ -17,6 +12,7 @@ public class WriteParam {
private byte[] retain; private byte[] retain;
//这里的length 就是 valueNum //这里的length 就是 valueNum
private List<WriteStrValue> values; private List<WriteStrValue> values;
public WriteParam(Integer valueNum, List<WriteStrValue> values) { public WriteParam(Integer valueNum, List<WriteStrValue> values) {
this.valueNum = ByteUtils.usintTo1Byte(valueNum); this.valueNum = ByteUtils.usintTo1Byte(valueNum);
this.retain = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00}; this.retain = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00};

View File

@ -5,11 +5,6 @@ import io.netty.buffer.Unpooled;
import java.util.List; import java.util.List;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/5 16:43
*/
public class WriteStrValue { public class WriteStrValue {
//变量名 16个字节 //变量名 16个字节
private String valueName; private String valueName;

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/5 16:44
*/
public class WriteValueMember { public class WriteValueMember {
//变量成员偏移 2个字节 //变量成员偏移 2个字节
private byte[] valueOffset; private byte[] valueOffset;
@ -16,6 +11,7 @@ public class WriteValueMember {
private byte[] valueLength; private byte[] valueLength;
//变量成员值 4个字节 //变量成员值 4个字节
private byte[] newValue; private byte[] newValue;
public WriteValueMember(Short valueOffset, Short valueLength, byte[] newValue) { public WriteValueMember(Short valueOffset, Short valueLength, byte[] newValue) {
this.valueOffset = ByteUtils.shortToBytes(valueOffset); this.valueOffset = ByteUtils.shortToBytes(valueOffset);
this.valueLength = ByteUtils.shortToBytes(valueLength); this.valueLength = ByteUtils.shortToBytes(valueLength);

View File

@ -4,11 +4,6 @@ import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled; import io.netty.buffer.Unpooled;
import org.opentcs.kc.common.byteutils.ByteUtil; import org.opentcs.kc.common.byteutils.ByteUtil;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/7 9:21
*/
public class RobotSetPosition { public class RobotSetPosition {
//机器人 x 坐标 ,8 个字节 //机器人 x 坐标 ,8 个字节
private byte[] robotX; private byte[] robotX;
@ -22,6 +17,7 @@ public class RobotSetPosition {
this.robotY = ByteUtil.doubleToBytes(robotY); this.robotY = ByteUtil.doubleToBytes(robotY);
this.robotAngle = ByteUtil.doubleToBytes(robotAngle); this.robotAngle = ByteUtil.doubleToBytes(robotAngle);
} }
public byte[] toBytes() { public byte[] toBytes() {
ByteBuf byteBuf = Unpooled.buffer(24); ByteBuf byteBuf = Unpooled.buffer(24);
byteBuf.writeBytes(robotX); byteBuf.writeBytes(robotX);

View File

@ -3,11 +3,6 @@ package org.opentcs.kc.udp.agv.param.function.x17;
import java.util.Arrays; import java.util.Arrays;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2025/2/7 9:43
*/
public class QueryRobotRunStatusRsp { public class QueryRobotRunStatusRsp {
//本体温度 ,8个字节 ,double //本体温度 ,8个字节 ,double
private double temp; private double temp;

View File

@ -4,11 +4,6 @@ package org.opentcs.kc.udp.agv.param.rsp;
import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.common.byteutils.ByteUtils;
import org.opentcs.kc.udp.agv.param.AgvEventHeader; import org.opentcs.kc.udp.agv.param.AgvEventHeader;
/**
* @Desc: "通用的数据传输底层类"
* @Author: caixiang
* @DATE: 2022/10/18 16:22
*/
public class RcvEventPackage { public class RcvEventPackage {
private boolean isOk; private boolean isOk;
@ -22,19 +17,26 @@ public class RcvEventPackage {
private String getContent(byte i) { private String getContent(byte i) {
if (i == 0x00) { if (i == 0x00) {
return "成功执行"; return "成功执行";
}else if(i==0x01){ }
else if (i == 0x01) {
return "执行失败,原因未知"; return "执行失败,原因未知";
}else if(i==0x02){ }
else if (i == 0x02) {
return "服务码错误"; return "服务码错误";
}else if(i==0x03){ }
else if (i == 0x03) {
return "命令码错误"; return "命令码错误";
}else if(i==0x04){ }
else if (i == 0x04) {
return "报文头部错误"; return "报文头部错误";
}else if(i==0x80){ }
else if (i == 0x80) {
return "无法执行命令,因为当前车辆导航状态与命令冲突"; return "无法执行命令,因为当前车辆导航状态与命令冲突";
}else if(i==0xFF){ }
else if (i == 0xFF) {
return "协议授权码错误"; return "协议授权码错误";
}else { }
else {
return "未知错误"; return "未知错误";
} }
@ -45,12 +47,14 @@ public class RcvEventPackage {
this.isOk = true; this.isOk = true;
this.header = new AgvEventHeader(ByteUtils.copyBytes(value, 0, 28)); this.header = new AgvEventHeader(ByteUtils.copyBytes(value, 0, 28));
this.dataBytes = ByteUtils.copyBytes(value, 28, value.length - 28); this.dataBytes = ByteUtils.copyBytes(value, 28, value.length - 28);
}else { }
else {
this.isOk = false; this.isOk = false;
} }
this.value = value; this.value = value;
this.content = getContent(executionCode); this.content = getContent(executionCode);
} }
public RcvEventPackage() { public RcvEventPackage() {
} }

View File

@ -9,6 +9,7 @@ import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel; import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.HashMap;
import java.util.Set; import java.util.Set;
import org.opentcs.access.KernelServicePortal; import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.rmi.KernelServicePortalBuilder; import org.opentcs.access.rmi.KernelServicePortalBuilder;
@ -27,21 +28,17 @@ import org.opentcs.kc.udp.agv.param.rsp.RcvEventPackage;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
/**
* @Desc: ""
* @Author: caixiang
* @DATE: 2022/1/15 13:01
*/
public enum UDPClient { public enum UDPClient {
//如果要配置多个链接 local1 local2 .... 这样排下去好了 //如果要配置多个链接 local1 local2 .... 这样排下去好了
localAGV("1","192.168.0.211",17804,55678), localAGV("50", "192.168.124.124", 17804, 55678),
//local("127.0.0.1",502,true),
; ;
// 服务端地址+端口 // 服务端用户名+密码+地址+端口
private String SERVICE_HOST = "192.168.0.123"; private String SERVICE_USER = GuestUserCredentials.USER;
private Integer SERVICE_PORT = 1099; private String SERVICE_PWD = GuestUserCredentials.PASSWORD;
private String SERVICE_HOST = GuestUserCredentials.IP;
private Integer SERVICE_PORT = GuestUserCredentials.PORT;
private String name; private String name;
private String host; private String host;
@ -55,9 +52,8 @@ public enum UDPClient {
private Channel conn; private Channel conn;
private boolean isOnline; private boolean isOnline;
private static final Logger logger = LoggerFactory.getLogger("AGVLOGGER"); // private static final Logger logger = LoggerFactory.getLogger("AGVLOGGER");
private static final Logger logger = LoggerFactory.getLogger(UDPClient.class);
// ==== 连接节点配置信息 ===== 开始 // ==== 连接节点配置信息 ===== 开始
@ -77,29 +73,33 @@ public enum UDPClient {
} }
public String getHost() { public String getHost() {
return this.host; return this.host;
} }
public String getName() { public String getName() {
return this.name; return this.name;
} }
public void setIsOnline(boolean isOnline) { public void setIsOnline(boolean isOnline) {
this.isOnline = isOnline; this.isOnline = isOnline;
} }
/** /**
* desc : 判断此链接 健康状况 * desc : 判断此链接 健康状况
* return * return
* true : 此tcp连接 正常 * true : 此tcp连接 正常
* false : 此tcp连接 异常 * false : 此tcp连接 异常
* */ */
public boolean isOnline() { public boolean isOnline() {
return isOnline; return isOnline;
} }
public void close() { public void close() {
//手动关闭连接会出发InActivite 事件 //手动关闭连接会出发InActivite 事件
group.shutdownGracefully(); group.shutdownGracefully();
} }
public static ByteBuf byteArrayToByteBuf(byte[] byteArray) { public static ByteBuf byteArrayToByteBuf(byte[] byteArray) {
// 使用Unpooled类创建ByteBuf // 使用Unpooled类创建ByteBuf
ByteBuf byteBuf = Unpooled.buffer(byteArray.length); ByteBuf byteBuf = Unpooled.buffer(byteArray.length);
@ -107,12 +107,13 @@ public enum UDPClient {
byteBuf.writeBytes(byteArray); byteBuf.writeBytes(byteArray);
return byteBuf; return byteBuf;
} }
/** /**
* --线程安全的-- * --线程安全的--
*
* *
* 如果返回null就代表出现了异常并且尝试了 retryMax 次数并且尝试重置连接 * 如果返回null就代表出现了异常并且尝试了 retryMax 次数并且尝试重置连接
* */ */
public RcvEventPackage send(AgvEvent event) { public RcvEventPackage send(AgvEvent event) {
try { try {
//sendread 报文 //sendread 报文
@ -124,53 +125,66 @@ public enum UDPClient {
this.conn.writeAndFlush( this.conn.writeAndFlush(
new DatagramPacket( new DatagramPacket(
byteArrayToByteBuf(mbPackage.getBody()), byteArrayToByteBuf(mbPackage.getBody()),
new InetSocketAddress(this.host,this.port))) new InetSocketAddress(this.host, this.port)
)
)
.sync(); .sync();
Package aPackage = add.get(5000L, mbPackage.getTransationId()); Package aPackage = add.get(5000L, mbPackage.getTransationId());
byte[] body = aPackage.getBody(); byte[] body = aPackage.getBody();
String errMsg = " [ AGVclient - send success ] [ "+name+" host: "+ this.host +" ]"+event.toString(); String errMsg = " [ AGVclient - send success ] [ " + name + " host: " + this.host
+ " ]" + event.toString();
logger.info(errMsg); logger.info(errMsg);
//注意这里的body 是整个 response结构包括 : 授权码 + header + body //注意这里的body 是整个 response结构包括 : 授权码 + header + body
return new RcvEventPackage(body[22], body); return new RcvEventPackage(body[22], body);
}catch (Throwable e) { }
catch (Throwable e) {
//e.printStackTrace(); //e.printStackTrace();
String errMsg = " [ AGVclient - Read ] [ "+name+" host: "+ this.host +" ] ( occur err ) errTime: "+" ; send errMsg : "+e.getMessage()+" ; event :"+event.toString(); String errMsg = " [ AGVclient - Read ] [ " + name + " host: " + this.host
+ " ] ( occur err ) errTime: " + " ; send errMsg : " + e.getMessage()
+ " ; event :" + event.toString();
logger.info(errMsg); logger.info(errMsg);
throw new RuntimeException(errMsg); throw new RuntimeException(errMsg);
} }
} }
public void subscribe0xB0(RcvEventPackage rcv){ public void subscribeKC(RcvEventPackage rcv, byte[] body) {
if (rcv.isOk()) { if (rcv.isOk()) {
KernelServicePortal servicePortal = new KernelServicePortalBuilder(
if(name.equals("1")){ SERVICE_USER, SERVICE_PWD
this.achieveSub0xB0(name, rcv); ).build();
}else if(name.equals("2")){ servicePortal.login(SERVICE_HOST, SERVICE_PORT);
this.achieveSub0xB0(name, rcv); VehicleService vehicleService = servicePortal.getVehicleService();
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
vehicleService.sendCommAdapterMessage(vehicle.getReference(), body);
servicePortal.logout();
}
else {
System.out.println();
System.out.println("subscribe received transationId : " + "isok:" + rcv.isOk());
}
} }
} else { public void subscribe0xB0(RcvEventPackage rcv, byte[] body) {
if (rcv.isOk()) {
this.achieveSub0xB0(body);
}
else {
System.out.println(); System.out.println();
System.out.println("subscribe0xB0 received transationId : " + "isok:" + rcv.isOk()); System.out.println("subscribe0xB0 received transationId : " + "isok:" + rcv.isOk());
} }
} }
public void subscribe0xAF(RcvEventPackage rcv){
public void subscribe0xAF(RcvEventPackage rcv, byte[] body) {
if (rcv.isOk()) { if (rcv.isOk()) {
this.achieveSub0xAF(body);
if (name.equals("1")) {
this.achieveSub0xAF(name, rcv);
} else if (name.equals("2")) {
this.achieveSub0xAF(name, rcv);
} }
else {
} else {
System.out.println(); System.out.println();
System.out.println("subscribe0xAF received transationId : " + "isok:" + rcv.isOk()); System.out.println("subscribe0xAF received transationId : " + "isok:" + rcv.isOk());
} }
@ -178,49 +192,47 @@ public enum UDPClient {
/** /**
* 0xAF上报信息传入通讯适配器 * 0xAF上报信息传入通讯适配器
* @param vehicleName 车辆名称 *
* @param rcv 响应数据 * @param body 响应数据
*/ */
private void achieveSub0xAF(String vehicleName ,RcvEventPackage rcv){ private void achieveSub0xAF(byte[] body) {
// QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes()); KernelServicePortal servicePortal = new KernelServicePortalBuilder(
SERVICE_USER, SERVICE_PWD
System.out.println(); ).build();
System.out.println("received subscribe 0xAF List : "+ "isok:"+rcv.isOk());
for (byte b:rcv.getValue()){
System.out.print(byteToHex(b)+" ");
}
KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER, GuestUserCredentials.PASSWORD).build();
servicePortal.login(SERVICE_HOST, SERVICE_PORT); servicePortal.login(SERVICE_HOST, SERVICE_PORT);
VehicleService vehicleService = servicePortal.getVehicleService(); VehicleService vehicleService = servicePortal.getVehicleService();
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, vehicleName); Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
//将AGV控制器上报信息传入通讯适配器 vehicleService.sendCommAdapterMessage(vehicle.getReference(), body);
vehicleService.sendCommAdapterMessage(vehicle.getReference(), queryRobotStatusRsp);
servicePortal.logout();
} }
/** /**
* 0xB0上报信息传入通讯适配器 * 0xB0上报信息传入通讯适配器
* @param vehicleName 车辆名称 *
* @param rcv 响应数据 * @param body 响应数据
*/ */
private void achieveSub0xB0(String vehicleName ,RcvEventPackage rcv){ private void achieveSub0xB0(byte[] body) {
QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes()); // QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes());
System.out.println(); // System.out.println();
System.out.println("received subscribe 0xB0 List : "+ "isok:"+rcv.isOk()); // System.out.println("received subscribe 0xB0 List : " + "isok:" + rcv.isOk());
for (byte b:rcv.getValue()){ // for (byte b : rcv.getValue()) {
System.out.print(byteToHex(b)+" "); // System.out.print(byteToHex(b) + " ");
} // }
KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER, GuestUserCredentials.PASSWORD).build(); KernelServicePortal servicePortal = new KernelServicePortalBuilder(
SERVICE_USER, SERVICE_PWD
).build();
servicePortal.login(SERVICE_HOST, SERVICE_PORT); servicePortal.login(SERVICE_HOST, SERVICE_PORT);
VehicleService vehicleService = servicePortal.getVehicleService(); VehicleService vehicleService = servicePortal.getVehicleService();
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, vehicleName); Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
if (vehicle == null) {
throw new RuntimeException("vehicle name:" + name + ",does not exist");
}
//将AGV控制器上报信息传入通讯适配器 //将AGV控制器上报信息传入通讯适配器
vehicleService.sendCommAdapterMessage(vehicle.getReference(), queryCargoStatusRsp); vehicleService.sendCommAdapterMessage(vehicle.getReference(), body);
servicePortal.logout(); servicePortal.logout();
} }
@ -231,6 +243,7 @@ public enum UDPClient {
System.out.print(byteToHex(b) + " "); System.out.print(byteToHex(b) + " ");
} }
} }
public static String byteToHex(byte b) { public static String byteToHex(byte b) {
// 将byte转换为无符号整数 // 将byte转换为无符号整数
int unsignedByte = b & 0xFF; int unsignedByte = b & 0xFF;
@ -242,9 +255,10 @@ public enum UDPClient {
} }
return hexString; return hexString;
} }
/** /**
* decs: 在项目启动的时候初始化 后面就不会初始化了 * decs: 在项目启动的时候初始化 后面就不会初始化了
* */ */
private void initClient() { private void initClient() {
//NioEventLoopGroup Bootstrap 这些资源其实是不用 release的因为全局共用一份的你释放了 下次还得再new //NioEventLoopGroup Bootstrap 这些资源其实是不用 release的因为全局共用一份的你释放了 下次还得再new
NioEventLoopGroup group = new NioEventLoopGroup(); NioEventLoopGroup group = new NioEventLoopGroup();
@ -254,7 +268,8 @@ public enum UDPClient {
.channel(NioDatagramChannel.class) .channel(NioDatagramChannel.class)
.handler(new ChannelInitializer<NioDatagramChannel>() { .handler(new ChannelInitializer<NioDatagramChannel>() {
@Override @Override
protected void initChannel(NioDatagramChannel ch) throws Exception { protected void initChannel(NioDatagramChannel ch)
throws Exception {
ChannelPipeline pipeline = ch.pipeline(); ChannelPipeline pipeline = ch.pipeline();
//0 代表禁用 readerIdleTime 事件的监听 //0 代表禁用 readerIdleTime 事件的监听
//这两个是固定的 //这两个是固定的
@ -267,7 +282,8 @@ public enum UDPClient {
}); });
try { try {
this.conn = this.bootstrap.bind(this.bindPort).sync().channel(); this.conn = this.bootstrap.bind(this.bindPort).sync().channel();
}catch (Exception e){ }
catch (Exception e) {
logger.info("AGV UDP Initial Exception : " + e.getMessage()); logger.info("AGV UDP Initial Exception : " + e.getMessage());
} }
} }

View File

@ -86,38 +86,44 @@ class SameThreadExecutorServiceTest {
verify(task).call(); verify(task).call();
} }
@Test /*
void testVehicle(){ * @Test
//获取车辆对象代码 * void testVehicle() {
KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER,GuestUserCredentials.PASSWORD).build(); * //获取车辆对象代码
servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT); * KernelServicePortal servicePortal = new KernelServicePortalBuilder(
// servicePortal.getPlantModelService().up * GuestUserCredentials.USER, GuestUserCredentials.PASSWORD
PlantModelService plantModelService = servicePortal.getPlantModelService(); * ).build();
VehicleService vehicleService = servicePortal.getVehicleService(); * servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT);
Set<Vehicle> vehicles = vehicleService.fetchObjects(Vehicle.class); * // servicePortal.getPlantModelService().up
for (Vehicle vehicle : vehicles) { * PlantModelService plantModelService = servicePortal.getPlantModelService();
System.out.println("vehicle:"+vehicle); * VehicleService vehicleService = servicePortal.getVehicleService();
} * Set<Vehicle> vehicles = vehicleService.fetchObjects(Vehicle.class);
} * for (Vehicle vehicle : vehicles) {
* System.out.println("vehicle:" + vehicle);
* }
* }
*/
@Test @Test
void testRemoveVehicle() { void testRemoveVehicle() {
HashMap<String, Object> map = new HashMap<>(); HashMap<String, Object> map = new HashMap<>();
int energy = 54; int energy = 52;
map.put("energy", energy); map.put("energy", energy);
long positionX = -100; long positionX = 3040;
map.put("positionX", positionX); map.put("positionX", positionX);
long positionY = 6510; long positionY = -40;
map.put("positionY", positionY); map.put("positionY", positionY);
double positionAngle = 0.0; double positionAngle = 0.0;
map.put("positionAngle", positionAngle); map.put("positionAngle", positionAngle);
//向车辆对应的通讯适配器发送消息 //向车辆对应的通讯适配器发送消息
KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER,GuestUserCredentials.PASSWORD).build(); KernelServicePortal servicePortal = new KernelServicePortalBuilder(
GuestUserCredentials.USER, GuestUserCredentials.PASSWORD
).build();
servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT); servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT);
VehicleService vehicleService = servicePortal.getVehicleService(); VehicleService vehicleService = servicePortal.getVehicleService();
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "2"); Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "50");
vehicleService.sendCommAdapterMessage(vehicle.getReference(), map); vehicleService.sendCommAdapterMessage(vehicle.getReference(), map);
} }

View File

@ -42,6 +42,7 @@ public class DefaultPropertySuggestions
keySuggestions.add(LoopbackAdapterConstants.AGV_AUTHORIZE_CODE); keySuggestions.add(LoopbackAdapterConstants.AGV_AUTHORIZE_CODE);
keySuggestions.add(LoopbackAdapterConstants.AGV_IP); keySuggestions.add(LoopbackAdapterConstants.AGV_IP);
keySuggestions.add(LoopbackAdapterConstants.AGV_PORT); keySuggestions.add(LoopbackAdapterConstants.AGV_PORT);
keySuggestions.add(LoopbackAdapterConstants.POINT_TYPE);
} }
@Override @Override