update vehicle adapter
This commit is contained in:
parent
17c28a5a7f
commit
4882a28c0a
@ -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);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -2,4 +2,3 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
org.opentcs.virtualvehicle.LoopbackCommAdapterModule
|
org.opentcs.virtualvehicle.LoopbackCommAdapterModule
|
||||||
org.opentcs.kcvehicle.KcCommAdapterModule
|
|
||||||
|
@ -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);
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -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() {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -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();
|
|
||||||
}
|
|
@ -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,74 +353,100 @@ public class LoopbackCommunicationAdapter
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void processMessage(Object message) {
|
public void processMessage(Object message) {
|
||||||
if (message instanceof String) {
|
|
||||||
//测试使用
|
if (message instanceof byte[]) {
|
||||||
getProcessModel().setEnergyLevel(66);
|
updateVehicleModel(message);
|
||||||
System.out.println(message);
|
|
||||||
}
|
}
|
||||||
else if (message instanceof QueryCargoStatusRsp) {
|
else if (message instanceof HashMap<?, ?>) {
|
||||||
//0xB0响应结果
|
//todo 测试代码----成功
|
||||||
QueryCargoStatusRsp queryCargoStatusRsp = (QueryCargoStatusRsp) message;
|
HashMap<?, ?> msg = (HashMap<?, ?>) message;
|
||||||
|
|
||||||
if (queryCargoStatusRsp.isCargo == 0) {
|
getProcessModel().setEnergyLevel((int) msg.get("energy"));
|
||||||
this.loadState = LoadState.EMPTY;
|
|
||||||
} 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<?,?>) {
|
|
||||||
HashMap<?,?> msg = ((HashMap<?, ?>) message);
|
|
||||||
|
|
||||||
getProcessModel().setEnergyLevel((int)msg.get("energy"));
|
|
||||||
getProcessModel().setState(Vehicle.State.EXECUTING);
|
getProcessModel().setState(Vehicle.State.EXECUTING);
|
||||||
|
|
||||||
long positionX = (long)msg.get("positionX");
|
long positionX = (long) msg.get("positionX");
|
||||||
long positionY = (long)msg.get("positionY");
|
long positionY = (long) msg.get("positionY");
|
||||||
Triple triple = new Triple(positionX, positionY, 0);
|
Triple triple = new Triple(positionX, positionY, 0);
|
||||||
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() {
|
||||||
|
|
||||||
//0xAF获取AGV状态
|
if (true) {
|
||||||
QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command();
|
//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订阅
|
||||||
Date now = new Date();
|
sub0xAF();
|
||||||
deadline = now.getTime() + 1000;
|
|
||||||
intervalTime = 100;
|
|
||||||
|
|
||||||
//开启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),等待机器人定位状态为定位完成;
|
//开启0xB0订阅
|
||||||
QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command();
|
// sub0xB0()
|
||||||
if (qryRobotRunStatusRsp.robotLocalizationState == 0) {
|
|
||||||
|
// //新:设置车辆姿势。(官方弃用设置车辆精确位置)-------------------目前车辆返回位置为固定值!!!!!
|
||||||
|
// 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);
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("=================---initAGV_0x03-----000000");
|
||||||
|
SwitchManualMode.command();
|
||||||
|
getProcessModel().setState(Vehicle.State.UNAVAILABLE);
|
||||||
|
|
||||||
|
//设置AGV最后一个点位置
|
||||||
|
String lastPassPointId = (qryRobotStatusRsp.locationStatusInfo.lastPassPointId).toString();
|
||||||
|
initVehiclePosition(lastPassPointId);
|
||||||
|
|
||||||
//2 执行机器人手动定位 (命令码:0x14);
|
//2 执行机器人手动定位 (命令码:0x14);
|
||||||
|
System.out.println("=================---initAGV_0x14");
|
||||||
|
LocationStatusInfo locationStatusInfo = qryRobotStatusRsp.locationStatusInfo;
|
||||||
|
double agvX = locationStatusInfo.globalX;
|
||||||
|
double agvY = locationStatusInfo.globalY;
|
||||||
|
double agvAngle = locationStatusInfo.absoluteDirecAngle;
|
||||||
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);
|
||||||
|
System.out.println("=================---initAGV_0x1F");
|
||||||
|
ConfirmRelocation.commnd();
|
||||||
|
|
||||||
|
//5 切换成自动模式(命令码:0x03,变量:NaviControl 修改为1);
|
||||||
|
System.out.println("=================---initAGV_0x03-----111111");
|
||||||
|
SwitchAutomaticMode.command();
|
||||||
|
getProcessModel().setState(Vehicle.State.IDLE);
|
||||||
|
|
||||||
|
//打开通讯适配器连接
|
||||||
|
getProcessModel().setCommAdapterConnected(true);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//4 确认初始位置(命令码:0x1F);
|
private void sub0xAF(){
|
||||||
ConfirmRelocation.commnd();
|
messageProcessingPool.submit(() -> {
|
||||||
|
Date now = new Date();
|
||||||
|
sub0xafDeadline = now.getTime() + 10000;
|
||||||
|
SubRobotStatue.command();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
//5 切换成自动模式(命令码:0x03,变量:NaviControl 修改为1);
|
private void sub0xB0(){
|
||||||
SwitchAutomaticMode.command();
|
messageProcessingPool.submit(() -> {
|
||||||
|
Date now = new Date();
|
||||||
//打开通讯适配器连接
|
sub0xb0Deadline = now.getTime() + 10000;
|
||||||
getProcessModel().setCommAdapterConnected(true);
|
SubCargoStatus.command();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -18,7 +18,7 @@ public interface GuestUserCredentials {
|
|||||||
/**
|
/**
|
||||||
* 主机IP
|
* 主机IP
|
||||||
*/
|
*/
|
||||||
String IP = "192.168.0.106";
|
String IP = "192.168.124.111";
|
||||||
/**
|
/**
|
||||||
* 内核开放端口
|
* 内核开放端口
|
||||||
*/
|
*/
|
||||||
|
@ -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";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -11,133 +11,136 @@ import org.opentcs.kc.common.byteutils.ByteUtils;
|
|||||||
|
|
||||||
public class CaffeineUtil {
|
public class CaffeineUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存的最大容量
|
* 缓存的最大容量
|
||||||
*/
|
*/
|
||||||
private static final int MAXIMUM_SIZE = 1000;
|
private static final int MAXIMUM_SIZE = 1000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 缓存项的写入后过期时间
|
* 缓存项的写入后过期时间
|
||||||
*/
|
*/
|
||||||
private static final int EXPIRE_AFTER_WRITE_DURATION = 10;
|
private static final int EXPIRE_AFTER_WRITE_DURATION = 10;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 过期时间单位(分钟)
|
* 过期时间单位(分钟)
|
||||||
*/
|
*/
|
||||||
private static final TimeUnit EXPIRE_AFTER_WRITE_TIMEUNIT = TimeUnit.MINUTES;
|
private static final TimeUnit EXPIRE_AFTER_WRITE_TIMEUNIT = TimeUnit.MINUTES;
|
||||||
|
|
||||||
private static Cache<String, Object> cache;
|
private static Cache<String, Object> cache;
|
||||||
private static Cache<String, AtomicInteger> cacheUUID;
|
private static Cache<String, AtomicInteger> cacheUUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化Caffeine缓存配置
|
* 初始化Caffeine缓存配置
|
||||||
*/
|
*/
|
||||||
static {
|
static {
|
||||||
//todo https://github.com/ben-manes/caffeine/wiki 研究一下,然后升级一下版本
|
//todo https://github.com/ben-manes/caffeine/wiki 研究一下,然后升级一下版本
|
||||||
cache = Caffeine.newBuilder()
|
cache = Caffeine.newBuilder()
|
||||||
.maximumSize(MAXIMUM_SIZE)
|
.maximumSize(MAXIMUM_SIZE)
|
||||||
.expireAfterWrite(EXPIRE_AFTER_WRITE_DURATION, EXPIRE_AFTER_WRITE_TIMEUNIT)
|
.expireAfterWrite(EXPIRE_AFTER_WRITE_DURATION, EXPIRE_AFTER_WRITE_TIMEUNIT)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
cacheUUID = Caffeine.newBuilder()
|
cacheUUID = Caffeine.newBuilder()
|
||||||
.maximumSize(10)
|
.maximumSize(10)
|
||||||
.expireAfterWrite(Long.MAX_VALUE, EXPIRE_AFTER_WRITE_TIMEUNIT)
|
.expireAfterWrite(Long.MAX_VALUE, EXPIRE_AFTER_WRITE_TIMEUNIT)
|
||||||
.build();
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
byte[] a = getUUID();
|
||||||
|
byte[] b = getUUID();
|
||||||
|
byte[] d = ByteUtils.intToBytes(300);
|
||||||
|
byte[] c = ByteUtils.intToBytes(32000);
|
||||||
|
//todo int 转两个字节长度
|
||||||
|
System.out.println(Arrays.asList(getUUID()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static synchronized byte[] getUUID() {
|
||||||
|
AtomicInteger uuid = cacheUUID.getIfPresent("UUID");
|
||||||
|
if (uuid == null) {
|
||||||
|
//transationId 从1 开始,0留给心跳变量,这样就固定报文了
|
||||||
|
cacheUUID.put("UUID", new AtomicInteger(1));
|
||||||
|
return ByteUtils.intToBytes(1);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
public static void main(String[] args) {
|
if (uuid.get() >= 32000) {
|
||||||
byte[] a = getUUID();
|
cacheUUID.put("UUID", new AtomicInteger(1));
|
||||||
byte[] b = getUUID();
|
return ByteUtils.intToBytes(1);
|
||||||
byte[] d = ByteUtils.intToBytes(300);
|
}
|
||||||
byte[] c = ByteUtils.intToBytes(32000);
|
else {
|
||||||
//todo int 转两个字节长度
|
return ByteUtils.intToBytes(uuid.incrementAndGet());
|
||||||
System.out.println(Arrays.asList(getUUID()));
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static synchronized byte[] getUUIDAGV() {
|
||||||
|
AtomicInteger agvuuid = cacheUUID.getIfPresent("AGVUUID");
|
||||||
public static synchronized byte[] getUUID() {
|
if (agvuuid == null) {
|
||||||
AtomicInteger uuid = cacheUUID.getIfPresent("UUID");
|
//transationId 从1 开始,0留给心跳变量,这样就固定报文了
|
||||||
if(uuid == null){
|
cacheUUID.put("AGVUUID", new AtomicInteger(1));
|
||||||
//transationId 从1 开始,0留给心跳变量,这样就固定报文了
|
return ByteUtils.intToBytesS(1);
|
||||||
cacheUUID.put("UUID",new AtomicInteger(1));
|
|
||||||
return ByteUtils.intToBytes(1);
|
|
||||||
}else {
|
|
||||||
if(uuid.get() >= 32000){
|
|
||||||
cacheUUID.put("UUID",new AtomicInteger(1));
|
|
||||||
return ByteUtils.intToBytes(1);
|
|
||||||
}else {
|
|
||||||
return ByteUtils.intToBytes(uuid.incrementAndGet());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
public static synchronized byte[] getUUIDAGV() {
|
if (agvuuid.get() >= 32000) {
|
||||||
AtomicInteger agvuuid = cacheUUID.getIfPresent("AGVUUID");
|
cacheUUID.put("AGVUUID", new AtomicInteger(1));
|
||||||
if(agvuuid == null){
|
return ByteUtils.intToBytesS(1);
|
||||||
//transationId 从1 开始,0留给心跳变量,这样就固定报文了
|
}
|
||||||
cacheUUID.put("AGVUUID",new AtomicInteger(1));
|
else {
|
||||||
return ByteUtils.intToBytesS(1);
|
return ByteUtils.intToBytesS(agvuuid.incrementAndGet());
|
||||||
}else {
|
}
|
||||||
if(agvuuid.get() >= 32000){
|
|
||||||
cacheUUID.put("AGVUUID",new AtomicInteger(1));
|
|
||||||
return ByteUtils.intToBytesS(1);
|
|
||||||
}else {
|
|
||||||
return ByteUtils.intToBytesS(agvuuid.incrementAndGet());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存值
|
* 获取缓存值
|
||||||
*
|
*
|
||||||
* @param key 缓存键
|
* @param key 缓存键
|
||||||
* @return 缓存值
|
* @return 缓存值
|
||||||
*/
|
*/
|
||||||
public static Object get(String key) {
|
public static Object get(String key) {
|
||||||
return cache.getIfPresent(key);
|
return cache.getIfPresent(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置缓存值
|
* 设置缓存值
|
||||||
*
|
*
|
||||||
* @param key 缓存键
|
* @param key 缓存键
|
||||||
* @param value 缓存值
|
* @param value 缓存值
|
||||||
*/
|
*/
|
||||||
public static void put(String key, Object value) {
|
public static void put(String key, Object value) {
|
||||||
cache.put(key, value);
|
cache.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 移除缓存项
|
* 移除缓存项
|
||||||
*
|
*
|
||||||
* @param key 缓存键
|
* @param key 缓存键
|
||||||
*/
|
*/
|
||||||
public static void remove(String key) {
|
public static void remove(String key) {
|
||||||
cache.invalidate(key);
|
cache.invalidate(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空缓存
|
* 清空缓存
|
||||||
*/
|
*/
|
||||||
public static void clear() {
|
public static void clear() {
|
||||||
cache.invalidateAll();
|
cache.invalidateAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取缓存中的所有值
|
* 获取缓存中的所有值
|
||||||
*
|
*
|
||||||
* @return 缓存中的所有值集合
|
* @return 缓存中的所有值集合
|
||||||
*/
|
*/
|
||||||
public static Collection<Object> getAllValues() {
|
public static Collection<Object> getAllValues() {
|
||||||
return cache.asMap().values();
|
return cache.asMap().values();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 清空缓存中的所有值
|
* 清空缓存中的所有值
|
||||||
*/
|
*/
|
||||||
public static void removeAllValues() {
|
public static void removeAllValues() {
|
||||||
cache.invalidateAll();
|
cache.invalidateAll();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,34 +6,35 @@ package org.opentcs.kc.common;
|
|||||||
* 2017年3月30日 下午7:05:54
|
* 2017年3月30日 下午7:05:54
|
||||||
*/
|
*/
|
||||||
public interface Const {
|
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
|
||||||
String[] split = s.split(",");
|
= "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";
|
||||||
System.out.println(split.length);
|
String[] split = s.split(",");
|
||||||
}
|
System.out.println(split.length);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 监听端口
|
* 监听端口
|
||||||
*/
|
*/
|
||||||
public static final int PORT = 6789;
|
public static final int PORT = 6789;
|
||||||
//public static final int PORT = 9000;
|
//public static final int PORT = 9000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 心跳超时时间
|
* 心跳超时时间
|
||||||
*/
|
*/
|
||||||
public static final int TIMEOUT = 5000;
|
public static final int TIMEOUT = 5000;
|
||||||
|
|
||||||
|
|
||||||
public static final int NEED_REPLY_TYPE = 1;
|
public static final int NEED_REPLY_TYPE = 1;
|
||||||
public static final int NO_REPLY_TYPE = 2;
|
public static final int NO_REPLY_TYPE = 2;
|
||||||
public static final int HEARTBEAT_TYPE = 3;
|
public static final int HEARTBEAT_TYPE = 3;
|
||||||
|
|
||||||
|
|
||||||
public static final Integer REQUEST_TYPE = 1;
|
public static final Integer REQUEST_TYPE = 1;
|
||||||
public static final Integer RESPONSE_TYPE = 2;
|
public static final Integer RESPONSE_TYPE = 2;
|
||||||
}
|
}
|
||||||
|
@ -3,43 +3,38 @@ 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;
|
||||||
private String transationId;
|
private String transationId;
|
||||||
|
|
||||||
|
|
||||||
public Package(byte[] body, String transationId) {
|
public Package(byte[] body, String transationId) {
|
||||||
this.body = body;
|
this.body = body;
|
||||||
this.transationId = transationId;
|
this.transationId = transationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBody() {
|
public byte[] getBody() {
|
||||||
return body;
|
return body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBody(byte[] body) {
|
public void setBody(byte[] body) {
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTransationId() {
|
public String getTransationId() {
|
||||||
return transationId;
|
return transationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setTransationId(String transationId) {
|
public void setTransationId(String transationId) {
|
||||||
this.transationId = transationId;
|
this.transationId = transationId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "Package{" +
|
return "Package{" +
|
||||||
"body=" + Arrays.toString(body) +
|
"body=" + Arrays.toString(body) +
|
||||||
", transationId='" + transationId + '\'' +
|
", transationId='" + transationId + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,64 +1,66 @@
|
|||||||
/*
|
/*
|
||||||
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;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new s7 exception.
|
* Instantiates a new s7 exception.
|
||||||
*/
|
*/
|
||||||
public ParseDataException() {
|
public ParseDataException() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new s7 exception.
|
* Instantiates a new s7 exception.
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message
|
||||||
* the message
|
* the message
|
||||||
*/
|
*/
|
||||||
public ParseDataException(final String message) {
|
public ParseDataException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new s7 exception.
|
* Instantiates a new s7 exception.
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message
|
||||||
* the message
|
* the message
|
||||||
* @param cause
|
* @param cause
|
||||||
* the cause
|
* the cause
|
||||||
*/
|
*/
|
||||||
public ParseDataException(final String message, final Throwable cause) {
|
public ParseDataException(final String message, final Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a new s7 exception.
|
* Instantiates a new s7 exception.
|
||||||
*
|
*
|
||||||
* @param cause
|
* @param cause
|
||||||
* the cause
|
* the cause
|
||||||
*/
|
*/
|
||||||
public ParseDataException(final Throwable cause) {
|
public ParseDataException(final Throwable cause) {
|
||||||
super(cause);
|
super(cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,49 +1,44 @@
|
|||||||
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;
|
||||||
private Object value;
|
private Object value;
|
||||||
private String content;
|
private String content;
|
||||||
|
|
||||||
public RcvPackage(boolean isOk, Object value, String content) {
|
public RcvPackage(boolean isOk, Object value, String content) {
|
||||||
this.isOk = isOk;
|
this.isOk = isOk;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
public RcvPackage() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk() {
|
public RcvPackage() {
|
||||||
return isOk;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void setValue(Object value) {
|
public boolean isOk() {
|
||||||
this.value = value;
|
return isOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object getValue() {
|
public void setValue(Object value) {
|
||||||
return value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContent() {
|
public Object getValue() {
|
||||||
return content;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getContent() {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
@Override
|
public String toString() {
|
||||||
public String toString() {
|
return "RcvPackage{" +
|
||||||
return "RcvPackage{" +
|
"isOk=" + isOk +
|
||||||
"isOk=" + isOk +
|
", value=" + value +
|
||||||
", value=" + value +
|
", content='" + content + '\'' +
|
||||||
", content='" + content + '\'' +
|
'}';
|
||||||
'}';
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -6,73 +6,60 @@ 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位数
|
public static String getTransationId() {
|
||||||
* @return
|
String val = String.valueOf(System.currentTimeMillis());
|
||||||
*/
|
Random random = new Random();
|
||||||
public static String getTransationId() {
|
for (int i = 0; i < 2; i++) {
|
||||||
String val = String.valueOf(System.currentTimeMillis());
|
val += String.valueOf(random.nextInt(10));
|
||||||
Random random = new Random();
|
}
|
||||||
for (int i = 0; i < 2; i++) {
|
return val;
|
||||||
val += String.valueOf(random.nextInt(10));
|
}
|
||||||
}
|
|
||||||
return val;
|
/**
|
||||||
|
* 获取指定长度的随机数
|
||||||
|
* (获取指定长度uuid)
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static String getUUID(int len) {
|
||||||
|
if (0 >= len) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
String uuid = getUUID();
|
||||||
* 获取指定长度的随机数
|
StringBuffer str = new StringBuffer();
|
||||||
* (获取指定长度uuid)
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public static String getUUID(int len)
|
|
||||||
{
|
|
||||||
if(0 >= len)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
String uuid = getUUID();
|
for (int i = 0; i < len; i++) {
|
||||||
StringBuffer str = new StringBuffer();
|
str.append(uuid.charAt(i));
|
||||||
|
|
||||||
for (int i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
str.append(uuid.charAt(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
return str.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return str.toString();
|
||||||
*32位默认长度的uuid
|
}
|
||||||
* (获取32位uuid)
|
|
||||||
*
|
/**
|
||||||
* @return
|
* 32位默认长度的uuid
|
||||||
*/
|
* (获取32位uuid)
|
||||||
public static String getUUID()
|
*
|
||||||
{
|
* @return
|
||||||
return UUID.randomUUID().toString().replace("-", "");
|
*/
|
||||||
|
public static String getUUID() {
|
||||||
|
return UUID.randomUUID().toString().replace("-", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* type:
|
||||||
|
* 1.返回的是这种格式:2021-08-16 15:00:05
|
||||||
|
* 2.返回的是这种格式:20210816150021
|
||||||
|
*/
|
||||||
|
public static String getNowDate(Integer type) {
|
||||||
|
if (type == 1) {
|
||||||
|
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
type:
|
|
||||||
1.返回的是这种格式:2021-08-16 15:00:05
|
|
||||||
2.返回的是这种格式:20210816150021
|
|
||||||
*/
|
|
||||||
public static String getNowDate(Integer type){
|
|
||||||
if(type==1){
|
|
||||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
|
||||||
}else {
|
|
||||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,346 +4,356 @@ import java.nio.ByteBuffer;
|
|||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
// 对数字和字节进行转换。 假设数据存储是以大端模式存储的:
|
||||||
* @Desc: ""
|
// byte: 字节类型 占8位二进制 00000000
|
||||||
* @Author: caixiang
|
// char: 字符类型 占2个字节 16位二进制 byte[0] byte[1]
|
||||||
* @DATE: 2022/4/1 17:32
|
// int : 整数类型 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3]
|
||||||
*/
|
// long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5]
|
||||||
//对数字和字节进行转换。 假设数据存储是以大端模式存储的:
|
// long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7]
|
||||||
// byte: 字节类型 占8位二进制 00000000
|
// float: 浮点数(小数) 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3]
|
||||||
// char: 字符类型 占2个字节 16位二进制 byte[0] byte[1]
|
// double: 双精度浮点数(小数) 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4]byte[5] byte[6] byte[7]
|
||||||
// int : 整数类型 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3]
|
|
||||||
// long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5]
|
|
||||||
// long: 长整数类型 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4] byte[5] byte[6] byte[7]
|
|
||||||
// float: 浮点数(小数) 占4个字节 32位二进制 byte[0] byte[1] byte[2] byte[3]
|
|
||||||
// double: 双精度浮点数(小数) 占8个字节 64位二进制 byte[0] byte[1] byte[2] byte[3] byte[4]byte[5] byte[6] byte[7]
|
|
||||||
|
|
||||||
public class ByteUtil {
|
public class ByteUtil {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* int转byte
|
* int转byte
|
||||||
*
|
*
|
||||||
* @param intValue int值
|
* @param intValue int值
|
||||||
* @return byte值
|
* @return byte值
|
||||||
*/
|
*/
|
||||||
public static byte intToByte(int intValue) {
|
public static byte intToByte(int intValue) {
|
||||||
return (byte) intValue;
|
return (byte) intValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte intTo1Byte(int intValue) {
|
||||||
|
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
|
||||||
|
byteBuffer.putInt(intValue);
|
||||||
|
byte[] byteArray = byteBuffer.array();
|
||||||
|
return byteArray[3]; // 取低字节
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte转无符号int
|
||||||
|
*
|
||||||
|
* @param byteValue byte值
|
||||||
|
* @return 无符号int值
|
||||||
|
* @since 3.2.0
|
||||||
|
*/
|
||||||
|
public static int byteToUnsignedInt(byte byteValue) {
|
||||||
|
// Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值
|
||||||
|
return byteValue & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 字符串转成16个字节的byte[] ,不足16个字节前面填充0
|
||||||
|
*/
|
||||||
|
public static byte[] stringTo16Byte(String input) {
|
||||||
|
byte[] originalBytes = input.getBytes(StandardCharsets.UTF_8);
|
||||||
|
ByteBuffer buffer = ByteBuffer.allocate(16);
|
||||||
|
buffer.put(originalBytes);
|
||||||
|
buffer.put(new byte[16 - originalBytes.length]);
|
||||||
|
return buffer.array();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组转short<br>
|
||||||
|
* 默认以小端序转换
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @return short值
|
||||||
|
*/
|
||||||
|
public static short bytesToShort(byte[] bytes) {
|
||||||
|
return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组转short<br>
|
||||||
|
* 自定义端序
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @param byteOrder 端序
|
||||||
|
* @return short值
|
||||||
|
*/
|
||||||
|
public static short bytesToShort(byte[] bytes, ByteOrder byteOrder) {
|
||||||
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
|
//小端模式,数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中
|
||||||
|
return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* short转byte数组<br>
|
||||||
|
* 默认以小端序转换
|
||||||
|
*
|
||||||
|
* @param shortValue short值
|
||||||
|
* @return byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] shortToBytes(short shortValue) {
|
||||||
|
return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* short转byte数组<br>
|
||||||
|
* 自定义端序
|
||||||
|
*
|
||||||
|
* @param shortValue short值
|
||||||
|
* @param byteOrder 端序
|
||||||
|
* @return byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] shortToBytes(short shortValue, ByteOrder byteOrder) {
|
||||||
|
byte[] b = new byte[Short.BYTES];
|
||||||
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
|
b[0] = (byte) (shortValue & 0xff);
|
||||||
|
b[1] = (byte) ((shortValue >> Byte.SIZE) & 0xff);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b[1] = (byte) (shortValue & 0xff);
|
||||||
|
b[0] = (byte) ((shortValue >> Byte.SIZE) & 0xff);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte[]转int值<br>
|
||||||
|
* 默认以小端序转换
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @return int值
|
||||||
|
*/
|
||||||
|
public static int bytesToInt(byte[] bytes) {
|
||||||
|
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte[]转int值<br>
|
||||||
|
* 自定义端序
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @param byteOrder 端序
|
||||||
|
* @return int值
|
||||||
|
*/
|
||||||
|
public static int bytesToInt(byte[] bytes, ByteOrder byteOrder) {
|
||||||
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
|
return bytes[0] & 0xFF | //
|
||||||
|
(bytes[1] & 0xFF) << 8 | //
|
||||||
|
(bytes[2] & 0xFF) << 16 | //
|
||||||
|
(bytes[3] & 0xFF) << 24; //
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return bytes[3] & 0xFF | //
|
||||||
|
(bytes[2] & 0xFF) << 8 | //
|
||||||
|
(bytes[1] & 0xFF) << 16 | //
|
||||||
|
(bytes[0] & 0xFF) << 24; //
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte intTo1Byte(int intValue) {
|
}
|
||||||
ByteBuffer byteBuffer = ByteBuffer.allocate(4);
|
|
||||||
byteBuffer.putInt(intValue);
|
|
||||||
byte[] byteArray = byteBuffer.array();
|
|
||||||
return byteArray[3]; // 取低字节
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* byte转无符号int
|
* int转byte数组<br>
|
||||||
*
|
* 默认以小端序转换
|
||||||
* @param byteValue byte值
|
*
|
||||||
* @return 无符号int值
|
* @param intValue int值
|
||||||
* @since 3.2.0
|
* @return byte数组
|
||||||
*/
|
*/
|
||||||
public static int byteToUnsignedInt(byte byteValue) {
|
public static byte[] intToBytes(int intValue) {
|
||||||
// Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值
|
return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN);
|
||||||
return byteValue & 0xFF;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* int转byte数组<br>
|
||||||
* 字符串转成16个字节的byte[] ,不足16个字节前面填充0
|
* 自定义端序
|
||||||
* */
|
*
|
||||||
public static byte[] stringTo16Byte(String input) {
|
* @param intValue int值
|
||||||
byte[] originalBytes = input.getBytes(StandardCharsets.UTF_8);
|
* @param byteOrder 端序
|
||||||
ByteBuffer buffer = ByteBuffer.allocate(16);
|
* @return byte数组
|
||||||
buffer.put(originalBytes);
|
*/
|
||||||
buffer.put(new byte[16 - originalBytes.length]);
|
public static byte[] intToBytes(int intValue, ByteOrder byteOrder) {
|
||||||
return buffer.array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
* byte数组转short<br>
|
return new byte[]{ //
|
||||||
* 默认以小端序转换
|
(byte) (intValue & 0xFF), //
|
||||||
*
|
(byte) ((intValue >> 8) & 0xFF), //
|
||||||
* @param bytes byte数组
|
(byte) ((intValue >> 16) & 0xFF), //
|
||||||
* @return short值
|
(byte) ((intValue >> 24) & 0xFF) //
|
||||||
*/
|
};
|
||||||
public static short bytesToShort(byte[] bytes) {
|
|
||||||
return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* byte数组转short<br>
|
|
||||||
* 自定义端序
|
|
||||||
*
|
|
||||||
* @param bytes byte数组
|
|
||||||
* @param byteOrder 端序
|
|
||||||
* @return short值
|
|
||||||
*/
|
|
||||||
public static short bytesToShort(byte[] bytes, ByteOrder byteOrder) {
|
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
|
||||||
//小端模式,数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中
|
|
||||||
return (short) (bytes[0] & 0xff | (bytes[1] & 0xff) << Byte.SIZE);
|
|
||||||
} else {
|
|
||||||
return (short) (bytes[1] & 0xff | (bytes[0] & 0xff) << Byte.SIZE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* short转byte数组<br>
|
|
||||||
* 默认以小端序转换
|
|
||||||
*
|
|
||||||
* @param shortValue short值
|
|
||||||
* @return byte数组
|
|
||||||
*/
|
|
||||||
public static byte[] shortToBytes(short shortValue) {
|
|
||||||
return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* short转byte数组<br>
|
|
||||||
* 自定义端序
|
|
||||||
*
|
|
||||||
* @param shortValue short值
|
|
||||||
* @param byteOrder 端序
|
|
||||||
* @return byte数组
|
|
||||||
*/
|
|
||||||
public static byte[] shortToBytes(short shortValue, ByteOrder byteOrder) {
|
|
||||||
byte[] b = new byte[Short.BYTES];
|
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
|
||||||
b[0] = (byte) (shortValue & 0xff);
|
|
||||||
b[1] = (byte) ((shortValue >> Byte.SIZE) & 0xff);
|
|
||||||
} else {
|
|
||||||
b[1] = (byte) (shortValue & 0xff);
|
|
||||||
b[0] = (byte) ((shortValue >> Byte.SIZE) & 0xff);
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* byte[]转int值<br>
|
|
||||||
* 默认以小端序转换
|
|
||||||
*
|
|
||||||
* @param bytes byte数组
|
|
||||||
* @return int值
|
|
||||||
*/
|
|
||||||
public static int bytesToInt(byte[] bytes) {
|
|
||||||
return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* byte[]转int值<br>
|
|
||||||
* 自定义端序
|
|
||||||
*
|
|
||||||
* @param bytes byte数组
|
|
||||||
* @param byteOrder 端序
|
|
||||||
* @return int值
|
|
||||||
*/
|
|
||||||
public static int bytesToInt(byte[] bytes, ByteOrder byteOrder) {
|
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
|
||||||
return bytes[0] & 0xFF | //
|
|
||||||
(bytes[1] & 0xFF) << 8 | //
|
|
||||||
(bytes[2] & 0xFF) << 16 | //
|
|
||||||
(bytes[3] & 0xFF) << 24; //
|
|
||||||
} else {
|
|
||||||
return bytes[3] & 0xFF | //
|
|
||||||
(bytes[2] & 0xFF) << 8 | //
|
|
||||||
(bytes[1] & 0xFF) << 16 | //
|
|
||||||
(bytes[0] & 0xFF) << 24; //
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
/**
|
return new byte[]{ //
|
||||||
* int转byte数组<br>
|
(byte) ((intValue >> 24) & 0xFF), //
|
||||||
* 默认以小端序转换
|
(byte) ((intValue >> 16) & 0xFF), //
|
||||||
*
|
(byte) ((intValue >> 8) & 0xFF), //
|
||||||
* @param intValue int值
|
(byte) (intValue & 0xFF) //
|
||||||
* @return byte数组
|
};
|
||||||
*/
|
|
||||||
public static byte[] intToBytes(int intValue) {
|
|
||||||
return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
}
|
||||||
* int转byte数组<br>
|
|
||||||
* 自定义端序
|
|
||||||
*
|
|
||||||
* @param intValue int值
|
|
||||||
* @param byteOrder 端序
|
|
||||||
* @return byte数组
|
|
||||||
*/
|
|
||||||
public static byte[] intToBytes(int intValue, ByteOrder byteOrder) {
|
|
||||||
|
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
/**
|
||||||
return new byte[]{ //
|
* long转byte数组<br>
|
||||||
(byte) (intValue & 0xFF), //
|
* 默认以小端序转换<br>
|
||||||
(byte) ((intValue >> 8) & 0xFF), //
|
* from:
|
||||||
(byte) ((intValue >> 16) & 0xFF), //
|
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||||
(byte) ((intValue >> 24) & 0xFF) //
|
*
|
||||||
};
|
* @param longValue long值
|
||||||
|
* @return byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] longToBytes(long longValue) {
|
||||||
|
return longToBytes(longValue, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
/**
|
||||||
return new byte[]{ //
|
* long转byte数组<br>
|
||||||
(byte) ((intValue >> 24) & 0xFF), //
|
* 自定义端序<br>
|
||||||
(byte) ((intValue >> 16) & 0xFF), //
|
* from:
|
||||||
(byte) ((intValue >> 8) & 0xFF), //
|
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||||
(byte) (intValue & 0xFF) //
|
*
|
||||||
};
|
* @param longValue long值
|
||||||
}
|
* @param byteOrder 端序
|
||||||
|
* @return byte数组
|
||||||
|
*/
|
||||||
|
public static byte[] longToBytes(long longValue, ByteOrder byteOrder) {
|
||||||
|
byte[] result = new byte[Long.BYTES];
|
||||||
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
|
for (int i = 0; i < result.length; i++) {
|
||||||
|
result[i] = (byte) (longValue & 0xFF);
|
||||||
|
longValue >>= Byte.SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = (result.length - 1); i >= 0; i--) {
|
||||||
|
result[i] = (byte) (longValue & 0xFF);
|
||||||
|
longValue >>= Byte.SIZE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组转long<br>
|
||||||
|
* 默认以小端序转换<br>
|
||||||
|
* from:
|
||||||
|
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @return long值
|
||||||
|
*/
|
||||||
|
public static long bytesToLong(byte[] bytes) {
|
||||||
|
return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* byte数组转long<br>
|
||||||
|
* 自定义端序<br>
|
||||||
|
* from:
|
||||||
|
* https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @param byteOrder 端序
|
||||||
|
* @return long值
|
||||||
|
*/
|
||||||
|
public static long bytesToLong(byte[] bytes, ByteOrder byteOrder) {
|
||||||
|
long values = 0;
|
||||||
|
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
||||||
|
for (int i = (Long.BYTES - 1); i >= 0; i--) {
|
||||||
|
values <<= Byte.SIZE;
|
||||||
|
values |= (bytes[i] & 0xff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
for (int i = 0; i < Long.BYTES; i++) {
|
||||||
|
values <<= Byte.SIZE;
|
||||||
|
values |= (bytes[i] & 0xff);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
return values;
|
||||||
* long转byte数组<br>
|
}
|
||||||
* 默认以小端序转换<br>
|
|
||||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
|
||||||
*
|
|
||||||
* @param longValue long值
|
|
||||||
* @return byte数组
|
|
||||||
*/
|
|
||||||
public static byte[] longToBytes(long longValue) {
|
|
||||||
return longToBytes(longValue, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* long转byte数组<br>
|
* double转byte数组<br>
|
||||||
* 自定义端序<br>
|
* 默认以小端序转换<br>
|
||||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
*
|
||||||
*
|
* @param doubleValue double值
|
||||||
* @param longValue long值
|
* @return byte数组
|
||||||
* @param byteOrder 端序
|
*/
|
||||||
* @return byte数组
|
public static byte[] doubleToBytes(double doubleValue) {
|
||||||
*/
|
return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN);
|
||||||
public static byte[] longToBytes(long longValue, ByteOrder byteOrder) {
|
}
|
||||||
byte[] result = new byte[Long.BYTES];
|
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
|
||||||
for (int i = 0; i < result.length; i++) {
|
|
||||||
result[i] = (byte) (longValue & 0xFF);
|
|
||||||
longValue >>= Byte.SIZE;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = (result.length - 1); i >= 0; i--) {
|
|
||||||
result[i] = (byte) (longValue & 0xFF);
|
|
||||||
longValue >>= Byte.SIZE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* byte数组转long<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 bytes byte数组
|
*
|
||||||
* @return long值
|
* @param doubleValue double值
|
||||||
*/
|
* @param byteOrder 端序
|
||||||
public static long bytesToLong(byte[] bytes) {
|
* @return byte数组
|
||||||
return bytesToLong(bytes, ByteOrder.LITTLE_ENDIAN);
|
*/
|
||||||
}
|
public static byte[] doubleToBytes(double doubleValue, ByteOrder byteOrder) {
|
||||||
|
return longToBytes(Double.doubleToLongBits(doubleValue), byteOrder);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* byte数组转long<br>
|
* byte数组转Double<br>
|
||||||
* 自定义端序<br>
|
* 默认以小端序转换<br>
|
||||||
* 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值
|
||||||
* @param byteOrder 端序
|
*/
|
||||||
* @return long值
|
public static double bytesToDouble(byte[] bytes) {
|
||||||
*/
|
return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN);
|
||||||
public static long bytesToLong(byte[] bytes, ByteOrder byteOrder) {
|
}
|
||||||
long values = 0;
|
|
||||||
if (ByteOrder.LITTLE_ENDIAN == byteOrder) {
|
|
||||||
for (int i = (Long.BYTES - 1); i >= 0; i--) {
|
|
||||||
values <<= Byte.SIZE;
|
|
||||||
values |= (bytes[i] & 0xff);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < Long.BYTES; i++) {
|
|
||||||
values <<= Byte.SIZE;
|
|
||||||
values |= (bytes[i] & 0xff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return values;
|
/**
|
||||||
}
|
* byte数组转double<br>
|
||||||
|
* 自定义端序<br>
|
||||||
|
*
|
||||||
|
* @param bytes byte数组
|
||||||
|
* @param byteOrder 端序
|
||||||
|
* @return long值
|
||||||
|
*/
|
||||||
|
public static double bytesToDouble(byte[] bytes, ByteOrder byteOrder) {
|
||||||
|
return Double.longBitsToDouble(bytesToLong(bytes, byteOrder));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* double转byte数组<br>
|
* 将{@link Number}转换为
|
||||||
* 默认以小端序转换<br>
|
*
|
||||||
*
|
* @param number 数字
|
||||||
* @param doubleValue double值
|
* @return bytes
|
||||||
* @return byte数组
|
*/
|
||||||
*/
|
public static byte[] numberToBytes(Number number) {
|
||||||
public static byte[] doubleToBytes(double doubleValue) {
|
return numberToBytes(number, ByteOrder.LITTLE_ENDIAN);
|
||||||
return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* double转byte数组<br>
|
* 将{@link Number}转换为
|
||||||
* 自定义端序<br>
|
*
|
||||||
* from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java
|
* @param number 数字
|
||||||
*
|
* @param byteOrder 端序
|
||||||
* @param doubleValue double值
|
* @return bytes
|
||||||
* @param byteOrder 端序
|
*/
|
||||||
* @return byte数组
|
public static byte[] numberToBytes(Number number, ByteOrder byteOrder) {
|
||||||
*/
|
if (number instanceof Double) {
|
||||||
public static byte[] doubleToBytes(double doubleValue, ByteOrder byteOrder) {
|
return doubleToBytes((Double) number, byteOrder);
|
||||||
return longToBytes(Double.doubleToLongBits(doubleValue), byteOrder);
|
|
||||||
}
|
}
|
||||||
|
else if (number instanceof Long) {
|
||||||
/**
|
return longToBytes((Long) number, byteOrder);
|
||||||
* byte数组转Double<br>
|
|
||||||
* 默认以小端序转换<br>
|
|
||||||
*
|
|
||||||
* @param bytes byte数组
|
|
||||||
* @return long值
|
|
||||||
*/
|
|
||||||
public static double bytesToDouble(byte[] bytes) {
|
|
||||||
return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
}
|
||||||
|
else if (number instanceof Integer) {
|
||||||
/**
|
return intToBytes((Integer) number, byteOrder);
|
||||||
* byte数组转double<br>
|
|
||||||
* 自定义端序<br>
|
|
||||||
*
|
|
||||||
* @param bytes byte数组
|
|
||||||
* @param byteOrder 端序
|
|
||||||
* @return long值
|
|
||||||
*/
|
|
||||||
public static double bytesToDouble(byte[] bytes, ByteOrder byteOrder) {
|
|
||||||
return Double.longBitsToDouble(bytesToLong(bytes, byteOrder));
|
|
||||||
}
|
}
|
||||||
|
else if (number instanceof Short) {
|
||||||
/**
|
return shortToBytes((Short) number, byteOrder);
|
||||||
* 将{@link Number}转换为
|
|
||||||
*
|
|
||||||
* @param number 数字
|
|
||||||
* @return bytes
|
|
||||||
*/
|
|
||||||
public static byte[] numberToBytes(Number number) {
|
|
||||||
return numberToBytes(number, ByteOrder.LITTLE_ENDIAN);
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
/**
|
return doubleToBytes(number.doubleValue(), byteOrder);
|
||||||
* 将{@link Number}转换为
|
|
||||||
*
|
|
||||||
* @param number 数字
|
|
||||||
* @param byteOrder 端序
|
|
||||||
* @return bytes
|
|
||||||
*/
|
|
||||||
public static byte[] numberToBytes(Number number, ByteOrder byteOrder) {
|
|
||||||
if (number instanceof Double) {
|
|
||||||
return doubleToBytes((Double) number, byteOrder);
|
|
||||||
} else if (number instanceof Long) {
|
|
||||||
return longToBytes((Long) number, byteOrder);
|
|
||||||
} else if (number instanceof Integer) {
|
|
||||||
return intToBytes((Integer) number, byteOrder);
|
|
||||||
} else if (number instanceof Short) {
|
|
||||||
return shortToBytes((Short) number, byteOrder);
|
|
||||||
} else {
|
|
||||||
return doubleToBytes(number.doubleValue(), byteOrder);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,16 @@
|
|||||||
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;
|
||||||
|
|
||||||
if(a%b!=0){
|
if (a % b != 0) {
|
||||||
c = a/b+1;
|
c = a / b + 1;
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
}
|
||||||
|
return c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,32 +1,27 @@
|
|||||||
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;
|
||||||
|
|
||||||
public StringArrayStruc(String[] content, Integer strSize) {
|
public StringArrayStruc(String[] content, Integer strSize) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
this.strSize = strSize;
|
this.strSize = strSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String[] getContent() {
|
public String[] getContent() {
|
||||||
return content;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setContent(String[] content) {
|
public void setContent(String[] content) {
|
||||||
this.content = content;
|
this.content = content;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getStrSize() {
|
public Integer getStrSize() {
|
||||||
return strSize;
|
return strSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setStrSize(Integer strSize) {
|
public void setStrSize(Integer strSize) {
|
||||||
this.strSize = strSize;
|
this.strSize = strSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,34 +1,34 @@
|
|||||||
package org.opentcs.kc.common.enmuc;
|
package org.opentcs.kc.common.enmuc;
|
||||||
|
|
||||||
public enum ModbusFC {
|
public enum ModbusFC {
|
||||||
//心跳变量(这个可以要求电控同事加一个,不和业务关联,只用于通讯)
|
//心跳变量(这个可以要求电控同事加一个,不和业务关联,只用于通讯)
|
||||||
MB_HOLD_REG((byte) 0x03, (byte) 0x10),
|
MB_HOLD_REG((byte) 0x03, (byte) 0x10),
|
||||||
Q_OUT((byte) 0x01, (byte) 0x05),
|
Q_OUT((byte) 0x01, (byte) 0x05),
|
||||||
I_IN((byte) 0x02, null),
|
I_IN((byte) 0x02, null),
|
||||||
IW_IN((byte) 0x04, null),
|
IW_IN((byte) 0x04, null),
|
||||||
;
|
;
|
||||||
|
|
||||||
private Byte fread;
|
private Byte fread;
|
||||||
private Byte fwrite;
|
private Byte fwrite;
|
||||||
|
|
||||||
ModbusFC(Byte fread, Byte fwrite){
|
ModbusFC(Byte fread, Byte fwrite) {
|
||||||
this.fread = fread;
|
this.fread = fread;
|
||||||
this.fwrite = fwrite;
|
this.fwrite = fwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Byte getFread() {
|
public Byte getFread() {
|
||||||
return fread;
|
return fread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFread(Byte fread) {
|
public void setFread(Byte fread) {
|
||||||
this.fread = fread;
|
this.fread = fread;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Byte getFwrite() {
|
public Byte getFwrite() {
|
||||||
return fwrite;
|
return fwrite;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setFwrite(Byte fwrite) {
|
public void setFwrite(Byte fwrite) {
|
||||||
this.fwrite = fwrite;
|
this.fwrite = fwrite;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,61 +5,62 @@ 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;
|
||||||
private Object oldRequest;
|
private Object oldRequest;
|
||||||
private Object result;
|
private Object result;
|
||||||
|
|
||||||
public AsyncFuture(Object oldRequest) {
|
public AsyncFuture(Object oldRequest) {
|
||||||
this.oldRequest = oldRequest;
|
this.oldRequest = oldRequest;
|
||||||
}
|
}
|
||||||
public AsyncFuture() {
|
|
||||||
}
|
public AsyncFuture() {
|
||||||
|
}
|
||||||
public void done(Object result){
|
|
||||||
synchronized (this){
|
public void done(Object result) {
|
||||||
this.result = result;
|
synchronized (this) {
|
||||||
this.done = true;
|
this.result = result;
|
||||||
//注意这里的notifyAll只能唤醒 本锁的所有 下的所有 wait(),这里的锁就是 AsyncFuture这个类
|
this.done = true;
|
||||||
notifyAll();
|
//注意这里的notifyAll只能唤醒 本锁的所有 下的所有 wait(),这里的锁就是 AsyncFuture这个类
|
||||||
}
|
notifyAll();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get(Long timeout) throws Exception {
|
public Object get(Long timeout)
|
||||||
return null;
|
throws Exception {
|
||||||
}
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Object get(Long timeout, String transationId) throws Exception {
|
public Object get(Long timeout, String transationId)
|
||||||
synchronized (this){
|
throws Exception {
|
||||||
//其实有 synchronize就相当于有一个阻塞队列,当有线程执行了wait 方法,就会把执行wait的这个线程给加入wait<Thread> 队列,
|
synchronized (this) {
|
||||||
//当有线程执行notify方法的时候,就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了
|
//其实有 synchronize就相当于有一个阻塞队列,当有线程执行了wait 方法,就会把执行wait的这个线程给加入wait<Thread> 队列,
|
||||||
|
//当有线程执行notify方法的时候,就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了
|
||||||
// System.out.println("get");
|
// System.out.println("get");
|
||||||
|
|
||||||
// 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。 wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify()
|
// 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。 wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify()
|
||||||
// * 当线程执行notify()/notifyAll()方法时,会唤醒一个处于等待状态该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁
|
// * 当线程执行notify()/notifyAll()方法时,会唤醒一个处于等待状态该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁
|
||||||
this.wait(timeout);
|
this.wait(timeout);
|
||||||
if(!done){
|
if (!done) {
|
||||||
//logger.error("T3 timeout , request information: "+oldRequest.toString());
|
//logger.error("T3 timeout , request information: "+oldRequest.toString());
|
||||||
SendedList.remove(transationId);
|
SendedList.remove(transationId);
|
||||||
throw new Exception("T3 timeout , request information: "+oldRequest.toString());
|
throw new Exception("T3 timeout , request information: " + oldRequest.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
//因为上面的代码是加锁的,所以这里的代码也是加锁的。
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
//因为上面的代码是加锁的,所以这里的代码也是加锁的。
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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){
|
||||||
@ -19,33 +13,33 @@ public class SendedList {
|
|||||||
// list.put(transitionId,asyncFuture);
|
// list.put(transitionId,asyncFuture);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public static synchronized AsyncFuture<Package> add(String transitionId, Package PackageRequest) {
|
public static synchronized AsyncFuture<Package> add(String transitionId, Package PackageRequest) {
|
||||||
AsyncFuture<Package> objectAsyncFuture = new AsyncFuture<>(PackageRequest);
|
AsyncFuture<Package> objectAsyncFuture = new AsyncFuture<>(PackageRequest);
|
||||||
//list.put(transitionId,objectAsyncFuture);
|
//list.put(transitionId,objectAsyncFuture);
|
||||||
CaffeineUtil.put(transitionId,objectAsyncFuture);
|
CaffeineUtil.put(transitionId, objectAsyncFuture);
|
||||||
return objectAsyncFuture;
|
return objectAsyncFuture;
|
||||||
|
}
|
||||||
|
|
||||||
|
//如果超时了,那么让外部把这个key 给清除掉,防止 list 过大
|
||||||
|
public static synchronized void remove(String transitionId) {
|
||||||
|
//list.remove(transitionId);
|
||||||
|
CaffeineUtil.remove(transitionId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public static synchronized Boolean set(String transitionId, Package message) {
|
||||||
|
//AsyncFuture<MBPackage> mqMessageAsyncFuture = list.get(transitionId);
|
||||||
|
AsyncFuture<Package> mqMessageAsyncFuture = (AsyncFuture<Package>) CaffeineUtil.get(
|
||||||
|
transitionId
|
||||||
|
);
|
||||||
|
if (mqMessageAsyncFuture == null) {
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
mqMessageAsyncFuture.done(message);
|
||||||
//如果超时了,那么让外部把这个key 给清除掉,防止 list 过大
|
//清除 ,防止这个hashMap过大。
|
||||||
public static synchronized void remove(String transitionId) {
|
CaffeineUtil.remove(transitionId);
|
||||||
//list.remove(transitionId);
|
return true;
|
||||||
CaffeineUtil.remove(transitionId);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public static synchronized Boolean set(String transitionId, Package message) {
|
|
||||||
//AsyncFuture<MBPackage> mqMessageAsyncFuture = list.get(transitionId);
|
|
||||||
AsyncFuture<Package> mqMessageAsyncFuture = (AsyncFuture<Package>)CaffeineUtil.get(transitionId);
|
|
||||||
if(mqMessageAsyncFuture == null){
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
mqMessageAsyncFuture.done(message);
|
|
||||||
//清除 ,防止这个hashMap过大。
|
|
||||||
CaffeineUtil.remove(transitionId);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,23 +13,24 @@ import java.util.Random;
|
|||||||
* 类说明:日志信息,用String数组代替
|
* 类说明:日志信息,用String数组代替
|
||||||
*/
|
*/
|
||||||
public class LogConst {
|
public class LogConst {
|
||||||
public final static int MONITOR_SIDE_PORT = 9998;
|
public final static int MONITOR_SIDE_PORT = 9998;
|
||||||
private static final String[] LOG_INFOS = {
|
private static final String[] LOG_INFOS = {
|
||||||
"晨光微好,暖在夕阳。幽幽的巷子里,有着岁月酝酿的酒,愈久愈淳。一笔墨香,一盏明灯,记千帆过浪,数不尽的悲欢离合,待那水莲花开。",
|
"晨光微好,暖在夕阳。幽幽的巷子里,有着岁月酝酿的酒,愈久愈淳。一笔墨香,一盏明灯,记千帆过浪,数不尽的悲欢离合,待那水莲花开。",
|
||||||
"未来无期,静在安好。一剪寒梅,纷扰了岁月,抚平了伤痕。摆动的双桨,拨动了心的潭水。陌上花开,落一地秋霜,红枫染了红尘,便许了你十里红装。",
|
"未来无期,静在安好。一剪寒梅,纷扰了岁月,抚平了伤痕。摆动的双桨,拨动了心的潭水。陌上花开,落一地秋霜,红枫染了红尘,便许了你十里红装。",
|
||||||
"离别的风,风干了月的泪。夜里的美",
|
"离别的风,风干了月的泪。夜里的美",
|
||||||
"是梦的呢喃低语,挥走一片彩云,段落成珠。拂袖离去,乘鹤而来,古道西风瘦马。斑驳的树影中,眉目如画的眼,轻语告别了往事如烟。",
|
"是梦的呢喃低语,挥走一片彩云,段落成珠。拂袖离去,乘鹤而来,古道西风瘦马。斑驳的树影中,眉目如画的眼,轻语告别了往事如烟。",
|
||||||
"无言的殇,几世沧桑,几生悲凉。一起剪了西窗烛,听了夜来风吹雨。昨日的叹息,今日的迷离,执一伞,存了一世一笔的温情。一曲长歌,唱尽了一世繁华,一世缘……",
|
"无言的殇,几世沧桑,几生悲凉。一起剪了西窗烛,听了夜来风吹雨。昨日的叹息,今日的迷离,执一伞,存了一世一笔的温情。一曲长歌,唱尽了一世繁华,一世缘……",
|
||||||
"一世恋书,那便十里花开。一生凄凉,那便霜花十里。" ,
|
"一世恋书,那便十里花开。一生凄凉,那便霜花十里。",
|
||||||
"一抹浓烟,便翻页书,展颜一笑,是时间带来遥远的梦。细数树的年轮,感受昨日惆怅,留一半清醒,梦一半叶落。在指尖流过的沙,海边浪花一朵朵,不相遇,才有不约而同。",
|
"一抹浓烟,便翻页书,展颜一笑,是时间带来遥远的梦。细数树的年轮,感受昨日惆怅,留一半清醒,梦一半叶落。在指尖流过的沙,海边浪花一朵朵,不相遇,才有不约而同。",
|
||||||
"这世俗,太多牵挂留在心间,一点朱砂泪,一曲相诗歌。岁月朦胧,梦醒了人生,风雨相容,演绎了一段风情。雪亦梦,雨亦梦,万张红纸从天洒来。惊动了山,撼动了天。" +
|
"这世俗,太多牵挂留在心间,一点朱砂泪,一曲相诗歌。岁月朦胧,梦醒了人生,风雨相容,演绎了一段风情。雪亦梦,雨亦梦,万张红纸从天洒来。惊动了山,撼动了天。" +
|
||||||
"一纸情愁,一指烟凉。一相思,一思量,水漫岸头,我们都有着自己不同的三生故事。迎一夜秋风,送一世暖阳,一切冰雪里的花开,是我一生的柔情。" +
|
"一纸情愁,一指烟凉。一相思,一思量,水漫岸头,我们都有着自己不同的三生故事。迎一夜秋风,送一世暖阳,一切冰雪里的花开,是我一生的柔情。" +
|
||||||
"记忆中的短笛,有着清风须来的气息,那时我们面向大海,海风在耳边述说着大海边缘的温暖故事。安好一轮冷月,静好了一残红日,这便是我的语言,我的情丝。" +
|
"记忆中的短笛,有着清风须来的气息,那时我们面向大海,海风在耳边述说着大海边缘的温暖故事。安好一轮冷月,静好了一残红日,这便是我的语言,我的情丝。" +
|
||||||
"一漫山水,一段情,留在了岁月,拭去了风,晴雨清风,倒是暖阳拂绿草。" +
|
"一漫山水,一段情,留在了岁月,拭去了风,晴雨清风,倒是暖阳拂绿草。" +
|
||||||
"这便,晨光微好,花开静好……"};
|
"这便,晨光微好,花开静好……"};
|
||||||
|
|
||||||
private final static Random r = new Random();
|
private final static Random r = new Random();
|
||||||
public static String getLogInfo(){
|
|
||||||
return LOG_INFOS[r.nextInt(LOG_INFOS.length-1)];
|
public static String getLogInfo() {
|
||||||
}
|
return LOG_INFOS[r.nextInt(LOG_INFOS.length - 1)];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,56 +19,66 @@ import java.net.InetSocketAddress;
|
|||||||
* 类说明:日志的广播端 ( Client 端 )
|
* 类说明:日志的广播端 ( Client 端 )
|
||||||
*/
|
*/
|
||||||
public class LogEventBroadcaster {
|
public class LogEventBroadcaster {
|
||||||
private final EventLoopGroup group;
|
private final EventLoopGroup group;
|
||||||
private final Bootstrap bootstrap;
|
private final Bootstrap bootstrap;
|
||||||
|
|
||||||
public LogEventBroadcaster(InetSocketAddress remoteAddress) {
|
public LogEventBroadcaster(InetSocketAddress remoteAddress) {
|
||||||
group = new NioEventLoopGroup();
|
group = new NioEventLoopGroup();
|
||||||
bootstrap = new Bootstrap();
|
bootstrap = new Bootstrap();
|
||||||
//引导该 NioDatagramChannel(无连接的)
|
//引导该 NioDatagramChannel(无连接的)
|
||||||
bootstrap.group(group).channel(NioDatagramChannel.class)
|
bootstrap.group(group).channel(NioDatagramChannel.class)
|
||||||
//todo 设置 SO_BROADCAST 套接字选项(option so_broadcast差异,这里和单播 是有差异的)
|
//todo 设置 SO_BROADCAST 套接字选项(option so_broadcast差异,这里和单播 是有差异的)
|
||||||
.option(ChannelOption.SO_BROADCAST, true)
|
.option(ChannelOption.SO_BROADCAST, true)
|
||||||
.handler(new LogEventEncoder(remoteAddress));
|
.handler(new LogEventEncoder(remoteAddress));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run()
|
||||||
|
throws Exception {
|
||||||
|
//绑定 Channel
|
||||||
|
Channel ch = bootstrap.bind(0).sync().channel();
|
||||||
|
long count = 0;
|
||||||
|
//启动主处理循环,模拟日志发送
|
||||||
|
for (;;) {
|
||||||
|
ch.writeAndFlush(
|
||||||
|
new LogMsg(
|
||||||
|
null, ++count,
|
||||||
|
LogConst.getLogInfo()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
//休眠 2 秒,如果被中断,则退出循环;
|
||||||
|
Thread.sleep(2000);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
Thread.interrupted();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void run() throws Exception {
|
public void stop() {
|
||||||
//绑定 Channel
|
group.shutdownGracefully();
|
||||||
Channel ch = bootstrap.bind(0).sync().channel();
|
}
|
||||||
long count = 0;
|
|
||||||
//启动主处理循环,模拟日志发送
|
public static void main(String[] args)
|
||||||
for (;;) {
|
throws Exception {
|
||||||
ch.writeAndFlush(new LogMsg(null, ++count,
|
|
||||||
LogConst.getLogInfo()));
|
//创建并启动一个新的 UdpQuestionSide 的实例
|
||||||
try {
|
LogEventBroadcaster broadcaster = new LogEventBroadcaster(
|
||||||
//休眠 2 秒,如果被中断,则退出循环;
|
//表明本应用发送的报文并没有一个确定的目的地,也就是进行广播
|
||||||
Thread.sleep(2000);
|
//就是往这个网络下 所有主机发送数据,往这些主机的 LogConst.MONITOR_SIDE_PORT端口 发送数据
|
||||||
} catch (InterruptedException e) {
|
//todo 这里的设置和 单播是有差异的
|
||||||
Thread.interrupted();
|
new InetSocketAddress(
|
||||||
break;
|
"255.255.255.255",
|
||||||
}
|
LogConst.MONITOR_SIDE_PORT
|
||||||
}
|
)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
System.out.println("广播服务启动");
|
||||||
|
broadcaster.run();
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
public void stop() {
|
broadcaster.stop();
|
||||||
group.shutdownGracefully();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
|
|
||||||
//创建并启动一个新的 UdpQuestionSide 的实例
|
|
||||||
LogEventBroadcaster broadcaster = new LogEventBroadcaster(
|
|
||||||
//表明本应用发送的报文并没有一个确定的目的地,也就是进行广播
|
|
||||||
//就是往这个网络下 所有主机发送数据,往这些主机的 LogConst.MONITOR_SIDE_PORT端口 发送数据
|
|
||||||
//todo 这里的设置和 单播是有差异的
|
|
||||||
new InetSocketAddress("255.255.255.255",
|
|
||||||
LogConst.MONITOR_SIDE_PORT));
|
|
||||||
try {
|
|
||||||
System.out.println("广播服务启动");
|
|
||||||
broadcaster.run();
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
broadcaster.stop();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,30 +18,38 @@ 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,
|
||||||
throws Exception {
|
DatagramPacket datagramPacket, List<Object> out
|
||||||
//获取对 DatagramPacket 中的数据(ByteBuf)的引用
|
)
|
||||||
ByteBuf data = datagramPacket.content();
|
throws Exception {
|
||||||
long time = new Date().getTime();
|
//获取对 DatagramPacket 中的数据(ByteBuf)的引用
|
||||||
|
ByteBuf data = datagramPacket.content();
|
||||||
|
long time = new Date().getTime();
|
||||||
|
|
||||||
System.out.println(time+" 接受到发送的消息:");
|
System.out.println(time + " 接受到发送的消息:");
|
||||||
//获得消息的id
|
//获得消息的id
|
||||||
long msgId = data.readLong();
|
long msgId = data.readLong();
|
||||||
//获得分隔符SEPARATOR
|
//获得分隔符SEPARATOR
|
||||||
byte sepa = data.readByte();
|
byte sepa = data.readByte();
|
||||||
//获取读索引的当前位置,就是分隔符的索引+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,
|
||||||
//构建一个新的 LogMsg 对象,并且将它添加到(已经解码的消息的)列表中
|
data.readableBytes()
|
||||||
LogMsg event = new LogMsg(datagramPacket.sender(),
|
).toString(CharsetUtil.UTF_8);
|
||||||
msgId, sendMsg);
|
//构建一个新的 LogMsg 对象,并且将它添加到(已经解码的消息的)列表中
|
||||||
//作为本handler的处理结果,交给后面的handler进行处理
|
LogMsg event = new LogMsg(
|
||||||
out.add(event);
|
datagramPacket.sender(),
|
||||||
}
|
msgId, sendMsg
|
||||||
|
);
|
||||||
|
//作为本handler的处理结果,交给后面的handler进行处理
|
||||||
|
out.add(event);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,31 +18,36 @@ import java.util.List;
|
|||||||
* 作者:DarkKIng
|
* 作者:DarkKIng
|
||||||
* 类说明:编码,将实际的日志实体类编码为DatagramPacket
|
* 类说明:编码,将实际的日志实体类编码为DatagramPacket
|
||||||
*/
|
*/
|
||||||
public class LogEventEncoder extends MessageToMessageEncoder<LogMsg> {
|
public class LogEventEncoder
|
||||||
private final InetSocketAddress remoteAddress;
|
extends
|
||||||
|
MessageToMessageEncoder<LogMsg> {
|
||||||
|
private final InetSocketAddress remoteAddress;
|
||||||
|
|
||||||
//LogEventEncoder 创建了即将被发送到指定的 InetSocketAddress
|
//LogEventEncoder 创建了即将被发送到指定的 InetSocketAddress
|
||||||
// 的 DatagramPacket 消息
|
// 的 DatagramPacket 消息
|
||||||
public LogEventEncoder(InetSocketAddress remoteAddress) {
|
public LogEventEncoder(InetSocketAddress remoteAddress) {
|
||||||
this.remoteAddress = remoteAddress;
|
this.remoteAddress = remoteAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void encode(ChannelHandlerContext channelHandlerContext,
|
protected void encode(
|
||||||
LogMsg logMsg, List<Object> out) throws Exception {
|
ChannelHandlerContext channelHandlerContext,
|
||||||
byte[] msg = logMsg.getMsg().getBytes(CharsetUtil.UTF_8);
|
LogMsg logMsg, List<Object> out
|
||||||
//容量的计算:两个long型+消息的内容+分割符
|
)
|
||||||
ByteBuf buf = channelHandlerContext.alloc()
|
throws Exception {
|
||||||
.buffer(8*2 + msg.length + 1);
|
byte[] msg = logMsg.getMsg().getBytes(CharsetUtil.UTF_8);
|
||||||
//将发送时间写入到 ByteBuf中
|
//容量的计算:两个long型+消息的内容+分割符
|
||||||
buf.writeLong(logMsg.getTime());
|
ByteBuf buf = channelHandlerContext.alloc()
|
||||||
//将消息id写入到 ByteBuf中
|
.buffer(8 * 2 + msg.length + 1);
|
||||||
buf.writeLong(logMsg.getMsgId());
|
//将发送时间写入到 ByteBuf中
|
||||||
//添加一个 SEPARATOR
|
buf.writeLong(logMsg.getTime());
|
||||||
buf.writeByte(LogMsg.SEPARATOR);
|
//将消息id写入到 ByteBuf中
|
||||||
//将日志消息写入 ByteBuf中
|
buf.writeLong(logMsg.getMsgId());
|
||||||
buf.writeBytes(msg);
|
//添加一个 SEPARATOR
|
||||||
//将一个拥有数据和目的地地址的新 DatagramPacket 添加到出站的消息列表中
|
buf.writeByte(LogMsg.SEPARATOR);
|
||||||
out.add(new DatagramPacket(buf, remoteAddress));
|
//将日志消息写入 ByteBuf中
|
||||||
}
|
buf.writeBytes(msg);
|
||||||
|
//将一个拥有数据和目的地地址的新 DatagramPacket 添加到出站的消息列表中
|
||||||
|
out.add(new DatagramPacket(buf, remoteAddress));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -14,29 +14,36 @@ 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,
|
||||||
//当异常发生时,打印栈跟踪信息,并关闭对应的 Channel
|
Throwable cause
|
||||||
cause.printStackTrace();
|
)
|
||||||
ctx.close();
|
throws Exception {
|
||||||
}
|
//当异常发生时,打印栈跟踪信息,并关闭对应的 Channel
|
||||||
|
cause.printStackTrace();
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void channelRead0(ChannelHandlerContext ctx,
|
public void channelRead0(
|
||||||
LogMsg event) throws Exception {
|
ChannelHandlerContext ctx,
|
||||||
//创建 StringBuilder,并且构建输出的字符串
|
LogMsg event
|
||||||
StringBuilder builder = new StringBuilder();
|
)
|
||||||
builder.append(event.getTime());
|
throws Exception {
|
||||||
builder.append(" [");
|
//创建 StringBuilder,并且构建输出的字符串
|
||||||
builder.append(event.getSource().toString());
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("] :[");
|
builder.append(event.getTime());
|
||||||
builder.append(event.getMsgId());
|
builder.append(" [");
|
||||||
builder.append("] :");
|
builder.append(event.getSource().toString());
|
||||||
builder.append(event.getMsg());
|
builder.append("] :[");
|
||||||
//打印 LogMsg 的数据
|
builder.append(event.getMsgId());
|
||||||
System.out.println(builder.toString());
|
builder.append("] :");
|
||||||
}
|
builder.append(event.getMsg());
|
||||||
|
//打印 LogMsg 的数据
|
||||||
|
System.out.println(builder.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,58 +6,55 @@ 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;
|
||||||
|
|
||||||
public LogEventMonitor(InetSocketAddress address) {
|
public LogEventMonitor(InetSocketAddress address) {
|
||||||
group = new NioEventLoopGroup();
|
group = new NioEventLoopGroup();
|
||||||
bootstrap = new Bootstrap();
|
bootstrap = new Bootstrap();
|
||||||
//引导该 NioDatagramChannel
|
//引导该 NioDatagramChannel
|
||||||
bootstrap.group(group)
|
bootstrap.group(group)
|
||||||
.channel(NioDatagramChannel.class)
|
.channel(NioDatagramChannel.class)
|
||||||
//设置套接字选项 SO_BROADCAST
|
//设置套接字选项 SO_BROADCAST
|
||||||
.option(ChannelOption.SO_BROADCAST, true)
|
.option(ChannelOption.SO_BROADCAST, true)
|
||||||
//允许重用
|
//允许重用
|
||||||
.option(ChannelOption.SO_REUSEADDR,true)
|
.option(ChannelOption.SO_REUSEADDR, true)
|
||||||
.handler( new ChannelInitializer<Channel>() {
|
.handler(new ChannelInitializer<Channel>() {
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(Channel channel)
|
protected void initChannel(Channel channel)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
ChannelPipeline pipeline = channel.pipeline();
|
ChannelPipeline pipeline = channel.pipeline();
|
||||||
pipeline.addLast(new LogEventDecoder());
|
pipeline.addLast(new LogEventDecoder());
|
||||||
pipeline.addLast(new LogEventHandler());
|
pipeline.addLast(new LogEventHandler());
|
||||||
}
|
}
|
||||||
} )
|
})
|
||||||
.localAddress(address);
|
.localAddress(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Channel bind() {
|
public Channel bind() {
|
||||||
//绑定 Channel。注意,DatagramChannel 是无连接的
|
//绑定 Channel。注意,DatagramChannel 是无连接的
|
||||||
return bootstrap.bind().syncUninterruptibly().channel();
|
return bootstrap.bind().syncUninterruptibly().channel();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
group.shutdownGracefully();
|
group.shutdownGracefully();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args)
|
||||||
//构造一个新的 UdpAnswerSide并指明监听端口
|
throws Exception {
|
||||||
LogEventMonitor monitor = new LogEventMonitor(
|
//构造一个新的 UdpAnswerSide并指明监听端口
|
||||||
new InetSocketAddress(LogConst.MONITOR_SIDE_PORT));
|
LogEventMonitor monitor = new LogEventMonitor(
|
||||||
try {
|
new InetSocketAddress(LogConst.MONITOR_SIDE_PORT)
|
||||||
//绑定本地监听端口
|
);
|
||||||
Channel channel = monitor.bind();
|
try {
|
||||||
System.out.println("UdpAnswerSide running");
|
//绑定本地监听端口
|
||||||
channel.closeFuture().sync();
|
Channel channel = monitor.bind();
|
||||||
} finally {
|
System.out.println("UdpAnswerSide running");
|
||||||
monitor.stop();
|
channel.closeFuture().sync();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
monitor.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,51 +13,53 @@ import java.net.InetSocketAddress;
|
|||||||
* 类说明:日志实体类
|
* 类说明:日志实体类
|
||||||
*/
|
*/
|
||||||
public final class LogMsg {
|
public final class LogMsg {
|
||||||
public static final byte SEPARATOR = (byte) ':';
|
public static final byte SEPARATOR = (byte) ':';
|
||||||
/*源的 InetSocketAddress*/
|
/* 源的 InetSocketAddress */
|
||||||
private final InetSocketAddress source;
|
private final InetSocketAddress source;
|
||||||
/*消息内容*/
|
/* 消息内容 */
|
||||||
private final String msg;
|
private final String msg;
|
||||||
/*消息id*/
|
/* 消息id */
|
||||||
private final long msgId;
|
private final long msgId;
|
||||||
/*消息发送的时间*/
|
/* 消息发送的时间 */
|
||||||
private final long time;
|
private final long time;
|
||||||
|
|
||||||
//用于传入消息的构造函数
|
//用于传入消息的构造函数
|
||||||
public LogMsg(String msg) {
|
public LogMsg(String msg) {
|
||||||
this(null, msg,-1,System.currentTimeMillis());
|
this(null, msg, -1, System.currentTimeMillis());
|
||||||
}
|
}
|
||||||
|
|
||||||
//用于传出消息的构造函数
|
//用于传出消息的构造函数
|
||||||
public LogMsg(InetSocketAddress source, long msgId,
|
public LogMsg(
|
||||||
String msg) {
|
InetSocketAddress source, long msgId,
|
||||||
this(source,msg,msgId,System.currentTimeMillis());
|
String msg
|
||||||
}
|
) {
|
||||||
|
this(source, msg, msgId, System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
public LogMsg(InetSocketAddress source, String msg, long msgId, long time) {
|
public LogMsg(InetSocketAddress source, String msg, long msgId, long time) {
|
||||||
this.source = source;
|
this.source = source;
|
||||||
this.msg = msg;
|
this.msg = msg;
|
||||||
this.msgId = msgId;
|
this.msgId = msgId;
|
||||||
this.time = time;
|
this.time = time;
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回发送 LogMsg 的源的 InetSocketAddress
|
//返回发送 LogMsg 的源的 InetSocketAddress
|
||||||
public InetSocketAddress getSource() {
|
public InetSocketAddress getSource() {
|
||||||
return source;
|
return source;
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回消息内容
|
//返回消息内容
|
||||||
public String getMsg() {
|
public String getMsg() {
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回消息id
|
//返回消息id
|
||||||
public long getMsgId() {
|
public long getMsgId() {
|
||||||
return msgId;
|
return msgId;
|
||||||
}
|
}
|
||||||
|
|
||||||
//返回消息中的时间
|
//返回消息中的时间
|
||||||
public long getTime() {
|
public long getTime() {
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,42 +18,42 @@ 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(下发订阅信令) 👌
|
||||||
* 初始化:
|
* 初始化:
|
||||||
* 0x03(切换手自动) 👌
|
* 0x03(切换手自动) 👌
|
||||||
* 0x14(手动定位) 👌
|
* 0x14(手动定位) 👌
|
||||||
* 0x17(查询机器人运行状态) 👌
|
* 0x17(查询机器人运行状态) 👌
|
||||||
* 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()){
|
||||||
|
// System.out.println();
|
||||||
|
// System.out.println("received transationId : "+ "isok:"+rcv.isOk());
|
||||||
|
// for (byte b:rcv.getValue()){
|
||||||
|
// 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());
|
// QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes());
|
||||||
// System.out.println();
|
|
||||||
// System.out.println("received transationId : "+ "isok:"+rcv.isOk());
|
|
||||||
// for (byte b:rcv.getValue()){
|
|
||||||
// System.out.print(byteToHex(b)+" ");
|
|
||||||
// }
|
|
||||||
// }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()){
|
||||||
|
// System.out.println();
|
||||||
|
// System.out.println("received transationId : "+ "isok:"+rcv.isOk());
|
||||||
|
// for (byte b:rcv.getValue()){
|
||||||
|
// 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());
|
// //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("received transationId : "+ "isok:"+rcv.isOk());
|
|
||||||
// for (byte b:rcv.getValue()){
|
|
||||||
// System.out.print(byteToHex(b)+" ");
|
|
||||||
// }
|
|
||||||
// }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(导航控制导航点控制)
|
||||||
@ -212,196 +224,235 @@ public class KCCommandDemo {
|
|||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String byteToHex(byte b) {
|
||||||
|
// 将byte转换为无符号整数
|
||||||
|
int unsignedByte = b & 0xFF;
|
||||||
|
// 使用Integer.toHexString方法转换为十六进制字符串
|
||||||
|
String hexString = Integer.toHexString(unsignedByte);
|
||||||
|
// 如果字符串长度为1,需要在前面补0
|
||||||
|
if (hexString.length() == 1) {
|
||||||
|
return "0" + hexString;
|
||||||
}
|
}
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void printInfo(AgvEvent agvEvent) {
|
||||||
public static String byteToHex(byte b) {
|
System.out.println("sended transationId : " + agvEvent.getTransationIdString());
|
||||||
// 将byte转换为无符号整数
|
for (byte b : agvEvent.toBytes().getBody()) {
|
||||||
int unsignedByte = b & 0xFF;
|
System.out.print(byteToHex(b) + " ");
|
||||||
// 使用Integer.toHexString方法转换为十六进制字符串
|
|
||||||
String hexString = Integer.toHexString(unsignedByte);
|
|
||||||
// 如果字符串长度为1,需要在前面补0
|
|
||||||
if (hexString.length() == 1) {
|
|
||||||
return "0" + hexString;
|
|
||||||
}
|
|
||||||
return hexString;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void printInfo(AgvEvent agvEvent){
|
public static void printInfo(RcvEventPackage rcv) {
|
||||||
System.out.println("sended transationId : "+agvEvent.getTransationIdString());
|
|
||||||
for (byte b:agvEvent.toBytes().getBody()){
|
for (byte b : rcv.getDataBytes()) {
|
||||||
System.out.print(byteToHex(b)+" ");
|
System.out.print(byteToHex(b) + " ");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static void printInfo(RcvEventPackage rcv){
|
/**
|
||||||
|
* decs: read操作
|
||||||
|
* 指令:0x02
|
||||||
|
* author: caixiang
|
||||||
|
* date: 2025/1/17 16:25
|
||||||
|
*/
|
||||||
|
public static AgvEvent readValue() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_READ);
|
||||||
|
List<ReadValueMember> readValueMemberList = new ArrayList<>();
|
||||||
|
ReadValueMember readValueMember1 = new ReadValueMember(Short.valueOf("0"), Short.valueOf("1"));
|
||||||
|
readValueMemberList.add(readValueMember1);
|
||||||
|
|
||||||
for (byte b: rcv.getDataBytes()){
|
List<ReadStrValue> readStrValueList = new ArrayList<>();
|
||||||
System.out.print(byteToHex(b)+" ");
|
ReadStrValue readStrValue = new ReadStrValue("Battry_SOC", 1, readValueMemberList);
|
||||||
}
|
readStrValueList.add(readStrValue);
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
ReadParam readParam = new ReadParam(agvEvent.getTransationId(), readStrValueList);
|
||||||
* decs: read操作
|
agvEvent.setBody(readParam.toBytes());
|
||||||
* 指令:0x02
|
|
||||||
* author: caixiang
|
|
||||||
* date: 2025/1/17 16:25
|
|
||||||
* */
|
|
||||||
public static AgvEvent readValue() {
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_READ);
|
|
||||||
List<ReadValueMember> readValueMemberList = new ArrayList<>();
|
|
||||||
ReadValueMember readValueMember1 = new ReadValueMember(Short.valueOf("0"),Short.valueOf("1"));
|
|
||||||
readValueMemberList.add(readValueMember1);
|
|
||||||
|
|
||||||
List<ReadStrValue> readStrValueList = new ArrayList<>();
|
return agvEvent;
|
||||||
ReadStrValue readStrValue = new ReadStrValue("Battry_SOC", 1, readValueMemberList);
|
}
|
||||||
readStrValueList.add(readStrValue);
|
|
||||||
|
|
||||||
ReadParam readParam = new ReadParam(agvEvent.getTransationId(),readStrValueList );
|
/**
|
||||||
agvEvent.setBody(readParam.toBytes());
|
* decs: write操作
|
||||||
|
* 指令:0x03
|
||||||
|
* author: caixiang
|
||||||
|
* date: 2025/1/17 16:25
|
||||||
|
*/
|
||||||
|
public static AgvEvent writeValue() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE);
|
||||||
|
|
||||||
return agvEvent;
|
List<WriteValueMember> valueMemberList = new ArrayList<>();
|
||||||
}
|
WriteValueMember valueMember1 = new WriteValueMember(
|
||||||
|
Short.valueOf("0"), Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)
|
||||||
|
);
|
||||||
|
valueMemberList.add(valueMember1);
|
||||||
|
|
||||||
/**
|
List<WriteStrValue> strValueList = new ArrayList<>();
|
||||||
* decs: write操作
|
WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList);
|
||||||
* 指令:0x03
|
strValueList.add(strValue);
|
||||||
* author: caixiang
|
|
||||||
* date: 2025/1/17 16:25
|
|
||||||
* */
|
|
||||||
public static AgvEvent writeValue() {
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE);
|
|
||||||
|
|
||||||
List<WriteValueMember> valueMemberList = new ArrayList<>();
|
WriteParam param = new WriteParam(1, strValueList);
|
||||||
WriteValueMember valueMember1 = new WriteValueMember(Short.valueOf("0"),Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN));
|
agvEvent.setBody(param.toBytes());
|
||||||
valueMemberList.add(valueMember1);
|
|
||||||
|
|
||||||
List<WriteStrValue> strValueList = new ArrayList<>();
|
return agvEvent;
|
||||||
WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList);
|
}
|
||||||
strValueList.add(strValue);
|
|
||||||
|
|
||||||
WriteParam param = new WriteParam(1,strValueList );
|
|
||||||
agvEvent.setBody(param.toBytes());
|
|
||||||
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decs: 查询机器人状态
|
||||||
|
* 指令:0xAF
|
||||||
|
* author: caixiang
|
||||||
|
* date: 2025/1/17 16:25
|
||||||
|
*/
|
||||||
|
public static AgvEvent queryStatus() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
|
||||||
|
return agvEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decs: 导航控制
|
||||||
|
* 指令:0xAE
|
||||||
|
* author: caixiang
|
||||||
|
* date: 2025/1/17 16:25
|
||||||
|
*/
|
||||||
|
public static AgvEvent navigationControl() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
|
||||||
|
//TODO 构建
|
||||||
|
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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
};
|
||||||
|
Point[] points = new Point[]{
|
||||||
|
new Point(
|
||||||
|
0, 1, 1f, (byte) 0x00, ByteUtils.usintTo1Byte(pointActions1.length), pointActions1
|
||||||
|
),
|
||||||
|
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
|
||||||
|
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[]{
|
||||||
|
new Path(
|
||||||
|
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
|
||||||
|
);
|
||||||
|
agvEvent.setBody(navigationParam.toBytes());
|
||||||
|
|
||||||
|
return agvEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decs: 确认机器人位置
|
||||||
|
* 指令:0x1F
|
||||||
|
* author: caixiang
|
||||||
|
* date: 2025/1/17 16:25
|
||||||
|
*/
|
||||||
|
public static AgvEvent confirmInitialPosition() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_CONFIRM_ROBOT_POSITION);
|
||||||
|
return agvEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decs: 查询机器人运行状态
|
||||||
|
* 指令:0x17
|
||||||
|
* author: caixiang
|
||||||
|
* date: 2025/1/17 16:25
|
||||||
|
*/
|
||||||
|
public static AgvEvent queryRobotRunStatus() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_RUN_STATUS);
|
||||||
|
return agvEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AgvEvent manualLocation() {
|
||||||
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ROBOT_SET_POSITION);
|
||||||
|
RobotSetPosition robotSetPosition = new RobotSetPosition(11, 11, 11);
|
||||||
|
byte[] bytes = robotSetPosition.toBytes();
|
||||||
|
agvEvent.setBody(bytes);
|
||||||
|
return agvEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* decs: 查询机器人状态
|
* decs: 查询载货状态
|
||||||
* 指令:0xAF
|
* 指令:0xB0
|
||||||
* author: caixiang
|
* author: caixiang
|
||||||
* date: 2025/1/17 16:25
|
* date: 2025/1/17 16:25
|
||||||
* */
|
*/
|
||||||
public static AgvEvent queryStatus() {
|
public static AgvEvent checkCargoStatus() {
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
|
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_CARRY_STATUS);
|
||||||
return agvEvent;
|
return agvEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* decs: 导航控制
|
* decs: 下发订阅信息
|
||||||
* 指令:0xAE
|
* 指令:0xB1
|
||||||
* author: caixiang
|
* author: caixiang
|
||||||
* date: 2025/1/17 16:25
|
* date: 2025/1/17 16:25
|
||||||
* */
|
*/
|
||||||
public static AgvEvent navigationControl() {
|
public static AgvEvent issueSubscribe() {
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS);
|
List<SubscribeInfo> subscribeInfoList = new ArrayList<>();
|
||||||
//TODO 构建
|
SubscribeInfo subscribeInfo = new SubscribeInfo(
|
||||||
Integer orderId = 1;
|
new byte[]{(byte) 0xaf, (byte) 0x00}, (short) 100, 1000
|
||||||
|
);
|
||||||
//构建point
|
//SubscribeInfo subscribeInfo = new SubscribeInfo(new byte[]{(byte)0xb0,(byte)0x00}, (short) 100,1000);
|
||||||
Action[] pointActions1 = new Action[]{
|
subscribeInfoList.add(subscribeInfo);
|
||||||
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
|
SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList);
|
||||||
//,new Action()... 每一个point 可以绑定一个或者多个 action
|
AgvEvent agvEvent = new AgvEvent(
|
||||||
};
|
AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION, subscribeParam.toBytes()
|
||||||
Action[] pointActions2 = new Action[]{
|
);
|
||||||
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
|
return agvEvent;
|
||||||
};
|
}
|
||||||
Action[] pointActions3 = new Action[]{
|
|
||||||
new Action(ActionSet.stop0x01, (byte) 0x00, 1, ActionSet.stop0x01_paramsize, ActionSet.stop0x01(orderId, (byte) 0x01))
|
|
||||||
};
|
|
||||||
Point[] points = new Point[]{
|
|
||||||
new Point(0, 1, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions1.length),pointActions1),
|
|
||||||
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
|
|
||||||
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[]{
|
|
||||||
new Path(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);
|
|
||||||
agvEvent.setBody(navigationParam.toBytes());
|
|
||||||
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decs: 确认机器人位置
|
|
||||||
* 指令:0x1F
|
|
||||||
* author: caixiang
|
|
||||||
* date: 2025/1/17 16:25
|
|
||||||
* */
|
|
||||||
public static AgvEvent confirmInitialPosition() {
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_CONFIRM_ROBOT_POSITION);
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decs: 查询机器人运行状态
|
|
||||||
* 指令:0x17
|
|
||||||
* author: caixiang
|
|
||||||
* date: 2025/1/17 16:25
|
|
||||||
* */
|
|
||||||
public static AgvEvent queryRobotRunStatus() {
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_RUN_STATUS);
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static AgvEvent manualLocation() {
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ROBOT_SET_POSITION);
|
|
||||||
RobotSetPosition robotSetPosition = new RobotSetPosition(11, 11, 11);
|
|
||||||
byte[] bytes = robotSetPosition.toBytes();
|
|
||||||
agvEvent.setBody(bytes);
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decs: 查询载货状态
|
|
||||||
* 指令:0xB0
|
|
||||||
* author: caixiang
|
|
||||||
* date: 2025/1/17 16:25
|
|
||||||
* */
|
|
||||||
public static AgvEvent checkCargoStatus() {
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_CARRY_STATUS);
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decs: 下发订阅信息
|
|
||||||
* 指令:0xB1
|
|
||||||
* author: caixiang
|
|
||||||
* date: 2025/1/17 16:25
|
|
||||||
* */
|
|
||||||
public static AgvEvent issueSubscribe() {
|
|
||||||
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)0xb0,(byte)0x00}, (short) 100,1000);
|
|
||||||
subscribeInfoList.add(subscribeInfo);
|
|
||||||
SubscribeParam subscribeParam = new SubscribeParam(subscribeInfoList);
|
|
||||||
AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION,subscribeParam.toBytes());
|
|
||||||
return agvEvent;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
@ -22,17 +17,17 @@ public class BaseCommand {
|
|||||||
return hexString;
|
return hexString;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printInfo(AgvEvent agvEvent){
|
public static void printInfo(AgvEvent agvEvent) {
|
||||||
System.out.println("sended transationId : "+agvEvent.getTransationIdString());
|
System.out.println("sended transationId : " + agvEvent.getTransationIdString());
|
||||||
for (byte b:agvEvent.toBytes().getBody()){
|
for (byte b : agvEvent.toBytes().getBody()) {
|
||||||
System.out.print(byteToHex(b)+" ");
|
System.out.print(byteToHex(b) + " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printInfo(RcvEventPackage rcv){
|
public static void printInfo(RcvEventPackage rcv) {
|
||||||
|
|
||||||
for (byte b: rcv.getDataBytes()){
|
for (byte b : rcv.getDataBytes()) {
|
||||||
System.out.print(byteToHex(b)+" ");
|
System.out.print(byteToHex(b) + " ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
@ -28,12 +25,13 @@ public class ConfirmRelocation extends BaseCommand{
|
|||||||
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 {
|
}
|
||||||
|
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)) {
|
||||||
//切换订单重置参数
|
//切换订单重置参数
|
||||||
@ -116,17 +128,19 @@ public class HybridNavigation extends BaseCommand{
|
|||||||
AgvEvent agvEvent = navigationControl(newSourcePoint, newDestinationPoint, pathID, operation);
|
AgvEvent agvEvent = navigationControl(newSourcePoint, newDestinationPoint, pathID, operation);
|
||||||
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("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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 初始化参数
|
* 初始化参数
|
||||||
|
*
|
||||||
* @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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
@ -27,19 +24,21 @@ public class ManualPosition extends BaseCommand{
|
|||||||
AgvEvent agvEvent = manualLocation(agvX, agvY, agvAngle);
|
AgvEvent agvEvent = manualLocation(agvX, agvY, agvAngle);
|
||||||
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());
|
||||||
throw new RuntimeException("0x14 failed");
|
throw new RuntimeException("0x14 failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
@ -29,19 +26,22 @@ public class QryRobotRunStatus extends BaseCommand{
|
|||||||
AgvEvent agvEvent = queryRobotRunStatus();
|
AgvEvent agvEvent = queryRobotRunStatus();
|
||||||
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());
|
//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());
|
||||||
for (byte b:rcv.getValue()){
|
for (byte b : rcv.getValue()) {
|
||||||
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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,16 +28,22 @@ 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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,60 +13,64 @@ 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);
|
||||||
//todo 订阅参数构建完毕 去写 回调部分
|
//todo 订阅参数构建完毕 去写 回调部分
|
||||||
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 transationId : "+ "isok:"+rcv.isOk());
|
System.out.println("received transationId : " + "isok:" + rcv.isOk());
|
||||||
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) {
|
||||||
//载货
|
//载货
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,18 +42,20 @@ public class SubRobotStatue extends BaseCommand {
|
|||||||
printInfo(agvEvent);
|
printInfo(agvEvent);
|
||||||
//todo 订阅参数构建完毕 去写 回调部分
|
//todo 订阅参数构建完毕 去写 回调部分
|
||||||
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 transationId : "+ "isok:"+rcv.isOk());
|
System.out.println("received transationId : " + "isok:" + rcv.isOk());
|
||||||
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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,31 +12,30 @@ 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<>();
|
||||||
WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList);
|
WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList);
|
||||||
strValueList.add(strValue);
|
strValueList.add(strValue);
|
||||||
|
|
||||||
WriteParam param = new WriteParam(1,strValueList );
|
WriteParam param = new WriteParam(1, strValueList);
|
||||||
agvEvent.setBody(param.toBytes());
|
agvEvent.setBody(param.toBytes());
|
||||||
|
|
||||||
return agvEvent;
|
return agvEvent;
|
||||||
@ -47,19 +46,21 @@ public class SwitchAutomaticMode extends BaseCommand{
|
|||||||
AgvEvent agvEvent = writeValue();
|
AgvEvent agvEvent = writeValue();
|
||||||
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("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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,31 +12,30 @@ 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<>();
|
||||||
WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList);
|
WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList);
|
||||||
strValueList.add(strValue);
|
strValueList.add(strValue);
|
||||||
|
|
||||||
WriteParam param = new WriteParam(1,strValueList );
|
WriteParam param = new WriteParam(1, strValueList);
|
||||||
agvEvent.setBody(param.toBytes());
|
agvEvent.setBody(param.toBytes());
|
||||||
|
|
||||||
return agvEvent;
|
return agvEvent;
|
||||||
@ -47,19 +46,21 @@ public class SwitchManualMode extends BaseCommand{
|
|||||||
AgvEvent agvEvent = writeValue();
|
AgvEvent agvEvent = writeValue();
|
||||||
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("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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,20 +7,23 @@ import org.opentcs.kc.udp.io.UDPClient;
|
|||||||
/**
|
/**
|
||||||
* 作者:蔡翔
|
* 作者:蔡翔
|
||||||
*/
|
*/
|
||||||
public class AgvUdpChannelInitializer extends ChannelInitializer<NioDatagramChannel> {
|
public class AgvUdpChannelInitializer
|
||||||
private UDPClient client;
|
extends
|
||||||
|
ChannelInitializer<NioDatagramChannel> {
|
||||||
|
private UDPClient client;
|
||||||
|
|
||||||
public AgvUdpChannelInitializer(UDPClient client) {
|
public AgvUdpChannelInitializer(UDPClient client) {
|
||||||
System.out.println(client.getHost());
|
System.out.println(client.getHost());
|
||||||
this.client = client;
|
this.client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void initChannel(NioDatagramChannel channel) throws Exception {
|
protected void initChannel(NioDatagramChannel channel)
|
||||||
// Modbus
|
throws Exception {
|
||||||
// 在管道中添加我们自己的接收数据实现方法
|
// 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
|
||||||
// channel.pipeline().addLast(
|
// channel.pipeline().addLast(
|
||||||
// new LengthFieldBasedFrameDecoder(
|
// new LengthFieldBasedFrameDecoder(
|
||||||
// 200,
|
// 200,
|
||||||
@ -30,7 +33,7 @@ public class AgvUdpChannelInitializer extends ChannelInitializer<NioDatagramChan
|
|||||||
// 7,
|
// 7,
|
||||||
// true)
|
// true)
|
||||||
// );
|
// );
|
||||||
channel.pipeline().addLast(new AgvUdpDecode(this.client)); //InBoundHandler
|
channel.pipeline().addLast(new AgvUdpDecode(this.client)); //InBoundHandler
|
||||||
//channel.pipeline().addLast(new AgvUdpEncode()); //OutBoundHandler
|
//channel.pipeline().addLast(new AgvUdpEncode()); //OutBoundHandler
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,78 +11,77 @@ 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;
|
||||||
|
|
||||||
//授权码16字节 + 报文头8个字节 + 报文数据长度2个字节 + 保留2字节 = 28字节
|
//授权码16字节 + 报文头8个字节 + 报文数据长度2个字节 + 保留2字节 = 28字节
|
||||||
private static final int HEADER_SIZE = 28;
|
private static final int HEADER_SIZE = 28;
|
||||||
|
|
||||||
public AgvUdpDecode(UDPClient client) {
|
public AgvUdpDecode(UDPClient client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
|
||||||
|
throws Exception {
|
||||||
|
//获得应答,DatagramPacket提供了content()方法取得报文的实际内容
|
||||||
|
ByteBuf in = msg.content();
|
||||||
|
if (in.readableBytes() < HEADER_SIZE) {
|
||||||
|
throw new Exception("readed bytes < header length");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
int dataLength = in.getShortLE(24);
|
||||||
protected void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg)
|
if (dataLength < 0) {
|
||||||
throws Exception {
|
throw new Exception(
|
||||||
//获得应答,DatagramPacket提供了content()方法取得报文的实际内容
|
"bodyLength [" + dataLength + "] is not right, remote:" + ctx.channel().remoteAddress()
|
||||||
ByteBuf in = msg.content();
|
);
|
||||||
if (in.readableBytes() < HEADER_SIZE){
|
|
||||||
throw new Exception("readed bytes < header length");
|
|
||||||
}
|
|
||||||
|
|
||||||
int dataLength = in.getShortLE(24);
|
|
||||||
if (dataLength < 0) {
|
|
||||||
throw new Exception("bodyLength [" + dataLength + "] is not right, remote:" + ctx.channel().remoteAddress());
|
|
||||||
}
|
|
||||||
|
|
||||||
int neededLength = HEADER_SIZE + dataLength;
|
|
||||||
int isDataEnough = in.readableBytes() - neededLength;
|
|
||||||
|
|
||||||
|
|
||||||
//收到的数据是否足够组包
|
|
||||||
if(isDataEnough<0){
|
|
||||||
// 不够消息体长度(剩下的buffe组不了消息体),重新去组包
|
|
||||||
throw new Exception("readed bytes < content length");
|
|
||||||
}else {
|
|
||||||
|
|
||||||
//todo这里重写subscribe 的逻辑,注意要区分是 订阅的还是 主动请求的。
|
|
||||||
//组包成功
|
|
||||||
byte[] body = new byte[neededLength];
|
|
||||||
in.readBytes(body);
|
|
||||||
//System.out.println("received bytes :"+ Arrays.toString(body));
|
|
||||||
String uuid = body[18]+"-"+body[19];
|
|
||||||
Package mbPackage = new Package(body,uuid);
|
|
||||||
byte commandCode = body[21];
|
|
||||||
|
|
||||||
if(body[18]==(byte)0x00 && body[19]==(byte)0x00){
|
|
||||||
|
|
||||||
//获取响应IP
|
|
||||||
InetSocketAddress sender = msg.sender();
|
|
||||||
String hostAddress = sender.getAddress().getHostAddress();
|
|
||||||
|
|
||||||
if(commandCode == (byte)0xAF ){
|
|
||||||
client.subscribe0xAF(new RcvEventPackage(body[22],body));
|
|
||||||
}else if(commandCode == (byte)0xB0){
|
|
||||||
client.subscribe0xB0(new RcvEventPackage(body[22],body));
|
|
||||||
}else {
|
|
||||||
SendedList.set(uuid , mbPackage);
|
|
||||||
}
|
|
||||||
}else {
|
|
||||||
SendedList.set(uuid , mbPackage);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
int neededLength = HEADER_SIZE + dataLength;
|
||||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
|
int isDataEnough = in.readableBytes() - neededLength;
|
||||||
throws Exception {
|
|
||||||
cause.printStackTrace();
|
|
||||||
ctx.close();
|
//收到的数据是否足够组包
|
||||||
|
if (isDataEnough < 0) {
|
||||||
|
// 不够消息体长度(剩下的buffe组不了消息体),重新去组包
|
||||||
|
throw new Exception("readed bytes < content length");
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
|
||||||
|
//todo这里重写subscribe 的逻辑,注意要区分是 订阅的还是 主动请求的。
|
||||||
|
//组包成功
|
||||||
|
byte[] body = new byte[neededLength];
|
||||||
|
in.readBytes(body);
|
||||||
|
//System.out.println("received bytes :"+ Arrays.toString(body));
|
||||||
|
String uuid = body[18] + "-" + body[19];
|
||||||
|
Package mbPackage = new Package(body, uuid);
|
||||||
|
byte commandCode = body[21];
|
||||||
|
|
||||||
|
if (body[18] == (byte) 0x00 && body[19] == (byte) 0x00) {
|
||||||
|
//获取响应IP
|
||||||
|
InetSocketAddress sender = msg.sender();
|
||||||
|
String hostAddress = sender.getAddress().getHostAddress();
|
||||||
|
|
||||||
|
if (commandCode == (byte) 0xAF || commandCode == (byte) 0xB0) {
|
||||||
|
client.subscribeKC(new RcvEventPackage(body[22], body), body);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SendedList.set(uuid, mbPackage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SendedList.set(uuid, mbPackage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
|
||||||
|
throws Exception {
|
||||||
|
cause.printStackTrace();
|
||||||
|
ctx.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,89 +5,90 @@ import java.util.Arrays;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.opentcs.kc.common.Package;
|
import org.opentcs.kc.common.Package;
|
||||||
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;
|
// 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;
|
||||||
|
|
||||||
//for Request
|
//for Request
|
||||||
//有content 传,没有content 传new byte[]
|
//有content 传,没有content 传new byte[]
|
||||||
public AgvEvent(Byte commandCode) {
|
public AgvEvent(Byte commandCode) {
|
||||||
super(commandCode);
|
super(commandCode);
|
||||||
//初始化
|
//初始化
|
||||||
bodyLength = new byte[]{0x00,0x00};
|
bodyLength = new byte[]{0x00, 0x00};
|
||||||
retain = new byte[]{0x00,0x00};
|
retain = new byte[]{0x00, 0x00};
|
||||||
body = new byte[]{};
|
body = new byte[]{};
|
||||||
}
|
}
|
||||||
public AgvEvent(Byte commandCode,byte[] body) {
|
|
||||||
super(commandCode);
|
|
||||||
//初始化
|
|
||||||
bodyLength = new byte[]{0x00,0x00};
|
|
||||||
retain = new byte[]{0x00,0x00};
|
|
||||||
if(commandCode.equals(AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION)){
|
|
||||||
//依据命令码 构建参数
|
|
||||||
this.bodyLength = ByteUtil.shortToBytes((short) body.length);
|
|
||||||
this.body = body;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setBody(byte[] body) {
|
public AgvEvent(Byte commandCode, byte[] body) {
|
||||||
this.bodyLength = ByteUtil.shortToBytes((short) body.length);
|
super(commandCode);
|
||||||
this.body = body;
|
//初始化
|
||||||
|
bodyLength = new byte[]{0x00, 0x00};
|
||||||
|
retain = new byte[]{0x00, 0x00};
|
||||||
|
if (commandCode.equals(AgvEventConstant.CommandCode_ISSUE_SUBSCRIPTION)) {
|
||||||
|
//依据命令码 构建参数
|
||||||
|
this.bodyLength = ByteUtil.shortToBytes((short) body.length);
|
||||||
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//for Response
|
public void setBody(byte[] body) {
|
||||||
public AgvEvent(Byte serviceCode, Byte commandCode, Byte executionCode) {
|
this.bodyLength = ByteUtil.shortToBytes((short) body.length);
|
||||||
super(serviceCode, commandCode, executionCode);
|
this.body = body;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
//for Response
|
||||||
public Package toBytes() {
|
public AgvEvent(Byte serviceCode, Byte commandCode, Byte executionCode) {
|
||||||
List<Byte> headerBytes = getHeaderBytes();
|
super(serviceCode, commandCode, executionCode);
|
||||||
for (Byte b : bodyLength) {
|
}
|
||||||
headerBytes.add(b);
|
|
||||||
}
|
|
||||||
for (Byte b : retain) {
|
|
||||||
headerBytes.add(b);
|
|
||||||
}
|
|
||||||
for (Byte b : body) {
|
|
||||||
headerBytes.add(b);
|
|
||||||
}
|
|
||||||
byte[] bytes = new byte[headerBytes.size()];
|
|
||||||
for (int i = 0; i < headerBytes.size(); i++) {
|
|
||||||
bytes[i] = headerBytes.get(i);
|
|
||||||
}
|
|
||||||
return new Package(bytes, getTransationIdString());
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTransationIdString() {
|
@Override
|
||||||
return transationId[0]+"-"+transationId[1];
|
public Package toBytes() {
|
||||||
|
List<Byte> headerBytes = getHeaderBytes();
|
||||||
|
for (Byte b : bodyLength) {
|
||||||
|
headerBytes.add(b);
|
||||||
}
|
}
|
||||||
|
for (Byte b : retain) {
|
||||||
|
headerBytes.add(b);
|
||||||
|
}
|
||||||
|
for (Byte b : body) {
|
||||||
|
headerBytes.add(b);
|
||||||
|
}
|
||||||
|
byte[] bytes = new byte[headerBytes.size()];
|
||||||
|
for (int i = 0; i < headerBytes.size(); i++) {
|
||||||
|
bytes[i] = headerBytes.get(i);
|
||||||
|
}
|
||||||
|
return new Package(bytes, getTransationIdString());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
public String getTransationIdString() {
|
||||||
public Package toBytes(Object newValue) {
|
return transationId[0] + "-" + transationId[1];
|
||||||
return null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public Package toBytes(Object newValue) {
|
||||||
return "AgvEvent{" +
|
return null;
|
||||||
"Header=" + headerToString() +
|
}
|
||||||
", bodyLength=" + Arrays.toString(bodyLength) +
|
|
||||||
", body=" + Arrays.toString(body) +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String protocolName() {
|
public String toString() {
|
||||||
return "";
|
return "AgvEvent{" +
|
||||||
}
|
"Header=" + headerToString() +
|
||||||
|
", bodyLength=" + Arrays.toString(bodyLength) +
|
||||||
|
", body=" + Arrays.toString(body) +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String protocolName() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,38 +1,35 @@
|
|||||||
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;
|
||||||
public static final byte MSGTypeRequest = 0x00;
|
public static final byte MSGTypeRequest = 0x00;
|
||||||
public static final byte MSGTypeResponse = 0x01;
|
public static final byte MSGTypeResponse = 0x01;
|
||||||
|
|
||||||
//命令码 开始
|
//命令码 开始
|
||||||
public static final byte ServiceCode = 0x10;
|
public static final byte ServiceCode = 0x10;
|
||||||
|
|
||||||
|
|
||||||
public static final byte CommandCode_READ = 0x02;
|
public static final byte CommandCode_READ = 0x02;
|
||||||
public static final byte CommandCode_WRITE = 0x03;
|
public static final byte CommandCode_WRITE = 0x03;
|
||||||
public static final byte CommandCode_MIXED_ISSUANCE_TASK = (byte) 0xAE;
|
public static final byte CommandCode_MIXED_ISSUANCE_TASK = (byte) 0xAE;
|
||||||
public static final byte CommandCode_QUERY_ROBOT_STATUS = (byte) 0xAF;
|
public static final byte CommandCode_QUERY_ROBOT_STATUS = (byte) 0xAF;
|
||||||
public static final byte CommandCode_QUERY_CARRY_STATUS = (byte) 0xB0;
|
public static final byte CommandCode_QUERY_CARRY_STATUS = (byte) 0xB0;
|
||||||
public static final byte CommandCode_ISSUE_SUBSCRIPTION = (byte) 0xB1;
|
public static final byte CommandCode_ISSUE_SUBSCRIPTION = (byte) 0xB1;
|
||||||
public static final byte CommandCode_ACT_IMMEDIATELY = (byte) 0xB2;
|
public static final byte CommandCode_ACT_IMMEDIATELY = (byte) 0xB2;
|
||||||
public static final byte CommandCode_SET_ABILITY= (byte) 0xB7;
|
public static final byte CommandCode_SET_ABILITY = (byte) 0xB7;
|
||||||
public static final byte CommandCode_ROBOT_SET_POSITION= (byte) 0x14;
|
public static final byte CommandCode_ROBOT_SET_POSITION = (byte) 0x14;
|
||||||
public static final byte CommandCode_GET_ROBOT_POSITION= (byte) 0x15;
|
public static final byte CommandCode_GET_ROBOT_POSITION = (byte) 0x15;
|
||||||
public static final byte CommandCode_NAVIGATION_CONTROL= (byte) 0x16;
|
public static final byte CommandCode_NAVIGATION_CONTROL = (byte) 0x16;
|
||||||
public static final byte CommandCode_QUERY_ROBOT_NAVIGATION_STATUS= (byte) 0x1D;
|
public static final byte CommandCode_QUERY_ROBOT_NAVIGATION_STATUS = (byte) 0x1D;
|
||||||
public static final byte CommandCode_QUERY_ROBOT_RUN_STATUS= (byte) 0x17;
|
public static final byte CommandCode_QUERY_ROBOT_RUN_STATUS = (byte) 0x17;
|
||||||
public static final byte CommandCode_CONFIRM_ROBOT_POSITION= (byte) 0x1F;
|
public static final byte CommandCode_CONFIRM_ROBOT_POSITION = (byte) 0x1F;
|
||||||
//命令码 结束
|
//命令码 结束
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -6,107 +6,102 @@ 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 {
|
||||||
|
|
||||||
|
|
||||||
//常量区域 开始
|
//常量区域 开始
|
||||||
//授权码
|
//授权码
|
||||||
public byte[] authorizationCode;
|
public byte[] authorizationCode;
|
||||||
//header 开始
|
//header 开始
|
||||||
//版本号
|
//版本号
|
||||||
public byte versionNum;
|
public byte versionNum;
|
||||||
//报文类型 0x00:请求报文 ; 0x01:应答报文
|
//报文类型 0x00:请求报文 ; 0x01:应答报文
|
||||||
public byte msgType;
|
public byte msgType;
|
||||||
//request 和 response ,transationId一致,2个字节
|
//request 和 response ,transationId一致,2个字节
|
||||||
public byte[] transationId;
|
public byte[] transationId;
|
||||||
//服务码
|
//服务码
|
||||||
public byte serviceCode;
|
public byte serviceCode;
|
||||||
//命令码,用于区分不同命令,request 和 response 相同
|
//命令码,用于区分不同命令,request 和 response 相同
|
||||||
public byte commandCode;
|
public byte commandCode;
|
||||||
//执行码,应答报文填写,表明命令执行情况,请求数据包置 0
|
//执行码,应答报文填写,表明命令执行情况,请求数据包置 0
|
||||||
public byte executionCode;
|
public byte executionCode;
|
||||||
//保留
|
//保留
|
||||||
public byte retain;
|
public byte retain;
|
||||||
|
|
||||||
//header 结束
|
//header 结束
|
||||||
//常量区域 结束
|
//常量区域 结束
|
||||||
|
|
||||||
|
|
||||||
//request
|
//request
|
||||||
public AgvEventHeader(Byte commandCode) {
|
public AgvEventHeader(Byte commandCode) {
|
||||||
this.authorizationCode = AgvEventConstant.AuthorizationCode;
|
this.authorizationCode = AgvEventConstant.AuthorizationCode;
|
||||||
this.versionNum = AgvEventConstant.VersionNum;
|
this.versionNum = AgvEventConstant.VersionNum;
|
||||||
this.msgType = AgvEventConstant.MSGTypeRequest;
|
this.msgType = AgvEventConstant.MSGTypeRequest;
|
||||||
|
|
||||||
this.transationId = CaffeineUtil.getUUIDAGV();
|
this.transationId = CaffeineUtil.getUUIDAGV();
|
||||||
this.serviceCode = 0x10;
|
this.serviceCode = 0x10;
|
||||||
this.commandCode = commandCode;
|
this.commandCode = commandCode;
|
||||||
this.executionCode = 0x00;
|
this.executionCode = 0x00;
|
||||||
this.retain = 0x00;
|
this.retain = 0x00;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AgvEventHeader(byte[] src) {
|
||||||
|
this.authorizationCode = ByteUtils.copyOfRange(src, 0, 16);
|
||||||
|
this.versionNum = src[16];
|
||||||
|
this.msgType = src[17];
|
||||||
|
this.transationId = ByteUtils.copyOfRange(src, 18, 20);
|
||||||
|
this.serviceCode = src[20];
|
||||||
|
this.commandCode = src[21];
|
||||||
|
this.executionCode = src[22];
|
||||||
|
this.retain = src[23];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//response
|
||||||
|
public AgvEventHeader(Byte serviceCode, Byte commandCode, Byte executionCode) {
|
||||||
|
this.authorizationCode = AgvEventConstant.AuthorizationCode;
|
||||||
|
this.versionNum = AgvEventConstant.VersionNum;
|
||||||
|
this.msgType = AgvEventConstant.MSGTypeResponse;
|
||||||
|
this.transationId = CaffeineUtil.getUUIDAGV();
|
||||||
|
this.serviceCode = serviceCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getTransationId() {
|
||||||
|
return transationId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String headerToString() {
|
||||||
|
return "AgvEventHeader{" +
|
||||||
|
"authorizationCode=" + Arrays.toString(authorizationCode) +
|
||||||
|
", versionNum=" + versionNum +
|
||||||
|
", msgType=" + msgType +
|
||||||
|
", transationId=" + Arrays.toString(transationId) +
|
||||||
|
", serviceCode=" + serviceCode +
|
||||||
|
", commandCode=" + commandCode +
|
||||||
|
", executionCode=" + executionCode +
|
||||||
|
", retain=" + retain +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Byte> getHeaderBytes() {
|
||||||
|
List<Byte> bytes = new ArrayList<>();
|
||||||
|
//add 授权码
|
||||||
|
for (byte b : authorizationCode) {
|
||||||
|
bytes.add(b);
|
||||||
}
|
}
|
||||||
|
//add 协议版本号
|
||||||
public AgvEventHeader(byte[] src){
|
bytes.add(versionNum);
|
||||||
this.authorizationCode = ByteUtils.copyOfRange(src,0,16);
|
//add 报文类型
|
||||||
this.versionNum = src[16];
|
bytes.add(msgType);
|
||||||
this.msgType = src[17];
|
//add 报文标识
|
||||||
this.transationId = ByteUtils.copyOfRange(src,18,20);
|
for (byte b : transationId) {
|
||||||
this.serviceCode = src[20];
|
bytes.add(b);
|
||||||
this.commandCode = src[21];
|
|
||||||
this.executionCode = src[22];
|
|
||||||
this.retain = src[23];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//response
|
|
||||||
public AgvEventHeader(Byte serviceCode, Byte commandCode, Byte executionCode) {
|
|
||||||
this.authorizationCode = AgvEventConstant.AuthorizationCode;
|
|
||||||
this.versionNum = AgvEventConstant.VersionNum;
|
|
||||||
this.msgType = AgvEventConstant.MSGTypeResponse;
|
|
||||||
this.transationId = CaffeineUtil.getUUIDAGV();
|
|
||||||
this.serviceCode = serviceCode;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getTransationId() {
|
|
||||||
return transationId;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String headerToString() {
|
|
||||||
return "AgvEventHeader{" +
|
|
||||||
"authorizationCode=" + Arrays.toString(authorizationCode) +
|
|
||||||
", versionNum=" + versionNum +
|
|
||||||
", msgType=" + msgType +
|
|
||||||
", transationId=" + Arrays.toString(transationId) +
|
|
||||||
", serviceCode=" + serviceCode +
|
|
||||||
", commandCode=" + commandCode +
|
|
||||||
", executionCode=" + executionCode +
|
|
||||||
", retain=" + retain +
|
|
||||||
'}';
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Byte> getHeaderBytes(){
|
|
||||||
List<Byte> bytes = new ArrayList<>();
|
|
||||||
//add 授权码
|
|
||||||
for (byte b : authorizationCode) {
|
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
//add 协议版本号
|
|
||||||
bytes.add(versionNum);
|
|
||||||
//add 报文类型
|
|
||||||
bytes.add(msgType);
|
|
||||||
//add 报文标识
|
|
||||||
for (byte b : transationId) {
|
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
bytes.add(serviceCode);
|
|
||||||
bytes.add(commandCode);
|
|
||||||
bytes.add(executionCode);
|
|
||||||
bytes.add(retain);
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
bytes.add(serviceCode);
|
||||||
|
bytes.add(commandCode);
|
||||||
|
bytes.add(executionCode);
|
||||||
|
bytes.add(retain);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,14 @@
|
|||||||
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;
|
||||||
public interface IAgvEvent {
|
import org.opentcs.kc.common.byteutils.ByteUtil;
|
||||||
//read sended
|
|
||||||
public Package toBytes();
|
|
||||||
//write sended
|
|
||||||
public Package toBytes(Object newValue);
|
|
||||||
|
|
||||||
public String protocolName();
|
public interface IAgvEvent {
|
||||||
|
//read sended
|
||||||
|
public Package toBytes();
|
||||||
|
|
||||||
|
//write sended
|
||||||
|
public Package toBytes(Object newValue);
|
||||||
|
|
||||||
|
public String protocolName();
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,19 @@ 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个字节
|
||||||
public byte[] eventCode;
|
public byte[] eventCode;
|
||||||
//异常等级,2个字节
|
//异常等级,2个字节
|
||||||
public byte[] abnormalLevel;
|
public byte[] abnormalLevel;
|
||||||
//remain,8个字节
|
//remain,8个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
|
|
||||||
public AbnormalEventStatusInfo(byte[] src) {
|
public AbnormalEventStatusInfo(byte[] src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.eventCode = ByteUtils.copyBytes(src, 0, 2);
|
this.eventCode = ByteUtils.copyBytes(src, 0, 2);
|
||||||
this.abnormalLevel = ByteUtils.copyBytes(src, 2, 2);
|
this.abnormalLevel = ByteUtils.copyBytes(src, 2, 2);
|
||||||
this.remain = ByteUtils.copyBytes(src, 4, 8);
|
this.remain = ByteUtils.copyBytes(src, 4, 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,24 +2,19 @@ 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个字节
|
||||||
public byte[] actionId;
|
public byte[] actionId;
|
||||||
//动作状态,1个字节
|
//动作状态,1个字节
|
||||||
public byte actionStatus;
|
public byte actionStatus;
|
||||||
//预留,7个字节
|
//预留,7个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
|
|
||||||
public ActionInfo(byte[] src) {
|
public ActionInfo(byte[] src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.actionId = ByteUtils.copyBytes(src, 0, 4);
|
this.actionId = ByteUtils.copyBytes(src, 0, 4);
|
||||||
this.actionStatus = src[4];
|
this.actionStatus = src[4];
|
||||||
this.remain = ByteUtils.copyBytes(src,5,7);
|
this.remain = ByteUtils.copyBytes(src, 5, 7);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,34 +2,30 @@ 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;
|
||||||
//电量百分比
|
//电量百分比
|
||||||
public float batteryPercentage;
|
public float batteryPercentage;
|
||||||
//电压
|
//电压
|
||||||
public float voltage;
|
public float voltage;
|
||||||
//电流
|
//电流
|
||||||
public float electricCurrent;
|
public float electricCurrent;
|
||||||
//充电情况,1个字节
|
//充电情况,1个字节
|
||||||
public byte chargingState;
|
public byte chargingState;
|
||||||
//预留,7个字节
|
//预留,7个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
public BatteryStatusInfo(byte[] src) {
|
|
||||||
this.src = src;
|
public BatteryStatusInfo(byte[] src) {
|
||||||
this.batteryPercentage = ByteUtils.bytesToFloat(src, 0);
|
this.src = src;
|
||||||
this.voltage = ByteUtils.bytesToFloat(src, 4);
|
this.batteryPercentage = ByteUtils.bytesToFloat(src, 0);
|
||||||
this.electricCurrent = ByteUtils.bytesToFloat(src, 8);
|
this.voltage = ByteUtils.bytesToFloat(src, 4);
|
||||||
this.chargingState = src[12];
|
this.electricCurrent = ByteUtils.bytesToFloat(src, 8);
|
||||||
this.remain=new byte[7];
|
this.chargingState = src[12];
|
||||||
for (int i = 0; i < 7; i++) {
|
this.remain = new byte[7];
|
||||||
this.remain[i]=src[13+i];
|
for (int i = 0; i < 7; i++) {
|
||||||
}
|
this.remain[i] = src[13 + i];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,79 +2,74 @@ 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
|
||||||
public float globalX;
|
public float globalX;
|
||||||
//4个字节,车 全局y,单位 m
|
//4个字节,车 全局y,单位 m
|
||||||
public float globalY;
|
public float globalY;
|
||||||
//机器人绝对车体方向角,单位 rad
|
//机器人绝对车体方向角,单位 rad
|
||||||
public float absoluteDirecAngle;
|
public float absoluteDirecAngle;
|
||||||
//最后通过点 ID
|
//最后通过点 ID
|
||||||
public Integer lastPassPointId;
|
public Integer lastPassPointId;
|
||||||
//最后通过edge ID
|
//最后通过edge ID
|
||||||
public Integer lastPassEdgeId;
|
public Integer lastPassEdgeId;
|
||||||
//最后通过点在任务中的序列号
|
//最后通过点在任务中的序列号
|
||||||
public Integer serialNumber;
|
public Integer serialNumber;
|
||||||
//置信度,1个字节
|
//置信度,1个字节
|
||||||
public byte confidenceLevel;
|
public byte confidenceLevel;
|
||||||
//预留8个字节
|
//预留8个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
byte[] src = new byte[32];
|
byte[] src = new byte[32];
|
||||||
src[0] = (byte) 0x73;
|
src[0] = (byte) 0x73;
|
||||||
src[1] = (byte) 0xde;
|
src[1] = (byte) 0xde;
|
||||||
src[2] = (byte) 0xba;
|
src[2] = (byte) 0xba;
|
||||||
src[3] = (byte) 0xbd;
|
src[3] = (byte) 0xbd;
|
||||||
|
|
||||||
src[4] = (byte) 0x34;
|
src[4] = (byte) 0x34;
|
||||||
src[5] = (byte) 0xbf;
|
src[5] = (byte) 0xbf;
|
||||||
src[6] = (byte) 0xd0;
|
src[6] = (byte) 0xd0;
|
||||||
src[7] = (byte) 0x40;
|
src[7] = (byte) 0x40;
|
||||||
|
|
||||||
src[8] = (byte) 0x59;
|
src[8] = (byte) 0x59;
|
||||||
src[9] = (byte) 0x3c;
|
src[9] = (byte) 0x3c;
|
||||||
src[10] = (byte) 0x1d;
|
src[10] = (byte) 0x1d;
|
||||||
src[11] = (byte) 0x3d;
|
src[11] = (byte) 0x3d;
|
||||||
System.out.println("x: "+ByteUtils.bytesToFloat(src, 0));
|
System.out.println("x: " + ByteUtils.bytesToFloat(src, 0));
|
||||||
System.out.println("y: "+ByteUtils.bytesToFloat(src, 4));
|
System.out.println("y: " + ByteUtils.bytesToFloat(src, 4));
|
||||||
System.out.println("z: "+ByteUtils.bytesToFloat(src, 8));
|
System.out.println("z: " + ByteUtils.bytesToFloat(src, 8));
|
||||||
|
}
|
||||||
|
|
||||||
|
public LocationStatusInfo(byte[] src) {
|
||||||
|
this.src = src;
|
||||||
|
for (byte b : src) {
|
||||||
|
System.out.print(byteToHex(b) + " ");
|
||||||
}
|
}
|
||||||
|
//[115, -34, -70, -67, 52, -65, -48, 64, 89, 60, 29, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||||
public LocationStatusInfo(byte[] src) {
|
this.globalX = ByteUtils.bytesToFloat(src, 0);
|
||||||
this.src = src;
|
this.globalY = ByteUtils.bytesToFloat(src, 4);
|
||||||
for (byte b:src){
|
this.absoluteDirecAngle = ByteUtils.bytesToFloat(src, 8);
|
||||||
System.out.print(byteToHex(b)+" ");
|
this.lastPassPointId = ByteUtils.bytesToInt(src, 12);
|
||||||
}
|
this.lastPassEdgeId = ByteUtils.bytesToInt(src, 16);
|
||||||
//[115, -34, -70, -67, 52, -65, -48, 64, 89, 60, 29, 61, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
this.serialNumber = ByteUtils.bytesToInt(src, 20);
|
||||||
this.globalX = ByteUtils.bytesToFloat(src, 0);
|
this.confidenceLevel = src[24];
|
||||||
this.globalY = ByteUtils.bytesToFloat(src, 4);
|
this.remain = new byte[7];
|
||||||
this.absoluteDirecAngle = ByteUtils.bytesToFloat(src, 8);
|
for (int i = 0; i < 7; i++) {
|
||||||
this.lastPassPointId = ByteUtils.bytesToInt(src, 12);
|
this.remain[i] = src[25 + i];
|
||||||
this.lastPassEdgeId = ByteUtils.bytesToInt(src, 16);
|
|
||||||
this.serialNumber = ByteUtils.bytesToInt(src, 20);
|
|
||||||
this.confidenceLevel = src[24];
|
|
||||||
this.remain = new byte[7];
|
|
||||||
for (int i = 0; i < 7; i++) {
|
|
||||||
this.remain[i] = src[25 + i];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public static String byteToHex(byte b) {
|
public static String byteToHex(byte b) {
|
||||||
// 将byte转换为无符号整数
|
// 将byte转换为无符号整数
|
||||||
int unsignedByte = b & 0xFF;
|
int unsignedByte = b & 0xFF;
|
||||||
// 使用Integer.toHexString方法转换为十六进制字符串
|
// 使用Integer.toHexString方法转换为十六进制字符串
|
||||||
String hexString = Integer.toHexString(unsignedByte);
|
String hexString = Integer.toHexString(unsignedByte);
|
||||||
// 如果字符串长度为1,需要在前面补0
|
// 如果字符串长度为1,需要在前面补0
|
||||||
if (hexString.length() == 1) {
|
if (hexString.length() == 1) {
|
||||||
return "0" + hexString;
|
return "0" + hexString;
|
||||||
}
|
|
||||||
return hexString;
|
|
||||||
}
|
}
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,17 @@ 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;
|
||||||
//序列号,4个字节
|
//序列号,4个字节
|
||||||
public Integer serialNumber;
|
public Integer serialNumber;
|
||||||
//序列号
|
//序列号
|
||||||
public Integer pathId;
|
public Integer pathId;
|
||||||
public PathStateSequence(byte[] src) {
|
|
||||||
this.src = src;
|
public PathStateSequence(byte[] src) {
|
||||||
this.serialNumber = ByteUtils.bytesToInt(src, 0);
|
this.src = src;
|
||||||
this.pathId = ByteUtils.bytesToInt(src, 4);
|
this.serialNumber = ByteUtils.bytesToInt(src, 0);
|
||||||
}
|
this.pathId = ByteUtils.bytesToInt(src, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,21 +2,17 @@ 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;
|
||||||
//序列号,4个字节
|
//序列号,4个字节
|
||||||
public Integer serialNumber;
|
public Integer serialNumber;
|
||||||
//序列号
|
//序列号
|
||||||
public Integer pointId;
|
public Integer pointId;
|
||||||
public PointStateSequence(byte[] src) {
|
|
||||||
this.src = src;
|
public PointStateSequence(byte[] src) {
|
||||||
this.serialNumber = ByteUtils.bytesToInt(src, 0);
|
this.src = src;
|
||||||
this.pointId = ByteUtils.bytesToInt(src, 4);
|
this.serialNumber = ByteUtils.bytesToInt(src, 0);
|
||||||
}
|
this.pointId = ByteUtils.bytesToInt(src, 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,50 +1,65 @@
|
|||||||
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;
|
||||||
public byte action_size;
|
public byte action_size;
|
||||||
//预留2个字节
|
//预留2个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
public LocationStatusInfo locationStatusInfo;
|
public LocationStatusInfo locationStatusInfo;
|
||||||
public RunningStatusInfo runningStatusInfo;
|
public RunningStatusInfo runningStatusInfo;
|
||||||
public TaskStatusInfo taskStatusInfo;
|
public TaskStatusInfo taskStatusInfo;
|
||||||
public BatteryStatusInfo batteryStatusInfo;
|
public BatteryStatusInfo batteryStatusInfo;
|
||||||
public List<AbnormalEventStatusInfo> abnormalEventStatusInfoList;
|
public List<AbnormalEventStatusInfo> abnormalEventStatusInfoList;
|
||||||
public List<ActionInfo> actionInfoList;
|
public List<ActionInfo> actionInfoList;
|
||||||
|
|
||||||
public QueryRobotStatusRsp(byte[] src) {
|
|
||||||
this.src = src;
|
|
||||||
this.abnormal_size = src[0];
|
|
||||||
this.action_size = src[1];
|
|
||||||
this.remain = ByteUtils.copyBytes(src,2,2); //index 2
|
|
||||||
this.locationStatusInfo = new LocationStatusInfo(ByteUtils.copyBytes(src,4,32));
|
|
||||||
this.runningStatusInfo = new RunningStatusInfo(ByteUtils.copyBytes(src,36,20));
|
|
||||||
|
|
||||||
Integer pointSize = ByteUtils.toInt(src[60]);
|
|
||||||
Integer edgeSize = ByteUtils.toInt(src[61]);
|
|
||||||
Integer taskByteSize = 12+8*(pointSize+edgeSize);
|
|
||||||
this.taskStatusInfo = new TaskStatusInfo(ByteUtils.copyBytes(src,56,taskByteSize));
|
|
||||||
this.batteryStatusInfo = new BatteryStatusInfo(ByteUtils.copyBytes(src,56+taskByteSize,20));
|
|
||||||
|
|
||||||
if(this.abnormal_size>0){
|
|
||||||
for(int i=0;i<this.abnormal_size;i++){
|
|
||||||
this.abnormalEventStatusInfoList.add(new AbnormalEventStatusInfo(ByteUtils.copyBytes(src,56+taskByteSize+20+12*i,12)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(this.action_size>0){
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
public QueryRobotStatusRsp(byte[] src) {
|
||||||
|
if (src == null) {
|
||||||
|
throw new RuntimeException("method_QueryRobotStatusRsp_params_src_is_NUll");
|
||||||
}
|
}
|
||||||
|
this.src = src;
|
||||||
|
this.abnormal_size = src[0];
|
||||||
|
this.action_size = src[1];
|
||||||
|
this.remain = ByteUtils.copyBytes(src, 2, 2); //index 2
|
||||||
|
this.locationStatusInfo = new LocationStatusInfo(ByteUtils.copyBytes(src, 4, 32));
|
||||||
|
this.runningStatusInfo = new RunningStatusInfo(ByteUtils.copyBytes(src, 36, 20));
|
||||||
|
|
||||||
|
Integer pointSize = ByteUtils.toInt(src[60]);
|
||||||
|
Integer edgeSize = ByteUtils.toInt(src[61]);
|
||||||
|
Integer taskByteSize = 12 + 8 * (pointSize + edgeSize);
|
||||||
|
this.taskStatusInfo = new TaskStatusInfo(ByteUtils.copyBytes(src, 56, taskByteSize));
|
||||||
|
this.batteryStatusInfo = new BatteryStatusInfo(ByteUtils.copyBytes(src, 56 + taskByteSize, 20));
|
||||||
|
|
||||||
|
if (this.abnormal_size > 0) {
|
||||||
|
if (this.abnormalEventStatusInfoList == null) {
|
||||||
|
this.abnormalEventStatusInfoList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
for (int i = 0; i < this.abnormal_size; i++) {
|
||||||
|
this.abnormalEventStatusInfoList.add(
|
||||||
|
new AbnormalEventStatusInfo(
|
||||||
|
ByteUtils.copyBytes(src, 56 + taskByteSize + 20 + 12 * i, 12)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.action_size > 0) {
|
||||||
|
if (this.actionInfoList == null) {
|
||||||
|
this.actionInfoList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
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
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,39 +2,34 @@ 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
|
||||||
public float speedX;
|
public float speedX;
|
||||||
//4个字节,车 轴y 速度,单位 m/s
|
//4个字节,车 轴y 速度,单位 m/s
|
||||||
public float speedY;
|
public float speedY;
|
||||||
//车角速度,单位 rad/s
|
//车角速度,单位 rad/s
|
||||||
public float angularSpeed;
|
public float angularSpeed;
|
||||||
//工作模式
|
//工作模式
|
||||||
public byte workMode;
|
public byte workMode;
|
||||||
//agv 状态,1个字节
|
//agv 状态,1个字节
|
||||||
public byte agvStatus;
|
public byte agvStatus;
|
||||||
//机器人能力集设置状态,1个字节
|
//机器人能力集设置状态,1个字节
|
||||||
public byte abilitySetStatus;
|
public byte abilitySetStatus;
|
||||||
//预留,5个字节
|
//预留,5个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
|
|
||||||
public RunningStatusInfo(byte[] src) {
|
public RunningStatusInfo(byte[] src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.speedX = ByteUtils.bytesToFloat(src, 0);
|
this.speedX = ByteUtils.bytesToFloat(src, 0);
|
||||||
this.speedY = ByteUtils.bytesToFloat(src, 4);
|
this.speedY = ByteUtils.bytesToFloat(src, 4);
|
||||||
this.angularSpeed = ByteUtils.bytesToFloat(src, 8);
|
this.angularSpeed = ByteUtils.bytesToFloat(src, 8);
|
||||||
this.workMode = src[12];
|
this.workMode = src[12];
|
||||||
this.agvStatus = src[13];
|
this.agvStatus = src[13];
|
||||||
this.abilitySetStatus = src[14];
|
this.abilitySetStatus = src[14];
|
||||||
this.remain = new byte[5];
|
this.remain = new byte[5];
|
||||||
for (int i = 0; i < 5; i++) {
|
for (int i = 0; i < 5; i++) {
|
||||||
this.remain[i] = src[15 + i];
|
this.remain[i] = src[15 + i];
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,48 +2,44 @@ 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
|
||||||
public Integer orderId;
|
public Integer orderId;
|
||||||
//任务 KEY
|
//任务 KEY
|
||||||
public Integer taskKey;
|
public Integer taskKey;
|
||||||
//点状态序列数量
|
//点状态序列数量
|
||||||
public Integer pointStatusNum;
|
public Integer pointStatusNum;
|
||||||
//段状态序列数量
|
//段状态序列数量
|
||||||
public Integer edgeStatusNum;
|
public Integer edgeStatusNum;
|
||||||
//预留,2个字节
|
//预留,2个字节
|
||||||
public byte[] remain;
|
public byte[] remain;
|
||||||
//点状态序列
|
//点状态序列
|
||||||
public PointStateSequence[] pointStatusInfo;
|
public PointStateSequence[] pointStatusInfo;
|
||||||
//段状态序列
|
//段状态序列
|
||||||
public PathStateSequence[] pathStatusInfo;
|
public PathStateSequence[] pathStatusInfo;
|
||||||
|
|
||||||
public TaskStatusInfo(byte[] src) {
|
public TaskStatusInfo(byte[] src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.orderId = ByteUtils.bytesToInt(src, 0);
|
this.orderId = ByteUtils.bytesToInt(src, 0);
|
||||||
this.taskKey = ByteUtils.bytesToInt(src, 4);
|
this.taskKey = ByteUtils.bytesToInt(src, 4);
|
||||||
|
|
||||||
this.pointStatusNum = ByteUtils.toInt(src[8]);
|
this.pointStatusNum = ByteUtils.toInt(src[8]);
|
||||||
this.edgeStatusNum = ByteUtils.toInt(src[9]);
|
this.edgeStatusNum = ByteUtils.toInt(src[9]);
|
||||||
this.remain = ByteUtils.copyBytes(src, 10, 2);
|
this.remain = ByteUtils.copyBytes(src, 10, 2);
|
||||||
if (pointStatusNum > 0) {
|
if (pointStatusNum > 0) {
|
||||||
this.pointStatusInfo = new PointStateSequence[pointStatusNum];
|
this.pointStatusInfo = new PointStateSequence[pointStatusNum];
|
||||||
for (int i = 0; i < pointStatusNum; i++) {
|
for (int i = 0; i < pointStatusNum; i++) {
|
||||||
this.pointStatusInfo[i] = new PointStateSequence(ByteUtils.copyBytes(src, 12 + 8 * i, 8));
|
this.pointStatusInfo[i] = new PointStateSequence(ByteUtils.copyBytes(src, 12 + 8 * i, 8));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (edgeStatusNum > 0) {
|
|
||||||
this.pathStatusInfo = new PathStateSequence[edgeStatusNum];
|
|
||||||
for (int i = 0; i < edgeStatusNum; i++) {
|
|
||||||
this.pathStatusInfo[i] = new PathStateSequence(ByteUtils.copyBytes(src, 12 + pointStatusNum*8 + 8 * pointStatusNum + 8 * i, 8));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (edgeStatusNum > 0) {
|
||||||
|
this.pathStatusInfo = new PathStateSequence[edgeStatusNum];
|
||||||
|
for (int i = 0; i < edgeStatusNum; i++) {
|
||||||
|
this.pathStatusInfo[i] = new PathStateSequence(
|
||||||
|
ByteUtils.copyBytes(src, 12 + pointStatusNum * 8 + 8 * pointStatusNum + 8 * i, 8)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,22 +2,17 @@ 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;
|
||||||
//是否载货
|
//是否载货
|
||||||
public byte isCargo;
|
public byte isCargo;
|
||||||
//预留,3个字节
|
//预留,3个字节
|
||||||
public byte[] reserved;
|
public byte[] reserved;
|
||||||
|
|
||||||
public QueryCargoStatusRsp(byte[] src) {
|
public QueryCargoStatusRsp(byte[] src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.isCargo = src[0];
|
this.isCargo = src[0];
|
||||||
this.reserved = ByteUtils.copyBytes(src, 1, 3);
|
this.reserved = ByteUtils.copyBytes(src, 1, 3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,25 +2,20 @@ 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;
|
||||||
//上报间隔时间 ,单位ms ,2个字节
|
//上报间隔时间 ,单位ms ,2个字节
|
||||||
public byte[] intervalTime;
|
public byte[] intervalTime;
|
||||||
//上报持续时间,单位ms ,4个字节
|
//上报持续时间,单位ms ,4个字节
|
||||||
public byte[] durationTime;
|
public byte[] durationTime;
|
||||||
//预留,8个字节
|
//预留,8个字节
|
||||||
public byte[] reserved;
|
public byte[] reserved;
|
||||||
|
|
||||||
public SubscribeInfo(byte[] commandCode, Short intervalTime, Integer durationTime) {
|
public SubscribeInfo(byte[] commandCode, Short intervalTime, Integer durationTime) {
|
||||||
this.commandCode = commandCode;
|
this.commandCode = commandCode;
|
||||||
this.intervalTime = ByteUtils.shortToBytes(intervalTime);
|
this.intervalTime = ByteUtils.shortToBytes(intervalTime);
|
||||||
this.durationTime = ByteUtils.intToBytes(durationTime,4);
|
this.durationTime = ByteUtils.intToBytes(durationTime, 4);
|
||||||
this.reserved = new byte[8];
|
this.reserved = new byte[8];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,67 +4,63 @@ 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) {
|
|
||||||
this.subscribeInfoList = subscribeInfoList;
|
public SubscribeParam(List<SubscribeInfo> subscribeInfoList) {
|
||||||
this.uuid = generate64ByteUUID();
|
this.subscribeInfoList = subscribeInfoList;
|
||||||
|
this.uuid = generate64ByteUUID();
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成 64 字节长度的 UUID,返回 byte[] 类型
|
||||||
|
public static byte[] generate64ByteUUID() {
|
||||||
|
// 创建 SecureRandom 实例用于生成安全的随机数
|
||||||
|
SecureRandom secureRandom = new SecureRandom();
|
||||||
|
// 定义一个长度为 64 的字节数组
|
||||||
|
byte[] uuidBytes = new byte[64];
|
||||||
|
// 使用 SecureRandom 生成随机字节填充字节数组
|
||||||
|
secureRandom.nextBytes(uuidBytes);
|
||||||
|
return uuidBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toBytes() {
|
||||||
|
src = new byte[192];
|
||||||
|
List<Byte> bytes = new ArrayList<>();
|
||||||
|
for (SubscribeInfo subscribeInfo : subscribeInfoList) {
|
||||||
|
bytes.add(subscribeInfo.commandCode[0]);
|
||||||
|
bytes.add(subscribeInfo.commandCode[1]);
|
||||||
|
bytes.add(subscribeInfo.intervalTime[0]);
|
||||||
|
bytes.add(subscribeInfo.intervalTime[1]);
|
||||||
|
bytes.add(subscribeInfo.durationTime[0]);
|
||||||
|
bytes.add(subscribeInfo.durationTime[1]);
|
||||||
|
bytes.add(subscribeInfo.durationTime[2]);
|
||||||
|
bytes.add(subscribeInfo.durationTime[3]);
|
||||||
|
bytes.add(subscribeInfo.reserved[0]);
|
||||||
|
bytes.add(subscribeInfo.reserved[1]);
|
||||||
|
bytes.add(subscribeInfo.reserved[2]);
|
||||||
|
bytes.add(subscribeInfo.reserved[3]);
|
||||||
|
bytes.add(subscribeInfo.reserved[4]);
|
||||||
|
bytes.add(subscribeInfo.reserved[5]);
|
||||||
|
bytes.add(subscribeInfo.reserved[6]);
|
||||||
|
bytes.add(subscribeInfo.reserved[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getUuid() {
|
for (int i = 0; i < bytes.size(); i++) {
|
||||||
return uuid;
|
src[i] = bytes.get(i);
|
||||||
|
}
|
||||||
|
for (int i = 0; i < uuid.length; i++) {
|
||||||
|
src[i + 128] = uuid[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
// 生成 64 字节长度的 UUID,返回 byte[] 类型
|
return src;
|
||||||
public static byte[] generate64ByteUUID() {
|
}
|
||||||
// 创建 SecureRandom 实例用于生成安全的随机数
|
|
||||||
SecureRandom secureRandom = new SecureRandom();
|
|
||||||
// 定义一个长度为 64 的字节数组
|
|
||||||
byte[] uuidBytes = new byte[64];
|
|
||||||
// 使用 SecureRandom 生成随机字节填充字节数组
|
|
||||||
secureRandom.nextBytes(uuidBytes);
|
|
||||||
return uuidBytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] toBytes(){
|
|
||||||
src = new byte[192];
|
|
||||||
List<Byte> bytes = new ArrayList<>();
|
|
||||||
for (SubscribeInfo subscribeInfo : subscribeInfoList) {
|
|
||||||
bytes.add(subscribeInfo.commandCode[0]);
|
|
||||||
bytes.add(subscribeInfo.commandCode[1]);
|
|
||||||
bytes.add(subscribeInfo.intervalTime[0]);
|
|
||||||
bytes.add(subscribeInfo.intervalTime[1]);
|
|
||||||
bytes.add(subscribeInfo.durationTime[0]);
|
|
||||||
bytes.add(subscribeInfo.durationTime[1]);
|
|
||||||
bytes.add(subscribeInfo.durationTime[2]);
|
|
||||||
bytes.add(subscribeInfo.durationTime[3]);
|
|
||||||
bytes.add(subscribeInfo.reserved[0]);
|
|
||||||
bytes.add(subscribeInfo.reserved[1]);
|
|
||||||
bytes.add(subscribeInfo.reserved[2]);
|
|
||||||
bytes.add(subscribeInfo.reserved[3]);
|
|
||||||
bytes.add(subscribeInfo.reserved[4]);
|
|
||||||
bytes.add(subscribeInfo.reserved[5]);
|
|
||||||
bytes.add(subscribeInfo.reserved[6]);
|
|
||||||
bytes.add(subscribeInfo.reserved[7]);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < bytes.size(); i++) {
|
|
||||||
src[i] = bytes.get(i);
|
|
||||||
}
|
|
||||||
for (int i = 0; i < uuid.length; i++) {
|
|
||||||
src[i+128] = uuid[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
return src;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,32 +2,29 @@ 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;
|
||||||
//uuid 64个字节
|
//uuid 64个字节
|
||||||
private byte[] uuid;
|
private byte[] uuid;
|
||||||
//errCode 1个字节
|
//errCode 1个字节
|
||||||
private byte errCode;
|
private byte errCode;
|
||||||
//reserved 3个字节
|
//reserved 3个字节
|
||||||
private byte[] reserved;
|
private byte[] reserved;
|
||||||
public SubscribeRsp(byte[] src) {
|
|
||||||
this.src = src;
|
|
||||||
this.uuid = ByteUtils.copyOfRange(src,0,64);
|
|
||||||
this.errCode = src[64];
|
|
||||||
this.reserved = ByteUtils.copyOfRange(src,65,3);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk(){
|
public SubscribeRsp(byte[] src) {
|
||||||
if(this.errCode==0){
|
this.src = src;
|
||||||
return true;
|
this.uuid = ByteUtils.copyOfRange(src, 0, 64);
|
||||||
}else {
|
this.errCode = src[64];
|
||||||
return false;
|
this.reserved = ByteUtils.copyOfRange(src, 65, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOk() {
|
||||||
|
if (this.errCode == 0) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,50 +4,47 @@ 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;
|
||||||
//执行动作并行方式,1个字节
|
//执行动作并行方式,1个字节
|
||||||
private byte actionParallel;
|
private byte actionParallel;
|
||||||
//预留,1个字节
|
//预留,1个字节
|
||||||
private byte actionRetain;
|
private byte actionRetain;
|
||||||
//动作 id,4个字节,actionId 自己定义不要重复就行,可以从0开始累加
|
//动作 id,4个字节,actionId 自己定义不要重复就行,可以从0开始累加
|
||||||
private byte[] actionId;
|
private byte[] actionId;
|
||||||
//参数长度,1个字节
|
//参数长度,1个字节
|
||||||
private byte paramSize;
|
private byte paramSize;
|
||||||
//预留,3个字节
|
//预留,3个字节
|
||||||
private byte[] paramRetain2;
|
private byte[] paramRetain2;
|
||||||
//参数内容,这里的长度 是 paramSize 长度,todo 注意 这里的paramContent 需要字节去构建一下 ,目前 这里还没有
|
//参数内容,这里的长度 是 paramSize 长度,todo 注意 这里的paramContent 需要字节去构建一下 ,目前 这里还没有
|
||||||
private byte[] paramContent;
|
private byte[] paramContent;
|
||||||
|
|
||||||
|
|
||||||
public Action(byte actionType, byte actionParallel, Integer actionId, Integer paramSize, byte[] paramContent) {
|
public Action(
|
||||||
this.actionType = new byte[]{actionType, (byte)0x00};
|
byte actionType, byte actionParallel, Integer actionId, Integer paramSize, byte[] paramContent
|
||||||
this.actionParallel = actionParallel;
|
) {
|
||||||
this.actionRetain = (byte)0x00;
|
this.actionType = new byte[]{actionType, (byte) 0x00};
|
||||||
this.actionId = ByteUtils.intToBytes(actionId,1);
|
this.actionParallel = actionParallel;
|
||||||
this.paramSize = ByteUtils.usintTo1Byte(paramSize);
|
this.actionRetain = (byte) 0x00;
|
||||||
this.paramRetain2 = new byte[]{(byte)0x00, (byte)0x00,(byte)0x00};
|
this.actionId = ByteUtils.intToBytes(actionId, 1);
|
||||||
this.paramContent = paramContent;
|
this.paramSize = ByteUtils.usintTo1Byte(paramSize);
|
||||||
}
|
this.paramRetain2 = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00};
|
||||||
|
this.paramContent = paramContent;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] toBytes() {
|
public byte[] toBytes() {
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
byteBuf.writeBytes(actionType);
|
byteBuf.writeBytes(actionType);
|
||||||
byteBuf.writeByte(actionParallel);
|
byteBuf.writeByte(actionParallel);
|
||||||
byteBuf.writeByte(actionRetain);
|
byteBuf.writeByte(actionRetain);
|
||||||
byteBuf.writeBytes(actionId);
|
byteBuf.writeBytes(actionId);
|
||||||
byteBuf.writeByte(paramSize);
|
byteBuf.writeByte(paramSize);
|
||||||
byteBuf.writeBytes(paramRetain2);
|
byteBuf.writeBytes(paramRetain2);
|
||||||
byteBuf.writeBytes(paramContent);
|
byteBuf.writeBytes(paramContent);
|
||||||
int i = byteBuf.writerIndex();
|
int i = byteBuf.writerIndex();
|
||||||
byte[] bytes = new byte[i];
|
byte[] bytes = new byte[i];
|
||||||
byteBuf.readBytes(bytes);
|
byteBuf.readBytes(bytes);
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,74 +4,71 @@ 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);
|
||||||
System.out.println();
|
System.out.println();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte stop0x01 = 0x01;
|
public static byte stop0x01 = 0x01;
|
||||||
public static byte recover0x02 = 0x02;
|
public static byte recover0x02 = 0x02;
|
||||||
public static byte cancelTask0x03 = 0x03;
|
public static byte cancelTask0x03 = 0x03;
|
||||||
public static byte forkliftElevation0x12 = 0x12;
|
public static byte forkliftElevation0x12 = 0x12;
|
||||||
public static byte trayElevation0x16 = 0x16;
|
public static byte trayElevation0x16 = 0x16;
|
||||||
|
|
||||||
|
|
||||||
public static Integer stop0x01_paramsize = 8;
|
public static Integer stop0x01_paramsize = 8;
|
||||||
public static Integer recover0x02_paramsize = 8;
|
public static Integer recover0x02_paramsize = 8;
|
||||||
public static Integer cancelTask0x03_paramsize = 8;
|
public static Integer cancelTask0x03_paramsize = 8;
|
||||||
public static Integer forkliftElevation0x12_paramsize = 8;
|
public static Integer forkliftElevation0x12_paramsize = 8;
|
||||||
public static Integer trayElevation0x16_paramsize = 4;
|
public static Integer trayElevation0x16_paramsize = 4;
|
||||||
|
|
||||||
|
|
||||||
public static byte[] stop0x01(Integer orderId,byte isStopImmediately){
|
public static byte[] stop0x01(Integer orderId, byte isStopImmediately) {
|
||||||
ByteBuf byteBuf = Unpooled.buffer(8);
|
ByteBuf byteBuf = Unpooled.buffer(8);
|
||||||
byteBuf.writeBytes(ByteUtils.intToBytes(orderId,1));
|
byteBuf.writeBytes(ByteUtils.intToBytes(orderId, 1));
|
||||||
byteBuf.writeByte(isStopImmediately);
|
byteBuf.writeByte(isStopImmediately);
|
||||||
return byteBuf.array();
|
return byteBuf.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static byte[] recover0x02(Integer orderId,Integer taskKey){
|
public static byte[] recover0x02(Integer orderId, Integer taskKey) {
|
||||||
ByteBuf byteBuf = Unpooled.buffer(8);
|
ByteBuf byteBuf = Unpooled.buffer(8);
|
||||||
byteBuf.writeBytes(ByteUtils.intToBytes(orderId,1));
|
byteBuf.writeBytes(ByteUtils.intToBytes(orderId, 1));
|
||||||
byteBuf.writeBytes(ByteUtils.intToBytes(taskKey,1));
|
byteBuf.writeBytes(ByteUtils.intToBytes(taskKey, 1));
|
||||||
return byteBuf.array();
|
return byteBuf.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
//取消任务
|
//取消任务
|
||||||
public static byte[] cancelTask0x03(Integer orderId,byte isStopImmediately){
|
public static byte[] cancelTask0x03(Integer orderId, byte isStopImmediately) {
|
||||||
ByteBuf byteBuf = Unpooled.buffer(8);
|
ByteBuf byteBuf = Unpooled.buffer(8);
|
||||||
byteBuf.writeBytes(ByteUtils.intToBytes(orderId,1));
|
byteBuf.writeBytes(ByteUtils.intToBytes(orderId, 1));
|
||||||
byteBuf.writeByte(isStopImmediately);
|
byteBuf.writeByte(isStopImmediately);
|
||||||
return byteBuf.array();
|
return byteBuf.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* desc:叉齿升降
|
* desc:叉齿升降
|
||||||
* 支持的命令:0xAE 0xB2
|
* 支持的命令:0xAE 0xB2
|
||||||
*
|
*
|
||||||
* */
|
*/
|
||||||
|
|
||||||
public static byte[] forkliftElevation0x12(float lifitingHeight,byte hightMean,byte moveType, byte taskOperationType){
|
public static byte[] forkliftElevation0x12(
|
||||||
ByteBuf byteBuf = Unpooled.buffer(8);
|
float lifitingHeight, byte hightMean, byte moveType, byte taskOperationType
|
||||||
byteBuf.writeBytes(ByteUtils.floatToBytes(lifitingHeight));
|
) {
|
||||||
byteBuf.writeByte(hightMean);
|
ByteBuf byteBuf = Unpooled.buffer(8);
|
||||||
byteBuf.writeByte(moveType);
|
byteBuf.writeBytes(ByteUtils.floatToBytes(lifitingHeight));
|
||||||
byteBuf.writeByte(taskOperationType);
|
byteBuf.writeByte(hightMean);
|
||||||
return byteBuf.array();
|
byteBuf.writeByte(moveType);
|
||||||
}
|
byteBuf.writeByte(taskOperationType);
|
||||||
|
return byteBuf.array();
|
||||||
|
}
|
||||||
|
|
||||||
//托盘升降
|
//托盘升降
|
||||||
public static byte[] trayElevation0x16(byte palletMovementMode){
|
public static byte[] trayElevation0x16(byte palletMovementMode) {
|
||||||
ByteBuf byteBuf = Unpooled.buffer(4);
|
ByteBuf byteBuf = Unpooled.buffer(4);
|
||||||
byteBuf.writeByte(palletMovementMode);
|
byteBuf.writeByte(palletMovementMode);
|
||||||
return byteBuf.array();
|
return byteBuf.array();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,54 +4,51 @@ 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;
|
||||||
//任务 KEY,4个字节,Integer,从1开始依次累加
|
//任务 KEY,4个字节,Integer,从1开始依次累加
|
||||||
private byte[] taskKey;
|
private byte[] taskKey;
|
||||||
//路径点信息个数(单条任务最大支持 8 个路径点),1个字节 ,byte
|
//路径点信息个数(单条任务最大支持 8 个路径点),1个字节 ,byte
|
||||||
private byte pointNum;
|
private byte pointNum;
|
||||||
//路径信息个数(单条任务最大支持 8 个路径点),1个字节,byte
|
//路径信息个数(单条任务最大支持 8 个路径点),1个字节,byte
|
||||||
private byte pathNum;
|
private byte pathNum;
|
||||||
//保留,2个字节
|
//保留,2个字节
|
||||||
private byte[] retain;
|
private byte[] retain;
|
||||||
//任务中路径点信息结构体,长度 pointNum
|
//任务中路径点信息结构体,长度 pointNum
|
||||||
private Point[] points;
|
private Point[] points;
|
||||||
//任务中路径信息结构体,长度 pathNum
|
//任务中路径信息结构体,长度 pathNum
|
||||||
private Path[] paths;
|
private Path[] paths;
|
||||||
|
|
||||||
public NavigationParam(Integer orderId, Integer taskKey, byte pointNum, byte pathNum, Point[] points, Path[] paths) {
|
public NavigationParam(
|
||||||
this.orderId = ByteUtils.intToBytes(orderId,1);
|
Integer orderId, Integer taskKey, byte pointNum, byte pathNum, Point[] points, Path[] paths
|
||||||
this.taskKey = ByteUtils.intToBytes(taskKey,1);
|
) {
|
||||||
this.pointNum = pointNum;
|
this.orderId = ByteUtils.intToBytes(orderId, 1);
|
||||||
this.pathNum = pathNum;
|
this.taskKey = ByteUtils.intToBytes(taskKey, 1);
|
||||||
this.retain = new byte[]{(byte)0x00, (byte)0x00};
|
this.pointNum = pointNum;
|
||||||
this.points = points;
|
this.pathNum = pathNum;
|
||||||
this.paths = paths;
|
this.retain = new byte[]{(byte) 0x00, (byte) 0x00};
|
||||||
|
this.points = points;
|
||||||
|
this.paths = paths;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toBytes() {
|
||||||
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
|
byteBuf.writeBytes(orderId);
|
||||||
|
byteBuf.writeBytes(taskKey);
|
||||||
|
byteBuf.writeByte(pointNum);
|
||||||
|
byteBuf.writeByte(pathNum);
|
||||||
|
byteBuf.writeBytes(retain);
|
||||||
|
|
||||||
|
for (Point point : points) {
|
||||||
|
byteBuf.writeBytes(point.toBytes());
|
||||||
}
|
}
|
||||||
|
for (Path path : paths) {
|
||||||
public byte[] toBytes() {
|
byteBuf.writeBytes(path.toBytes());
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
|
||||||
byteBuf.writeBytes(orderId);
|
|
||||||
byteBuf.writeBytes(taskKey);
|
|
||||||
byteBuf.writeByte(pointNum);
|
|
||||||
byteBuf.writeByte(pathNum);
|
|
||||||
byteBuf.writeBytes(retain);
|
|
||||||
|
|
||||||
for (Point point : points) {
|
|
||||||
byteBuf.writeBytes(point.toBytes());
|
|
||||||
}
|
|
||||||
for (Path path : paths) {
|
|
||||||
byteBuf.writeBytes(path.toBytes());
|
|
||||||
}
|
|
||||||
int i = byteBuf.writerIndex();
|
|
||||||
byte[] bytes = new byte[i];
|
|
||||||
byteBuf.readBytes(bytes);
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
int i = byteBuf.writerIndex();
|
||||||
|
byte[] bytes = new byte[i];
|
||||||
|
byteBuf.readBytes(bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,71 +4,71 @@ 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 开始奇数递增(如 1、3、5......)(point 2 4 6,这样path 和point就可以结合起来了),以区分同一个段 ID 在任务中是否多次出现
|
//序列号,4个字节,Integer,用于定位段在整个任务中的位置,从 1 开始奇数递增(如 1、3、5......)(point 2 4 6,这样path 和point就可以结合起来了),以区分同一个段 ID 在任务中是否多次出现
|
||||||
private byte[] serialNum;
|
private byte[] serialNum;
|
||||||
//段 ID,4个字节,Integer
|
//段 ID,4个字节,Integer
|
||||||
private byte[] pathId;
|
private byte[] pathId;
|
||||||
//指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效
|
//指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效
|
||||||
private byte[] angle;
|
private byte[] angle;
|
||||||
//是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定
|
//是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定
|
||||||
private byte isSpecifyAngle;
|
private byte isSpecifyAngle;
|
||||||
|
|
||||||
//行驶姿态,1个字节,byte
|
//行驶姿态,1个字节,byte
|
||||||
private byte drivePose;
|
private byte drivePose;
|
||||||
//任务中边上动作信息个数,1个字节,byte
|
//任务中边上动作信息个数,1个字节,byte
|
||||||
private byte pathActionSize;
|
private byte pathActionSize;
|
||||||
//保留,1个字节
|
//保留,1个字节
|
||||||
private byte pathRetain;
|
private byte pathRetain;
|
||||||
//指定的目标最大速度,4个字节,float
|
//指定的目标最大速度,4个字节,float
|
||||||
private byte[] maxSpeed;
|
private byte[] maxSpeed;
|
||||||
//指定的目标最大角速度,4个字节,float
|
//指定的目标最大角速度,4个字节,float
|
||||||
private byte[] maxAngularSpeed;
|
private byte[] maxAngularSpeed;
|
||||||
//预留,4个字节
|
//预留,4个字节
|
||||||
private byte[] pathRetain2;
|
private byte[] pathRetain2;
|
||||||
|
|
||||||
//任务中点上动作结构体,这里数组的长度是 pathActionSize 长度
|
//任务中点上动作结构体,这里数组的长度是 pathActionSize 长度
|
||||||
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(
|
||||||
this.serialNum = ByteUtils.intToBytes(serialNum,1);
|
Integer serialNum, Integer pathId, float angle, byte isSpecifyAngle, byte drivePose,
|
||||||
this.pathId = ByteUtils.intToBytes(pathId,1);
|
byte pathActionSize, float maxSpeed, float maxAngularSpeed, Action[] actions
|
||||||
this.angle = ByteUtils.floatToBytes(angle);
|
) {
|
||||||
this.isSpecifyAngle = isSpecifyAngle;
|
this.serialNum = ByteUtils.intToBytes(serialNum, 1);
|
||||||
this.drivePose = drivePose;
|
this.pathId = ByteUtils.intToBytes(pathId, 1);
|
||||||
this.pathActionSize = pathActionSize;
|
this.angle = ByteUtils.floatToBytes(angle);
|
||||||
this.pathRetain = (byte)0x00;
|
this.isSpecifyAngle = isSpecifyAngle;
|
||||||
this.maxSpeed = ByteUtils.floatToBytes(maxSpeed);
|
this.drivePose = drivePose;
|
||||||
this.maxAngularSpeed = ByteUtils.floatToBytes(maxAngularSpeed);
|
this.pathActionSize = pathActionSize;
|
||||||
this.pathRetain2 = new byte[]{(byte)0x00, (byte)0x00,(byte)0x00,(byte)0x00};
|
this.pathRetain = (byte) 0x00;
|
||||||
this.actions = actions;
|
this.maxSpeed = ByteUtils.floatToBytes(maxSpeed);
|
||||||
}
|
this.maxAngularSpeed = ByteUtils.floatToBytes(maxAngularSpeed);
|
||||||
|
this.pathRetain2 = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00};
|
||||||
public byte[] toBytes() {
|
this.actions = actions;
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
}
|
||||||
byteBuf.writeBytes(serialNum);
|
|
||||||
byteBuf.writeBytes(pathId);
|
public byte[] toBytes() {
|
||||||
byteBuf.writeBytes(angle);
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
byteBuf.writeByte(isSpecifyAngle);
|
byteBuf.writeBytes(serialNum);
|
||||||
byteBuf.writeByte(drivePose);
|
byteBuf.writeBytes(pathId);
|
||||||
byteBuf.writeByte(pathActionSize);
|
byteBuf.writeBytes(angle);
|
||||||
byteBuf.writeByte(pathRetain);
|
byteBuf.writeByte(isSpecifyAngle);
|
||||||
byteBuf.writeBytes(maxSpeed);
|
byteBuf.writeByte(drivePose);
|
||||||
byteBuf.writeBytes(maxAngularSpeed);
|
byteBuf.writeByte(pathActionSize);
|
||||||
byteBuf.writeBytes(pathRetain2);
|
byteBuf.writeByte(pathRetain);
|
||||||
for (Action action : actions) {
|
byteBuf.writeBytes(maxSpeed);
|
||||||
byteBuf.writeBytes(action.toBytes());
|
byteBuf.writeBytes(maxAngularSpeed);
|
||||||
}
|
byteBuf.writeBytes(pathRetain2);
|
||||||
int i = byteBuf.writerIndex();
|
if (actions != null) {
|
||||||
byte[] bytes = new byte[i];
|
for (Action action : actions) {
|
||||||
byteBuf.readBytes(bytes);
|
byteBuf.writeBytes(action.toBytes());
|
||||||
return bytes;
|
}
|
||||||
}
|
}
|
||||||
|
int i = byteBuf.writerIndex();
|
||||||
|
byte[] bytes = new byte[i];
|
||||||
|
byteBuf.readBytes(bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,51 +4,52 @@ 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 开始偶数递增(如 0、2、4、6......),以区分同一个点 ID 在任务中是否多次出现
|
//序列号,4个字节,Integer,用于定位点在整个任务中的位置,从 0 开始偶数递增(如 0、2、4、6......),以区分同一个点 ID 在任务中是否多次出现
|
||||||
private byte[] serialNum;
|
private byte[] serialNum;
|
||||||
//路径点 ID,4个字节,Integer
|
//路径点 ID,4个字节,Integer
|
||||||
private byte[] pointId;
|
private byte[] pointId;
|
||||||
//指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效
|
//指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效
|
||||||
private byte[] angle;
|
private byte[] angle;
|
||||||
//是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定
|
//是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定
|
||||||
private byte isSpecifyAngle;
|
private byte isSpecifyAngle;
|
||||||
//任务中点上动作信息个数,1个字节,byte
|
//任务中点上动作信息个数,1个字节,byte
|
||||||
private byte pointActionSize;
|
private byte pointActionSize;
|
||||||
//保留,6个字节
|
//保留,6个字节
|
||||||
private byte[] pointRetain;
|
private byte[] pointRetain;
|
||||||
//任务中点上动作结构体,这里数组的长度是 pointActionSize 长度
|
//任务中点上动作结构体,这里数组的长度是 pointActionSize 长度
|
||||||
private Action[] actions;
|
private Action[] actions;
|
||||||
|
|
||||||
public Point(Integer serialNum, Integer pointId, float angle, byte isSpecifyAngle, byte pointActionSize, Action[] actions) {
|
public Point(
|
||||||
this.serialNum = ByteUtils.intToBytes(serialNum,1);
|
Integer serialNum, Integer pointId, float angle, byte isSpecifyAngle, byte pointActionSize,
|
||||||
this.pointId = ByteUtils.intToBytes(pointId,1);
|
Action[] actions
|
||||||
this.angle = ByteUtils.floatToBytes(angle);
|
) {
|
||||||
this.isSpecifyAngle = isSpecifyAngle;
|
this.serialNum = ByteUtils.intToBytes(serialNum, 1);
|
||||||
this.pointActionSize = pointActionSize;
|
this.pointId = ByteUtils.intToBytes(pointId, 1);
|
||||||
this.pointRetain = new byte[]{(byte)0x00, (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00};
|
this.angle = ByteUtils.floatToBytes(angle);
|
||||||
this.actions = actions;
|
this.isSpecifyAngle = isSpecifyAngle;
|
||||||
}
|
this.pointActionSize = pointActionSize;
|
||||||
|
this.pointRetain = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00,
|
||||||
|
(byte) 0x00};
|
||||||
|
this.actions = actions;
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] toBytes() {
|
public byte[] toBytes() {
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
byteBuf.writeBytes(serialNum);
|
byteBuf.writeBytes(serialNum);
|
||||||
byteBuf.writeBytes(pointId);
|
byteBuf.writeBytes(pointId);
|
||||||
byteBuf.writeBytes(angle);
|
byteBuf.writeBytes(angle);
|
||||||
byteBuf.writeByte(isSpecifyAngle);
|
byteBuf.writeByte(isSpecifyAngle);
|
||||||
byteBuf.writeByte(pointActionSize);
|
byteBuf.writeByte(pointActionSize);
|
||||||
byteBuf.writeBytes(pointRetain);
|
byteBuf.writeBytes(pointRetain);
|
||||||
for (Action action : actions) {
|
if (actions != null) {
|
||||||
byteBuf.writeBytes(action.toBytes());
|
for (Action action : actions) {
|
||||||
}
|
byteBuf.writeBytes(action.toBytes());
|
||||||
int i = byteBuf.writerIndex();
|
}
|
||||||
byte[] bytes = new byte[i];
|
|
||||||
byteBuf.readBytes(bytes);
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
int i = byteBuf.writerIndex();
|
||||||
|
byte[] bytes = new byte[i];
|
||||||
|
byteBuf.readBytes(bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,48 +4,44 @@ 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) {
|
|
||||||
// 这里的valueId 也是 header里面的 transationId
|
|
||||||
valueNum = ByteUtil.intTo1Byte(rvalues.size());
|
|
||||||
retain = new byte[]{0x00,0x00,0x00};
|
|
||||||
|
|
||||||
this.valueId = new byte[]{valueId[0],valueId[1],0x00,0x00};
|
public ReadParam(byte[] valueId, List<ReadStrValue> rvalues) {
|
||||||
List<Byte> bytes = new ArrayList<>();
|
// 这里的valueId 也是 header里面的 transationId
|
||||||
for (ReadStrValue b : rvalues) {
|
valueNum = ByteUtil.intTo1Byte(rvalues.size());
|
||||||
bytes.addAll(b.toBytes());
|
retain = new byte[]{0x00, 0x00, 0x00};
|
||||||
}
|
|
||||||
readStrValues = new byte[bytes.size()];
|
|
||||||
for (int i = 0; i < bytes.size(); i++) {
|
|
||||||
readStrValues[i] = bytes.get(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] toBytes() {
|
this.valueId = new byte[]{valueId[0], valueId[1], 0x00, 0x00};
|
||||||
List<Byte> bytes = new ArrayList<>();
|
List<Byte> bytes = new ArrayList<>();
|
||||||
bytes.add(valueNum);
|
for (ReadStrValue b : rvalues) {
|
||||||
for (byte b : retain) {
|
bytes.addAll(b.toBytes());
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
for (byte b : valueId) {
|
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
for (byte b : readStrValues) {
|
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
byte[] b = new byte[bytes.size()];
|
|
||||||
for (int i = 0; i < bytes.size(); i++) {
|
|
||||||
b[i] = bytes.get(i);
|
|
||||||
}
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
readStrValues = new byte[bytes.size()];
|
||||||
|
for (int i = 0; i < bytes.size(); i++) {
|
||||||
|
readStrValues[i] = bytes.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toBytes() {
|
||||||
|
List<Byte> bytes = new ArrayList<>();
|
||||||
|
bytes.add(valueNum);
|
||||||
|
for (byte b : retain) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
for (byte b : valueId) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
for (byte b : readStrValues) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
byte[] b = new byte[bytes.size()];
|
||||||
|
for (int i = 0; i < bytes.size(); i++) {
|
||||||
|
b[i] = bytes.get(i);
|
||||||
|
}
|
||||||
|
return b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,36 +2,32 @@ 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;
|
||||||
//ValueID ,4个字节
|
//ValueID ,4个字节
|
||||||
public byte[] valueId;
|
public byte[] valueId;
|
||||||
//应答数据总长度,2个字节
|
//应答数据总长度,2个字节
|
||||||
public short valueByteLength;
|
public short valueByteLength;
|
||||||
//预留,2个字节
|
//预留,2个字节
|
||||||
public byte[] reserved;
|
public byte[] reserved;
|
||||||
//变量值,长度是 valueByteLength
|
//变量值,长度是 valueByteLength
|
||||||
public byte[] dataValue;
|
public byte[] dataValue;
|
||||||
|
|
||||||
public ReadRsp(byte[] src) {
|
public ReadRsp(byte[] src) {
|
||||||
this.src = src;
|
this.src = src;
|
||||||
this.valueId = ByteUtils.copyBytes(src, 0, 4);
|
this.valueId = ByteUtils.copyBytes(src, 0, 4);
|
||||||
this.valueByteLength = ByteUtils.bytesToShort(ByteUtils.copyBytes(src, 4, 2),1);
|
this.valueByteLength = ByteUtils.bytesToShort(ByteUtils.copyBytes(src, 4, 2), 1);
|
||||||
this.reserved = ByteUtils.copyBytes(src, 6, 2);
|
this.reserved = ByteUtils.copyBytes(src, 6, 2);
|
||||||
this.dataValue = ByteUtils.copyBytes(src, 8, valueByteLength-8);
|
this.dataValue = ByteUtils.copyBytes(src, 8, valueByteLength - 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isOk(){
|
public boolean isOk() {
|
||||||
if(valueByteLength<=0){
|
if (valueByteLength <= 0) {
|
||||||
return false;
|
return false;
|
||||||
}else {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,46 +4,43 @@ 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) {
|
|
||||||
this.varName = ByteUtil.stringTo16Byte(varName);
|
|
||||||
this.memberVarNum = ByteUtil.intToBytes(memberVarNum);
|
|
||||||
List<Byte> bytes = new ArrayList<>();
|
|
||||||
for (ReadValueMember member : memberList) {
|
|
||||||
bytes.addAll(member.toBytes());
|
|
||||||
}
|
|
||||||
this.memberList = new byte[bytes.size()];
|
|
||||||
for (int i = 0; i < bytes.size(); i++) {
|
|
||||||
this.memberList[i] = bytes.get(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public ReadStrValue(String varName) {
|
|
||||||
this.varName = ByteUtil.stringTo16Byte(varName);
|
|
||||||
this.memberVarNum = ByteUtil.intToBytes(0);
|
|
||||||
this.memberList = new byte[0];
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<Byte> toBytes() {
|
public ReadStrValue(String varName, Integer memberVarNum, List<ReadValueMember> memberList) {
|
||||||
List<Byte> bytes = new ArrayList<>();
|
this.varName = ByteUtil.stringTo16Byte(varName);
|
||||||
for (byte b : varName) {
|
this.memberVarNum = ByteUtil.intToBytes(memberVarNum);
|
||||||
bytes.add(b);
|
List<Byte> bytes = new ArrayList<>();
|
||||||
}
|
for (ReadValueMember member : memberList) {
|
||||||
for (byte b : memberVarNum) {
|
bytes.addAll(member.toBytes());
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
for (byte b : memberList) {
|
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
this.memberList = new byte[bytes.size()];
|
||||||
|
for (int i = 0; i < bytes.size(); i++) {
|
||||||
|
this.memberList[i] = bytes.get(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ReadStrValue(String varName) {
|
||||||
|
this.varName = ByteUtil.stringTo16Byte(varName);
|
||||||
|
this.memberVarNum = ByteUtil.intToBytes(0);
|
||||||
|
this.memberList = new byte[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Byte> toBytes() {
|
||||||
|
List<Byte> bytes = new ArrayList<>();
|
||||||
|
for (byte b : varName) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
for (byte b : memberVarNum) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
for (byte b : memberList) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,31 +4,26 @@ 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;
|
||||||
//变量成员长度,就是你要读取的content长度,可以是1个变量的长度,也可以是n个变量的长度(就是数据类型 的字节长度)
|
//变量成员长度,就是你要读取的content长度,可以是1个变量的长度,也可以是n个变量的长度(就是数据类型 的字节长度)
|
||||||
private byte[] memberVarLength;
|
private byte[] memberVarLength;
|
||||||
|
|
||||||
public ReadValueMember(Short offsetValue, Short memberVarLength) {
|
public ReadValueMember(Short offsetValue, Short memberVarLength) {
|
||||||
this.offsetValue = ByteUtil.shortToBytes(offsetValue);
|
this.offsetValue = ByteUtil.shortToBytes(offsetValue);
|
||||||
this.memberVarLength = ByteUtil.shortToBytes(memberVarLength);
|
this.memberVarLength = ByteUtil.shortToBytes(memberVarLength);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Byte> toBytes() {
|
public List<Byte> toBytes() {
|
||||||
List<Byte> bytes = new ArrayList<>();
|
List<Byte> bytes = new ArrayList<>();
|
||||||
for (byte b : offsetValue) {
|
for (byte b : offsetValue) {
|
||||||
bytes.add(b);
|
bytes.add(b);
|
||||||
}
|
|
||||||
for (byte b : memberVarLength) {
|
|
||||||
bytes.add(b);
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
}
|
||||||
|
for (byte b : memberVarLength) {
|
||||||
|
bytes.add(b);
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,35 +5,31 @@ 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;
|
||||||
//保留 3个字节
|
//保留 3个字节
|
||||||
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) {
|
|
||||||
this.valueNum = ByteUtils.usintTo1Byte(valueNum);
|
|
||||||
this.retain = new byte[]{(byte)0x00,(byte)0x00,(byte)0x00};
|
|
||||||
this.values = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] toBytes() {
|
public WriteParam(Integer valueNum, List<WriteStrValue> values) {
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
this.valueNum = ByteUtils.usintTo1Byte(valueNum);
|
||||||
byteBuf.writeByte(valueNum);
|
this.retain = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00};
|
||||||
byteBuf.writeBytes(retain);
|
this.values = values;
|
||||||
for (WriteStrValue value : values) {
|
}
|
||||||
byteBuf.writeBytes(value.toBytes());
|
|
||||||
}
|
public byte[] toBytes() {
|
||||||
int i = byteBuf.writerIndex();
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
byte[] bytes = new byte[i];
|
byteBuf.writeByte(valueNum);
|
||||||
byteBuf.readBytes(bytes);
|
byteBuf.writeBytes(retain);
|
||||||
return bytes;
|
for (WriteStrValue value : values) {
|
||||||
|
byteBuf.writeBytes(value.toBytes());
|
||||||
}
|
}
|
||||||
|
int i = byteBuf.writerIndex();
|
||||||
|
byte[] bytes = new byte[i];
|
||||||
|
byteBuf.readBytes(bytes);
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,37 +5,32 @@ 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;
|
||||||
//变量成员数量 4个字节
|
//变量成员数量 4个字节
|
||||||
private Integer valueNum;
|
private Integer valueNum;
|
||||||
private List<WriteValueMember> members;
|
private List<WriteValueMember> members;
|
||||||
|
|
||||||
public WriteStrValue(String valueName, Integer valueNum, List<WriteValueMember> members) {
|
public WriteStrValue(String valueName, Integer valueNum, List<WriteValueMember> members) {
|
||||||
this.valueName = valueName;
|
this.valueName = valueName;
|
||||||
this.valueNum = valueNum;
|
this.valueNum = valueNum;
|
||||||
this.members = members;
|
this.members = members;
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] toBytes() {
|
||||||
|
ByteBuf byteBuf = Unpooled.buffer();
|
||||||
|
byteBuf.writeBytes(ByteUtils.stringToBytes(valueName, 16));
|
||||||
|
byteBuf.writeBytes(ByteUtils.intToBytes(valueNum, 1));
|
||||||
|
for (WriteValueMember member : members) {
|
||||||
|
byteBuf.writeBytes(member.toBytes());
|
||||||
}
|
}
|
||||||
|
int i = byteBuf.writerIndex();
|
||||||
|
byte[] bytes = new byte[i];
|
||||||
|
byteBuf.readBytes(bytes);
|
||||||
|
|
||||||
public byte[] toBytes() {
|
return bytes;
|
||||||
ByteBuf byteBuf = Unpooled.buffer();
|
}
|
||||||
byteBuf.writeBytes(ByteUtils.stringToBytes(valueName, 16));
|
|
||||||
byteBuf.writeBytes(ByteUtils.intToBytes(valueNum,1));
|
|
||||||
for (WriteValueMember member : members) {
|
|
||||||
byteBuf.writeBytes(member.toBytes());
|
|
||||||
}
|
|
||||||
int i = byteBuf.writerIndex();
|
|
||||||
byte[] bytes = new byte[i];
|
|
||||||
byteBuf.readBytes(bytes);
|
|
||||||
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,29 +4,25 @@ 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;
|
||||||
//变量成员长度 2个字节
|
//变量成员长度 2个字节
|
||||||
private byte[] valueLength;
|
private byte[] valueLength;
|
||||||
//变量成员值 4个字节
|
//变量成员值 4个字节
|
||||||
private byte[] newValue;
|
private byte[] newValue;
|
||||||
public WriteValueMember(Short valueOffset, Short valueLength, byte[] newValue) {
|
|
||||||
this.valueOffset = ByteUtils.shortToBytes(valueOffset);
|
|
||||||
this.valueLength = ByteUtils.shortToBytes(valueLength);
|
|
||||||
this.newValue = newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] toBytes() {
|
public WriteValueMember(Short valueOffset, Short valueLength, byte[] newValue) {
|
||||||
ByteBuf byteBuf = Unpooled.buffer(8);
|
this.valueOffset = ByteUtils.shortToBytes(valueOffset);
|
||||||
byteBuf.writeBytes(valueOffset);
|
this.valueLength = ByteUtils.shortToBytes(valueLength);
|
||||||
byteBuf.writeBytes(valueLength);
|
this.newValue = newValue;
|
||||||
byteBuf.writeBytes(newValue);
|
}
|
||||||
return byteBuf.array();
|
|
||||||
}
|
public byte[] toBytes() {
|
||||||
|
ByteBuf byteBuf = Unpooled.buffer(8);
|
||||||
|
byteBuf.writeBytes(valueOffset);
|
||||||
|
byteBuf.writeBytes(valueLength);
|
||||||
|
byteBuf.writeBytes(newValue);
|
||||||
|
return byteBuf.array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,29 +4,25 @@ 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;
|
||||||
//机器人 y 坐标 ,8 个字节
|
//机器人 y 坐标 ,8 个字节
|
||||||
private byte[] robotY;
|
private byte[] robotY;
|
||||||
//机器人朝向角度 ,8 个字节
|
//机器人朝向角度 ,8 个字节
|
||||||
private byte[] robotAngle;
|
private byte[] robotAngle;
|
||||||
|
|
||||||
public RobotSetPosition(double robotX, double robotY, double robotAngle) {
|
public RobotSetPosition(double robotX, double robotY, double robotAngle) {
|
||||||
this.robotX = ByteUtil.doubleToBytes(robotX);
|
this.robotX = ByteUtil.doubleToBytes(robotX);
|
||||||
this.robotY = ByteUtil.doubleToBytes(robotY);
|
this.robotY = ByteUtil.doubleToBytes(robotY);
|
||||||
this.robotAngle = ByteUtil.doubleToBytes(robotAngle);
|
this.robotAngle = ByteUtil.doubleToBytes(robotAngle);
|
||||||
}
|
}
|
||||||
public byte[] toBytes() {
|
|
||||||
ByteBuf byteBuf = Unpooled.buffer(24);
|
public byte[] toBytes() {
|
||||||
byteBuf.writeBytes(robotX);
|
ByteBuf byteBuf = Unpooled.buffer(24);
|
||||||
byteBuf.writeBytes(robotY);
|
byteBuf.writeBytes(robotX);
|
||||||
byteBuf.writeBytes(robotAngle);
|
byteBuf.writeBytes(robotY);
|
||||||
return byteBuf.array();
|
byteBuf.writeBytes(robotAngle);
|
||||||
}
|
return byteBuf.array();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,128 +3,123 @@ 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;
|
||||||
//位置的 X 坐标 , 8个字节 ,double
|
//位置的 X 坐标 , 8个字节 ,double
|
||||||
private double currentX;
|
private double currentX;
|
||||||
//位置的 Y 坐标,8个字节 ,double
|
//位置的 Y 坐标,8个字节 ,double
|
||||||
private double currentY;
|
private double currentY;
|
||||||
//位置的 角度 ,8个字节 ,double
|
//位置的 角度 ,8个字节 ,double
|
||||||
private double currentAngle;
|
private double currentAngle;
|
||||||
//电池电量,,8个字节 ,double
|
//电池电量,,8个字节 ,double
|
||||||
private double battery;
|
private double battery;
|
||||||
//是否被阻挡,1个字节,byte
|
//是否被阻挡,1个字节,byte
|
||||||
private byte isBlocked;
|
private byte isBlocked;
|
||||||
//是否在充电,1个字节,byte
|
//是否在充电,1个字节,byte
|
||||||
private byte isCharging;
|
private byte isCharging;
|
||||||
//运行模式,1个字节,byte
|
//运行模式,1个字节,byte
|
||||||
private byte runMode;
|
private byte runMode;
|
||||||
//地图载入状态,1个字节,byte
|
//地图载入状态,1个字节,byte
|
||||||
private byte mapLoadState;
|
private byte mapLoadState;
|
||||||
//当前的目标点 id,U32 ,4个字节
|
//当前的目标点 id,U32 ,4个字节
|
||||||
private Integer currentTargetId;
|
private Integer currentTargetId;
|
||||||
|
|
||||||
//前进速度,8个字节,double
|
//前进速度,8个字节,double
|
||||||
private double forwardSpeed;
|
private double forwardSpeed;
|
||||||
//转弯速度,8个字节,double
|
//转弯速度,8个字节,double
|
||||||
private double turnSpeed;
|
private double turnSpeed;
|
||||||
//电池电压(充电为正,放电为负),8个字节,double
|
//电池电压(充电为正,放电为负),8个字节,double
|
||||||
private double batteryVoltage;
|
private double batteryVoltage;
|
||||||
//电流(充电为正,放电为负),double
|
//电流(充电为正,放电为负),double
|
||||||
private double electricCurrent;
|
private double electricCurrent;
|
||||||
//当前任务状态,1个字节,byte
|
//当前任务状态,1个字节,byte
|
||||||
private byte taskState;
|
private byte taskState;
|
||||||
//保留,1个字节
|
//保留,1个字节
|
||||||
private byte retain1;
|
private byte retain1;
|
||||||
//地图版本号,2个字节
|
//地图版本号,2个字节
|
||||||
private short mapVersion;
|
private short mapVersion;
|
||||||
//保留,4个字节
|
//保留,4个字节
|
||||||
private byte[] retain2;
|
private byte[] retain2;
|
||||||
//累计行驶里程(单位 m),8个字节
|
//累计行驶里程(单位 m),8个字节
|
||||||
private double cumulativeMileage;
|
private double cumulativeMileage;
|
||||||
//本次运行时间(单位 ms),8个字节
|
//本次运行时间(单位 ms),8个字节
|
||||||
private double currentRunTime;
|
private double currentRunTime;
|
||||||
//累计运行时间(单位 ms),8个字节
|
//累计运行时间(单位 ms),8个字节
|
||||||
private double cumulativeRunTime;
|
private double cumulativeRunTime;
|
||||||
//机器人定位状态,1个字节
|
//机器人定位状态,1个字节
|
||||||
public byte robotLocalizationState;
|
public byte robotLocalizationState;
|
||||||
//保留,3个字节
|
//保留,3个字节
|
||||||
private byte[] retain3;
|
private byte[] retain3;
|
||||||
//地图数量,U32,4个字节
|
//地图数量,U32,4个字节
|
||||||
private Integer mapNum;
|
private Integer mapNum;
|
||||||
//当前地图名称,64字节
|
//当前地图名称,64字节
|
||||||
private String currentMapName;
|
private String currentMapName;
|
||||||
//置信度,4个字节
|
//置信度,4个字节
|
||||||
private float confidence;
|
private float confidence;
|
||||||
//保留,4个字节
|
//保留,4个字节
|
||||||
private byte[] retain4;
|
private byte[] retain4;
|
||||||
|
|
||||||
public QueryRobotRunStatusRsp(byte[] src) {
|
public QueryRobotRunStatusRsp(byte[] src) {
|
||||||
this.temp = ByteUtils.bytesToDouble(src, 0);
|
this.temp = ByteUtils.bytesToDouble(src, 0);
|
||||||
this.currentX = ByteUtils.bytesToDouble(src, 8);
|
this.currentX = ByteUtils.bytesToDouble(src, 8);
|
||||||
this.currentY = ByteUtils.bytesToDouble(src, 16);
|
this.currentY = ByteUtils.bytesToDouble(src, 16);
|
||||||
this.currentAngle = ByteUtils.bytesToDouble(src, 24);
|
this.currentAngle = ByteUtils.bytesToDouble(src, 24);
|
||||||
this.battery = ByteUtils.bytesToDouble(src, 32);
|
this.battery = ByteUtils.bytesToDouble(src, 32);
|
||||||
this.isBlocked = src[40];
|
this.isBlocked = src[40];
|
||||||
this.isCharging = src[41];
|
this.isCharging = src[41];
|
||||||
this.runMode = src[42];
|
this.runMode = src[42];
|
||||||
this.mapLoadState = src[43];
|
this.mapLoadState = src[43];
|
||||||
this.currentTargetId = ByteUtils.bytesToInt(src, 44);
|
this.currentTargetId = ByteUtils.bytesToInt(src, 44);
|
||||||
this.forwardSpeed = ByteUtils.bytesToDouble(src, 48);
|
this.forwardSpeed = ByteUtils.bytesToDouble(src, 48);
|
||||||
this.turnSpeed = ByteUtils.bytesToDouble(src, 56);
|
this.turnSpeed = ByteUtils.bytesToDouble(src, 56);
|
||||||
this.batteryVoltage = ByteUtils.bytesToDouble(src, 64);
|
this.batteryVoltage = ByteUtils.bytesToDouble(src, 64);
|
||||||
this.electricCurrent = ByteUtils.bytesToDouble(src, 72);
|
this.electricCurrent = ByteUtils.bytesToDouble(src, 72);
|
||||||
this.taskState = src[80];
|
this.taskState = src[80];
|
||||||
this.retain1 = src[81];
|
this.retain1 = src[81];
|
||||||
this.mapVersion = ByteUtils.bytesToShortLitt(src, 82);
|
this.mapVersion = ByteUtils.bytesToShortLitt(src, 82);
|
||||||
this.retain2 = ByteUtils.copyBytes(src, 84, 4);
|
this.retain2 = ByteUtils.copyBytes(src, 84, 4);
|
||||||
this.cumulativeMileage = ByteUtils.bytesToDouble(src, 88);
|
this.cumulativeMileage = ByteUtils.bytesToDouble(src, 88);
|
||||||
this.currentRunTime = ByteUtils.bytesToDouble(src, 96);
|
this.currentRunTime = ByteUtils.bytesToDouble(src, 96);
|
||||||
this.cumulativeRunTime = ByteUtils.bytesToDouble(src, 104);
|
this.cumulativeRunTime = ByteUtils.bytesToDouble(src, 104);
|
||||||
this.robotLocalizationState = src[112];
|
this.robotLocalizationState = src[112];
|
||||||
this.retain3 = ByteUtils.copyBytes(src, 113, 3);
|
this.retain3 = ByteUtils.copyBytes(src, 113, 3);
|
||||||
this.mapNum = ByteUtils.bytesToInt(src, 116);
|
this.mapNum = ByteUtils.bytesToInt(src, 116);
|
||||||
this.currentMapName = ByteUtils.bytesToString(src, 120, 64);
|
this.currentMapName = ByteUtils.bytesToString(src, 120, 64);
|
||||||
this.confidence = ByteUtils.bytesToFloat(src, 184);
|
this.confidence = ByteUtils.bytesToFloat(src, 184);
|
||||||
this.retain4 = ByteUtils.copyBytes(src, 188, 4);
|
this.retain4 = ByteUtils.copyBytes(src, 188, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "QueryRobotRunStatusRsp{" +
|
return "QueryRobotRunStatusRsp{" +
|
||||||
"temp=" + temp +
|
"temp=" + temp +
|
||||||
", currentX=" + currentX +
|
", currentX=" + currentX +
|
||||||
", currentY=" + currentY +
|
", currentY=" + currentY +
|
||||||
", currentAngle=" + currentAngle +
|
", currentAngle=" + currentAngle +
|
||||||
", battery=" + battery +
|
", battery=" + battery +
|
||||||
", isBlocked=" + isBlocked +
|
", isBlocked=" + isBlocked +
|
||||||
", isCharging=" + isCharging +
|
", isCharging=" + isCharging +
|
||||||
", runMode=" + runMode +
|
", runMode=" + runMode +
|
||||||
", mapLoadState=" + mapLoadState +
|
", mapLoadState=" + mapLoadState +
|
||||||
", currentTargetId=" + currentTargetId +
|
", currentTargetId=" + currentTargetId +
|
||||||
", forwardSpeed=" + forwardSpeed +
|
", forwardSpeed=" + forwardSpeed +
|
||||||
", turnSpeed=" + turnSpeed +
|
", turnSpeed=" + turnSpeed +
|
||||||
", batteryVoltage=" + batteryVoltage +
|
", batteryVoltage=" + batteryVoltage +
|
||||||
", electricCurrent=" + electricCurrent +
|
", electricCurrent=" + electricCurrent +
|
||||||
", taskState=" + taskState +
|
", taskState=" + taskState +
|
||||||
", retain1=" + retain1 +
|
", retain1=" + retain1 +
|
||||||
", mapVersion=" + mapVersion +
|
", mapVersion=" + mapVersion +
|
||||||
", retain2=" + Arrays.toString(retain2) +
|
", retain2=" + Arrays.toString(retain2) +
|
||||||
", cumulativeMileage=" + cumulativeMileage +
|
", cumulativeMileage=" + cumulativeMileage +
|
||||||
", cuttentRunTime=" + currentRunTime +
|
", cuttentRunTime=" + currentRunTime +
|
||||||
", cumulativeRunTime=" + cumulativeRunTime +
|
", cumulativeRunTime=" + cumulativeRunTime +
|
||||||
", robotLocalizationState=" + robotLocalizationState +
|
", robotLocalizationState=" + robotLocalizationState +
|
||||||
", retain3=" + Arrays.toString(retain3) +
|
", retain3=" + Arrays.toString(retain3) +
|
||||||
", mapNum=" + mapNum +
|
", mapNum=" + mapNum +
|
||||||
", currentMapName='" + currentMapName + '\'' +
|
", currentMapName='" + currentMapName + '\'' +
|
||||||
", confidence=" + confidence +
|
", confidence=" + confidence +
|
||||||
", retain4=" + Arrays.toString(retain4) +
|
", retain4=" + Arrays.toString(retain4) +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,86 +4,90 @@ 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;
|
||||||
private byte[] value;
|
private byte[] value;
|
||||||
private String content;
|
private String content;
|
||||||
// header size = 授权码16 + 报文头12(包括报文数据长度2个字节+保留2个字节) = 28
|
// header size = 授权码16 + 报文头12(包括报文数据长度2个字节+保留2个字节) = 28
|
||||||
private AgvEventHeader header;
|
private AgvEventHeader header;
|
||||||
private byte[] dataBytes;
|
private byte[] dataBytes;
|
||||||
|
|
||||||
|
|
||||||
private String getContent(byte i) {
|
private String getContent(byte i) {
|
||||||
if(i==0x00){
|
if (i == 0x00) {
|
||||||
return "成功执行";
|
return "成功执行";
|
||||||
}else if(i==0x01){
|
}
|
||||||
return "执行失败,原因未知";
|
else if (i == 0x01) {
|
||||||
}else if(i==0x02){
|
return "执行失败,原因未知";
|
||||||
return "服务码错误";
|
}
|
||||||
}else if(i==0x03){
|
else if (i == 0x02) {
|
||||||
return "命令码错误";
|
return "服务码错误";
|
||||||
}else if(i==0x04){
|
}
|
||||||
return "报文头部错误";
|
else if (i == 0x03) {
|
||||||
}else if(i==0x80){
|
return "命令码错误";
|
||||||
return "无法执行命令,因为当前车辆导航状态与命令冲突";
|
}
|
||||||
}else if(i==0xFF){
|
else if (i == 0x04) {
|
||||||
return "协议授权码错误";
|
return "报文头部错误";
|
||||||
}else {
|
}
|
||||||
return "未知错误";
|
else if (i == 0x80) {
|
||||||
}
|
return "无法执行命令,因为当前车辆导航状态与命令冲突";
|
||||||
|
}
|
||||||
|
else if (i == 0xFF) {
|
||||||
|
return "协议授权码错误";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "未知错误";
|
||||||
}
|
}
|
||||||
|
|
||||||
public RcvEventPackage(byte executionCode, byte[] value) {
|
}
|
||||||
if(executionCode == 0x00){
|
|
||||||
this.isOk = true;
|
|
||||||
this.header = new AgvEventHeader(ByteUtils.copyBytes(value,0,28));
|
|
||||||
this.dataBytes = ByteUtils.copyBytes(value,28,value.length-28);
|
|
||||||
}else {
|
|
||||||
this.isOk = false;
|
|
||||||
}
|
|
||||||
this.value = value;
|
|
||||||
this.content = getContent(executionCode);
|
|
||||||
}
|
|
||||||
public RcvEventPackage() {
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isOk() {
|
public RcvEventPackage(byte executionCode, byte[] value) {
|
||||||
return isOk;
|
if (executionCode == 0x00) {
|
||||||
|
this.isOk = true;
|
||||||
|
this.header = new AgvEventHeader(ByteUtils.copyBytes(value, 0, 28));
|
||||||
|
this.dataBytes = ByteUtils.copyBytes(value, 28, value.length - 28);
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
this.isOk = false;
|
||||||
|
}
|
||||||
|
this.value = value;
|
||||||
|
this.content = getContent(executionCode);
|
||||||
|
}
|
||||||
|
|
||||||
public void setValue(byte[] value) {
|
public RcvEventPackage() {
|
||||||
this.value = value;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getValue() {
|
public boolean isOk() {
|
||||||
return value;
|
return isOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getContent() {
|
public void setValue(byte[] value) {
|
||||||
return content;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AgvEventHeader getHeader() {
|
public byte[] getValue() {
|
||||||
return header;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getDataBytes() {
|
public String getContent() {
|
||||||
return dataBytes;
|
return content;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public AgvEventHeader getHeader() {
|
||||||
public String toString() {
|
return header;
|
||||||
return "RcvPackage{" +
|
}
|
||||||
"isOk=" + isOk +
|
|
||||||
", value=" + value +
|
public byte[] getDataBytes() {
|
||||||
", content='" + content + '\'' +
|
return dataBytes;
|
||||||
'}';
|
}
|
||||||
}
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "RcvPackage{" +
|
||||||
|
"isOk=" + isOk +
|
||||||
|
", value=" + value +
|
||||||
|
", content='" + content + '\'' +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,250 +28,265 @@ 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;
|
||||||
//默认 0 port
|
//默认 0 port
|
||||||
private Integer port;
|
private Integer port;
|
||||||
private Integer bindPort;
|
private Integer bindPort;
|
||||||
private Bootstrap bootstrap;
|
private Bootstrap bootstrap;
|
||||||
private NioEventLoopGroup group;
|
private NioEventLoopGroup group;
|
||||||
|
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
// ==== 连接节点配置信息 ===== 开始
|
||||||
|
|
||||||
|
// ==== 连接节点配置信息 ===== 结束
|
||||||
|
|
||||||
|
UDPClient() {
|
||||||
|
}
|
||||||
|
|
||||||
|
//coreSize 是线程池的数量
|
||||||
|
UDPClient(String name, String host, Integer port, Integer bindPort) {
|
||||||
|
this.name = name;
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
this.conn = null;
|
||||||
|
this.bindPort = bindPort;
|
||||||
|
initClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getHost() {
|
||||||
|
return this.host;
|
||||||
|
}
|
||||||
|
|
||||||
// ==== 连接节点配置信息 ===== 开始
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
// ==== 连接节点配置信息 ===== 结束
|
public void setIsOnline(boolean isOnline) {
|
||||||
|
this.isOnline = isOnline;
|
||||||
|
}
|
||||||
|
|
||||||
UDPClient() {
|
/**
|
||||||
|
* desc : 判断此链接 健康状况
|
||||||
|
* return
|
||||||
|
* true : 此tcp连接 正常
|
||||||
|
* false : 此tcp连接 异常
|
||||||
|
*/
|
||||||
|
public boolean isOnline() {
|
||||||
|
return isOnline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void close() {
|
||||||
|
//手动关闭连接,会出发InActivite 事件
|
||||||
|
group.shutdownGracefully();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ByteBuf byteArrayToByteBuf(byte[] byteArray) {
|
||||||
|
// 使用Unpooled类创建ByteBuf
|
||||||
|
ByteBuf byteBuf = Unpooled.buffer(byteArray.length);
|
||||||
|
// 将byte[]写入ByteBuf
|
||||||
|
byteBuf.writeBytes(byteArray);
|
||||||
|
return byteBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (--)线程安全的(--)
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 如果返回null,就代表出现了异常,并且尝试了 retryMax 次数,并且尝试重置连接
|
||||||
|
*/
|
||||||
|
public RcvEventPackage send(AgvEvent event) {
|
||||||
|
try {
|
||||||
|
//sendread 报文
|
||||||
|
//应该是ReadRequestFrame 继承 Packet 类,然后直接 Tio.bSend(this.conn, ReadRequestFrame)
|
||||||
|
|
||||||
|
Package mbPackage = event.toBytes();
|
||||||
|
AsyncFuture<Package> add = SendedList.add(mbPackage.getTransationId(), null);
|
||||||
|
|
||||||
|
this.conn.writeAndFlush(
|
||||||
|
new DatagramPacket(
|
||||||
|
byteArrayToByteBuf(mbPackage.getBody()),
|
||||||
|
new InetSocketAddress(this.host, this.port)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.sync();
|
||||||
|
|
||||||
|
Package aPackage = add.get(5000L, mbPackage.getTransationId());
|
||||||
|
byte[] body = aPackage.getBody();
|
||||||
|
|
||||||
|
String errMsg = " [ AGVclient - send success ] [ " + name + " host: " + this.host
|
||||||
|
+ " ]" + event.toString();
|
||||||
|
logger.info(errMsg);
|
||||||
|
//注意:这里的body 是整个 response结构,包括 : 授权码 + header + body
|
||||||
|
return new RcvEventPackage(body[22], body);
|
||||||
}
|
}
|
||||||
|
catch (Throwable e) {
|
||||||
|
//e.printStackTrace();
|
||||||
|
String errMsg = " [ AGVclient - Read ] [ " + name + " host: " + this.host
|
||||||
|
+ " ] ( occur err ) errTime: " + " ; send errMsg : " + e.getMessage()
|
||||||
|
+ " ; event :" + event.toString();
|
||||||
|
logger.info(errMsg);
|
||||||
|
throw new RuntimeException(errMsg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//coreSize 是线程池的数量
|
public void subscribeKC(RcvEventPackage rcv, byte[] body) {
|
||||||
UDPClient(String name, String host, Integer port, Integer bindPort) {
|
if (rcv.isOk()) {
|
||||||
this.name = name;
|
KernelServicePortal servicePortal = new KernelServicePortalBuilder(
|
||||||
this.host = host;
|
SERVICE_USER, SERVICE_PWD
|
||||||
this.port = port;
|
).build();
|
||||||
this.conn = null;
|
servicePortal.login(SERVICE_HOST, SERVICE_PORT);
|
||||||
this.bindPort = bindPort;
|
VehicleService vehicleService = servicePortal.getVehicleService();
|
||||||
initClient();
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void subscribe0xB0(RcvEventPackage rcv, byte[] body) {
|
||||||
|
|
||||||
|
if (rcv.isOk()) {
|
||||||
|
this.achieveSub0xB0(body);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.out.println();
|
||||||
|
System.out.println("subscribe0xB0 received transationId : " + "isok:" + rcv.isOk());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String getHost(){
|
public void subscribe0xAF(RcvEventPackage rcv, byte[] body) {
|
||||||
return this.host;
|
|
||||||
|
if (rcv.isOk()) {
|
||||||
|
this.achieveSub0xAF(body);
|
||||||
}
|
}
|
||||||
public String getName(){
|
else {
|
||||||
return this.name;
|
System.out.println();
|
||||||
}
|
System.out.println("subscribe0xAF received transationId : " + "isok:" + rcv.isOk());
|
||||||
public void setIsOnline(boolean isOnline){
|
|
||||||
this.isOnline = isOnline;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* desc : 判断此链接 健康状况
|
|
||||||
* return
|
|
||||||
* true : 此tcp连接 正常
|
|
||||||
* false : 此tcp连接 异常
|
|
||||||
* */
|
|
||||||
public boolean isOnline(){
|
|
||||||
return isOnline;
|
|
||||||
}
|
|
||||||
public void close(){
|
|
||||||
//手动关闭连接,会出发InActivite 事件
|
|
||||||
group.shutdownGracefully();
|
|
||||||
}
|
|
||||||
public static ByteBuf byteArrayToByteBuf(byte[] byteArray) {
|
|
||||||
// 使用Unpooled类创建ByteBuf
|
|
||||||
ByteBuf byteBuf = Unpooled.buffer(byteArray.length);
|
|
||||||
// 将byte[]写入ByteBuf
|
|
||||||
byteBuf.writeBytes(byteArray);
|
|
||||||
return byteBuf;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* (--)线程安全的(--)
|
|
||||||
|
|
||||||
*
|
|
||||||
* 如果返回null,就代表出现了异常,并且尝试了 retryMax 次数,并且尝试重置连接
|
|
||||||
* */
|
|
||||||
public RcvEventPackage send(AgvEvent event) {
|
|
||||||
try {
|
|
||||||
//sendread 报文
|
|
||||||
//应该是ReadRequestFrame 继承 Packet 类,然后直接 Tio.bSend(this.conn, ReadRequestFrame)
|
|
||||||
|
|
||||||
Package mbPackage = event.toBytes();
|
|
||||||
AsyncFuture<Package> add = SendedList.add(mbPackage.getTransationId(),null);
|
|
||||||
|
|
||||||
this.conn.writeAndFlush(
|
|
||||||
new DatagramPacket(
|
|
||||||
byteArrayToByteBuf(mbPackage.getBody()),
|
|
||||||
new InetSocketAddress(this.host,this.port)))
|
|
||||||
.sync();
|
|
||||||
|
|
||||||
Package aPackage = add.get(5000L, mbPackage.getTransationId());
|
|
||||||
byte[] body = aPackage.getBody();
|
|
||||||
|
|
||||||
String errMsg = " [ AGVclient - send success ] [ "+name+" host: "+ this.host +" ]"+event.toString();
|
|
||||||
logger.info(errMsg);
|
|
||||||
//注意:这里的body 是整个 response结构,包括 : 授权码 + header + body
|
|
||||||
return new RcvEventPackage(body[22],body);
|
|
||||||
}catch (Throwable e) {
|
|
||||||
//e.printStackTrace();
|
|
||||||
String errMsg = " [ AGVclient - Read ] [ "+name+" host: "+ this.host +" ] ( occur err ) errTime: "+" ; send errMsg : "+e.getMessage()+" ; event :"+event.toString();
|
|
||||||
logger.info(errMsg);
|
|
||||||
throw new RuntimeException(errMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void subscribe0xB0(RcvEventPackage rcv){
|
|
||||||
|
|
||||||
if (rcv.isOk()) {
|
|
||||||
|
|
||||||
if(name.equals("1")){
|
|
||||||
this.achieveSub0xB0(name, rcv);
|
|
||||||
}else if(name.equals("2")){
|
|
||||||
this.achieveSub0xB0(name, rcv);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
System.out.println();
|
|
||||||
System.out.println("subscribe0xB0 received transationId : "+ "isok:"+rcv.isOk());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
public void subscribe0xAF(RcvEventPackage rcv){
|
|
||||||
|
|
||||||
if (rcv.isOk()) {
|
|
||||||
|
|
||||||
if (name.equals("1")) {
|
|
||||||
this.achieveSub0xAF(name, rcv);
|
|
||||||
} else if (name.equals("2")) {
|
|
||||||
this.achieveSub0xAF(name, rcv);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
System.out.println();
|
|
||||||
System.out.println("subscribe0xAF received transationId : "+ "isok:"+rcv.isOk());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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());
|
servicePortal.login(SERVICE_HOST, SERVICE_PORT);
|
||||||
for (byte b:rcv.getValue()){
|
VehicleService vehicleService = servicePortal.getVehicleService();
|
||||||
System.out.print(byteToHex(b)+" ");
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
|
||||||
}
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), body);
|
||||||
|
}
|
||||||
KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER, GuestUserCredentials.PASSWORD).build();
|
|
||||||
servicePortal.login(SERVICE_HOST, SERVICE_PORT);
|
|
||||||
VehicleService vehicleService = servicePortal.getVehicleService();
|
|
||||||
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, vehicleName);
|
|
||||||
//将AGV控制器上报信息传入通讯适配器
|
|
||||||
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(
|
||||||
servicePortal.login(SERVICE_HOST, SERVICE_PORT);
|
SERVICE_USER, SERVICE_PWD
|
||||||
VehicleService vehicleService = servicePortal.getVehicleService();
|
).build();
|
||||||
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, vehicleName);
|
servicePortal.login(SERVICE_HOST, SERVICE_PORT);
|
||||||
//将AGV控制器上报信息传入通讯适配器
|
VehicleService vehicleService = servicePortal.getVehicleService();
|
||||||
vehicleService.sendCommAdapterMessage(vehicle.getReference(), queryCargoStatusRsp);
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name);
|
||||||
|
|
||||||
servicePortal.logout();
|
if (vehicle == null) {
|
||||||
|
throw new RuntimeException("vehicle name:" + name + ",does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void printInfo(AgvEvent agvEvent){
|
//将AGV控制器上报信息传入通讯适配器
|
||||||
System.out.println("sended transationId : "+agvEvent.getTransationIdString());
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), body);
|
||||||
for (byte b:agvEvent.toBytes().getBody()){
|
|
||||||
System.out.print(byteToHex(b)+" ");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public static String byteToHex(byte b) {
|
|
||||||
// 将byte转换为无符号整数
|
|
||||||
int unsignedByte = b & 0xFF;
|
|
||||||
// 使用Integer.toHexString方法转换为十六进制字符串
|
|
||||||
String hexString = Integer.toHexString(unsignedByte);
|
|
||||||
// 如果字符串长度为1,需要在前面补0
|
|
||||||
if (hexString.length() == 1) {
|
|
||||||
return "0" + hexString;
|
|
||||||
}
|
|
||||||
return hexString;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* decs: 在项目启动的时候初始化 后面就不会初始化了
|
|
||||||
* */
|
|
||||||
private void initClient() {
|
|
||||||
//NioEventLoopGroup 、 Bootstrap 这些资源其实是不用 release的,因为全局共用一份的你释放了 下次还得再new
|
|
||||||
NioEventLoopGroup group = new NioEventLoopGroup();
|
|
||||||
this.bootstrap = new Bootstrap();
|
|
||||||
this.bootstrap.group(group)
|
|
||||||
/*由于我们用的是UDP协议,所以要用NioDatagramChannel来创建*/
|
|
||||||
.channel(NioDatagramChannel.class)
|
|
||||||
.handler(new ChannelInitializer<NioDatagramChannel>() {
|
|
||||||
@Override
|
|
||||||
protected void initChannel(NioDatagramChannel ch) throws Exception {
|
|
||||||
ChannelPipeline pipeline = ch.pipeline();
|
|
||||||
//0 代表禁用 readerIdleTime 事件的监听
|
|
||||||
//这两个是固定的
|
|
||||||
//pipeline.addLast(new IdleStateHandler(0,0,10, TimeUnit.SECONDS));
|
|
||||||
|
|
||||||
//协议层的handler 这里要做以区分
|
servicePortal.logout();
|
||||||
|
}
|
||||||
|
|
||||||
pipeline.addLast(new AgvUdpChannelInitializer(UDPClient.this));
|
public static void printInfo(AgvEvent agvEvent) {
|
||||||
}
|
System.out.println("sended transationId : " + agvEvent.getTransationIdString());
|
||||||
});
|
for (byte b : agvEvent.toBytes().getBody()) {
|
||||||
try {
|
System.out.print(byteToHex(b) + " ");
|
||||||
this.conn = this.bootstrap.bind(this.bindPort).sync().channel();
|
|
||||||
}catch (Exception e){
|
|
||||||
logger.info("AGV UDP Initial Exception : "+e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String byteToHex(byte b) {
|
||||||
|
// 将byte转换为无符号整数
|
||||||
|
int unsignedByte = b & 0xFF;
|
||||||
|
// 使用Integer.toHexString方法转换为十六进制字符串
|
||||||
|
String hexString = Integer.toHexString(unsignedByte);
|
||||||
|
// 如果字符串长度为1,需要在前面补0
|
||||||
|
if (hexString.length() == 1) {
|
||||||
|
return "0" + hexString;
|
||||||
|
}
|
||||||
|
return hexString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* decs: 在项目启动的时候初始化 后面就不会初始化了
|
||||||
|
*/
|
||||||
|
private void initClient() {
|
||||||
|
//NioEventLoopGroup 、 Bootstrap 这些资源其实是不用 release的,因为全局共用一份的你释放了 下次还得再new
|
||||||
|
NioEventLoopGroup group = new NioEventLoopGroup();
|
||||||
|
this.bootstrap = new Bootstrap();
|
||||||
|
this.bootstrap.group(group)
|
||||||
|
/* 由于我们用的是UDP协议,所以要用NioDatagramChannel来创建 */
|
||||||
|
.channel(NioDatagramChannel.class)
|
||||||
|
.handler(new ChannelInitializer<NioDatagramChannel>() {
|
||||||
|
@Override
|
||||||
|
protected void initChannel(NioDatagramChannel ch)
|
||||||
|
throws Exception {
|
||||||
|
ChannelPipeline pipeline = ch.pipeline();
|
||||||
|
//0 代表禁用 readerIdleTime 事件的监听
|
||||||
|
//这两个是固定的
|
||||||
|
//pipeline.addLast(new IdleStateHandler(0,0,10, TimeUnit.SECONDS));
|
||||||
|
|
||||||
|
//协议层的handler 这里要做以区分
|
||||||
|
|
||||||
|
pipeline.addLast(new AgvUdpChannelInitializer(UDPClient.this));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
this.conn = this.bootstrap.bind(this.bindPort).sync().channel();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
logger.info("AGV UDP Initial Exception : " + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -86,40 +86,46 @@ 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(
|
||||||
servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT);
|
GuestUserCredentials.USER, GuestUserCredentials.PASSWORD
|
||||||
VehicleService vehicleService = servicePortal.getVehicleService();
|
).build();
|
||||||
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "2");
|
servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT);
|
||||||
vehicleService.sendCommAdapterMessage(vehicle.getReference(), map);
|
VehicleService vehicleService = servicePortal.getVehicleService();
|
||||||
|
Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "50");
|
||||||
|
vehicleService.sendCommAdapterMessage(vehicle.getReference(), map);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user