From 4882a28c0a888770d1b84e0494f4ebd819737b94 Mon Sep 17 00:00:00 2001 From: wait <2543137953@qq.com> Date: Fri, 18 Apr 2025 11:06:14 +0800 Subject: [PATCH] update vehicle adapter --- .../kcvehicle/KcCommAdapterModule.java | 40 - ...ustomizations.kernel.KernelInjectionModule | 1 - .../kcvehicle/KcAdapterComponentsFactory.java | 10 - .../kcvehicle/KcCommunicationAdapter.java | 163 -- .../KcCommunicationAdapterDescription.java | 15 - .../KcCommunicationAdapterFactory.java | 61 - .../kcvehicle/KcVehicleConfiguration.java | 77 - .../LoopbackCommunicationAdapter.java | 515 +++- .../LoopbackVehicleModelTO.java | 45 + .../opentcs/common/GuestUserCredentials.java | 2 +- .../common/LoopbackAdapterConstants.java | 4 + .../org/opentcs/kc/common/CaffeineUtil.java | 229 +- .../java/org/opentcs/kc/common/Const.java | 47 +- .../java/org/opentcs/kc/common/Package.java | 55 +- .../opentcs/kc/common/ParseDataException.java | 104 +- .../org/opentcs/kc/common/RcvPackage.java | 67 +- .../java/org/opentcs/kc/common/Utils.java | 109 +- .../opentcs/kc/common/byteutils/ByteUtil.java | 638 ++--- .../kc/common/byteutils/ByteUtils.java | 2352 +++++++++-------- .../kc/common/byteutils/CommonFunctions.java | 23 +- .../kc/common/byteutils/StringArrayStruc.java | 41 +- .../org/opentcs/kc/common/enmuc/ModbusFC.java | 48 +- .../java/org/opentcs/kc/syn/AsyncFuture.java | 93 +- .../main/java/org/opentcs/kc/syn/Future.java | 13 +- .../main/java/org/opentcs/kc/syn/Main.java | 7 - .../java/org/opentcs/kc/syn/SendedList.java | 58 +- .../java/org/opentcs/kc/udp/GB/LogConst.java | 37 +- .../kc/udp/GB/LogEventBroadcaster.java | 104 +- .../opentcs/kc/udp/GB/LogEventDecoder.java | 56 +- .../opentcs/kc/udp/GB/LogEventEncoder.java | 55 +- .../opentcs/kc/udp/GB/LogEventHandler.java | 53 +- .../opentcs/kc/udp/GB/LogEventMonitor.java | 93 +- .../java/org/opentcs/kc/udp/GB/LogMsg.java | 82 +- .../org/opentcs/kc/udp/KCCommandDemo.java | 511 ++-- .../opentcs/kc/udp/Service/BaseCommand.java | 19 +- .../kc/udp/Service/ConfirmRelocation.java | 26 +- .../kc/udp/Service/HybridNavigation.java | 124 +- .../kc/udp/Service/ManualPosition.java | 23 +- .../kc/udp/Service/QryRobotRunStatus.java | 30 +- .../kc/udp/Service/QryRobotStatus.java | 31 +- .../kc/udp/Service/SubCargoStatus.java | 46 +- .../kc/udp/Service/SubRobotStatue.java | 36 +- .../kc/udp/Service/SwitchAutomaticMode.java | 31 +- .../kc/udp/Service/SwitchManualMode.java | 31 +- .../agv/codec/AgvUdpChannelInitializer.java | 31 +- .../kc/udp/agv/codec/AgvUdpDecode.java | 131 +- .../opentcs/kc/udp/agv/param/AgvEvent.java | 149 +- .../kc/udp/agv/param/AgvEventConstant.java | 49 +- .../kc/udp/agv/param/AgvEventHeader.java | 181 +- .../opentcs/kc/udp/agv/param/IAgvEvent.java | 16 +- .../function/af/AbnormalEventStatusInfo.java | 31 +- .../udp/agv/param/function/af/ActionInfo.java | 31 +- .../param/function/af/BatteryStatusInfo.java | 50 +- .../param/function/af/LocationStatusInfo.java | 129 +- .../param/function/af/PathStateSequence.java | 28 +- .../param/function/af/PointStateSequence.java | 28 +- .../function/af/QueryRobotStatusRsp.java | 97 +- .../param/function/af/RunningStatusInfo.java | 59 +- .../agv/param/function/af/TaskStatusInfo.java | 76 +- .../function/b0/QueryCargoStatusRsp.java | 27 +- .../agv/param/function/b1/SubscribeInfo.java | 33 +- .../agv/param/function/b1/SubscribeParam.java | 108 +- .../agv/param/function/b1/SubscribeRsp.java | 47 +- .../agv/param/function/navigation/Action.java | 81 +- .../param/function/navigation/ActionSet.java | 111 +- .../function/navigation/NavigationParam.java | 89 +- .../agv/param/function/navigation/Path.java | 120 +- .../agv/param/function/navigation/Point.java | 87 +- .../agv/param/function/read/ReadParam.java | 76 +- .../udp/agv/param/function/read/ReadRsp.java | 52 +- .../agv/param/function/read/ReadStrValue.java | 75 +- .../param/function/read/ReadValueMember.java | 39 +- .../agv/param/function/write/WriteParam.java | 50 +- .../param/function/write/WriteStrValue.java | 49 +- .../function/write/WriteValueMember.java | 42 +- .../param/function/x14/RobotSetPosition.java | 42 +- .../function/x17/QueryRobotRunStatusRsp.java | 235 +- .../kc/udp/agv/param/rsp/RcvEventPackage.java | 140 +- .../java/org/opentcs/kc/udp/io/UDPClient.java | 432 +-- .../common/SameThreadExecutorServiceTest.java | 68 +- .../DefaultPropertySuggestions.java | 1 + 81 files changed, 4660 insertions(+), 4635 deletions(-) delete mode 100644 opentcs-commadapter-loopback/src/guiceConfig/java/org/opentcs/kcvehicle/KcCommAdapterModule.java delete mode 100644 opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcAdapterComponentsFactory.java delete mode 100644 opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapter.java delete mode 100644 opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterDescription.java delete mode 100644 opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterFactory.java delete mode 100644 opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcVehicleConfiguration.java diff --git a/opentcs-commadapter-loopback/src/guiceConfig/java/org/opentcs/kcvehicle/KcCommAdapterModule.java b/opentcs-commadapter-loopback/src/guiceConfig/java/org/opentcs/kcvehicle/KcCommAdapterModule.java deleted file mode 100644 index aecceac..0000000 --- a/opentcs-commadapter-loopback/src/guiceConfig/java/org/opentcs/kcvehicle/KcCommAdapterModule.java +++ /dev/null @@ -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); - } - -} diff --git a/opentcs-commadapter-loopback/src/guiceConfig/resources/META-INF/services/org.opentcs.customizations.kernel.KernelInjectionModule b/opentcs-commadapter-loopback/src/guiceConfig/resources/META-INF/services/org.opentcs.customizations.kernel.KernelInjectionModule index 088ec41..bf0777b 100644 --- a/opentcs-commadapter-loopback/src/guiceConfig/resources/META-INF/services/org.opentcs.customizations.kernel.KernelInjectionModule +++ b/opentcs-commadapter-loopback/src/guiceConfig/resources/META-INF/services/org.opentcs.customizations.kernel.KernelInjectionModule @@ -2,4 +2,3 @@ # SPDX-License-Identifier: MIT org.opentcs.virtualvehicle.LoopbackCommAdapterModule -org.opentcs.kcvehicle.KcCommAdapterModule diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcAdapterComponentsFactory.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcAdapterComponentsFactory.java deleted file mode 100644 index a9768d6..0000000 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcAdapterComponentsFactory.java +++ /dev/null @@ -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); -} diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapter.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapter.java deleted file mode 100644 index d45e334..0000000 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapter.java +++ /dev/null @@ -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()); - } -} diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterDescription.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterDescription.java deleted file mode 100644 index 59d7640..0000000 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterDescription.java +++ /dev/null @@ -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; - } -} diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterFactory.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterFactory.java deleted file mode 100644 index 3604863..0000000 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcCommunicationAdapterFactory.java +++ /dev/null @@ -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() { - - } - -} diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcVehicleConfiguration.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcVehicleConfiguration.java deleted file mode 100644 index c0432db..0000000 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/kcvehicle/KcVehicleConfiguration.java +++ /dev/null @@ -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(); -} diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java index 10ac126..d8407b7 100644 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java +++ b/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackCommunicationAdapter.java @@ -7,6 +7,7 @@ import static java.util.Objects.requireNonNull; import com.google.inject.assistedinject.Assisted; import jakarta.inject.Inject; import java.beans.PropertyChangeEvent; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.Date; import java.util.HashMap; @@ -14,11 +15,14 @@ import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; import org.opentcs.common.LoopbackAdapterConstants; import org.opentcs.customizations.kernel.KernelExecutor; +import org.opentcs.data.model.Point; import org.opentcs.data.model.Pose; import org.opentcs.data.model.Triple; 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.b0.QueryCargoStatusRsp; 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.virtualvehicle.VelocityController.WayEntry; import org.slf4j.Logger; @@ -113,25 +118,32 @@ public class LoopbackCommunicationAdapter */ private boolean initialized; /** - * 上报截止时间 + * 0xAF上报截止时间. */ - private long deadline; + private long sub0xafDeadline; /** - * 上报间隔时间/ms + * 0xB0上报截止时间. */ - private long intervalTime; -// /** -// * AGV IP -// */ -// private final String IP; -// /** -// * AGV 端口 -// */ -// private final int PORT; -// /** -// * AGV AUTHORIZE_CODE -// */ -// private final String AUTHORIZE_CODE; + private long sub0xb0Deadline; + /** + * 创建线程 + */ + private final ExecutorService messageProcessingPool = new ThreadPoolExecutor( + 4, + 8, + 60L, + TimeUnit.MILLISECONDS, + new LinkedBlockingQueue<>(100), + new ThreadPoolExecutor.CallerRunsPolicy() + ); + /** + * 订阅状态 + */ + private static boolean SUBSCRIBE_STATUS; + /** + * 最后经过点位 + */ + private static String LAST_PASSED_POINT; /** * Creates a new instance. @@ -193,41 +205,52 @@ public class LoopbackCommunicationAdapter @Override public void propertyChange(PropertyChangeEvent evt) { + //调用父类的 propertyChange 方法处理事件。 super.propertyChange(evt); + //如果事件源不是 LoopbackVehicleModel 类型,直接返回。 if (!((evt.getSource()) instanceof LoopbackVehicleModel)) { return; } + + //如果事件属性名为 LOAD_HANDLING_DEVICES: if (Objects.equals( evt.getPropertyName(), VehicleProcessModel.Attribute.LOAD_HANDLING_DEVICES.name() )) { if (!getProcessModel().getLoadHandlingDevices().isEmpty() && getProcessModel().getLoadHandlingDevices().get(0).isFull()) { + //检查负载处理设备是否为空且第一个设备是否满载,更新负载状态为 FULL 并设置车辆长度为加载状态下的长度。 loadState = LoadState.FULL; getProcessModel().setBoundingBox( getProcessModel().getBoundingBox().withLength(configuration.vehicleLengthLoaded()) ); } else { + //否则,更新负载状态为 EMPTY 并设置车辆长度为未加载状态下的长度。 loadState = LoadState.EMPTY; getProcessModel().setBoundingBox( getProcessModel().getBoundingBox().withLength(configuration.vehicleLengthUnloaded()) ); } } + + //如果事件属性名为 SINGLE_STEP_MODE: if (Objects.equals( evt.getPropertyName(), LoopbackVehicleModel.Attribute.SINGLE_STEP_MODE.name() )) { // When switching from single step mode to automatic mode and there are commands to be // processed, ensure that we start/continue processing them. + //如果单步模式关闭、待处理命令队列非空且模拟未运行,则启动车辆模拟。 if (!getProcessModel().isSingleStepModeEnabled() && !getSentCommands().isEmpty() && !isSimulationRunning) { + //标记模拟正在运行 isSimulationRunning = true; + //提交任务到线程池,执行队列中的第一个命令 ((ExecutorService) getExecutor()).submit( - () -> startVehicleSimulation(getSentCommands().peek()) + () -> startVehicle(getSentCommands().peek()) ); } } @@ -261,6 +284,7 @@ public class LoopbackCommunicationAdapter System.out.println(cmd); System.out.println("send cmd print start"); +// SubRobotStatue.command(); //订单ID String orderName = cmd.getTransportOrder().getName(); @@ -283,29 +307,40 @@ public class LoopbackCommunicationAdapter System.out.println("sourcePoint:" + sourcePoint); //下发终点 - String destinationPoint = cmd.getStep().getDestinationPoint().getName(); - System.out.println("destinationPoint:" + destinationPoint); + Point destinationPoint = cmd.getStep().getDestinationPoint(); + //获取点类型 + 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"); + //订阅0xAF +// sub0xAF(); //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() && !isSimulationRunning) { 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()) { - ((ExecutorService) getExecutor()).submit(() -> startVehicleSimulation(cmd)); + ((ExecutorService) getExecutor()).submit(() -> startVehicle(cmd)); } else { ((ExecutorService) getExecutor()).submit( - () -> startVehicleSimulation(getSentCommands().peek()) + () -> startVehicle(getSentCommands().peek()) ); } } @@ -318,74 +353,100 @@ public class LoopbackCommunicationAdapter @Override public void processMessage(Object message) { - if (message instanceof String) { - //测试使用 - getProcessModel().setEnergyLevel(66); - System.out.println(message); + + if (message instanceof byte[]) { + updateVehicleModel(message); } - else if (message instanceof QueryCargoStatusRsp) { - //0xB0响应结果 - QueryCargoStatusRsp queryCargoStatusRsp = (QueryCargoStatusRsp) message; + else if (message instanceof HashMap) { + //todo 测试代码----成功 + HashMap msg = (HashMap) message; - if (queryCargoStatusRsp.isCargo == 0) { - 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().setEnergyLevel((int) msg.get("energy")); getProcessModel().setState(Vehicle.State.EXECUTING); - long positionX = (long)msg.get("positionX"); - long positionY = (long)msg.get("positionY"); + long positionX = (long) msg.get("positionX"); + long positionY = (long) msg.get("positionY"); 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)); } + } - //上报自动续订操作 -// renewalSubscribe(); + private void updateVehicleModel(Object message) { + 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(); - if (now.getTime() + intervalTime >= deadline) { - //开启AGV订阅监听 (0xAF & 0xB0) - SubRobotStatue.command(); - SubCargoStatus.command(); + if (sub0xafDeadline - now.getTime() <= SubRobotStatue.intervalTime && SUBSCRIBE_STATUS) { + sub0xAF(); + } + } + + /** + * 订阅到期,自动续订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 protected synchronized void connectVehicle() { - String ip = requireNonNull(vehicle.getProperties().get(LoopbackAdapterConstants.AGV_IP), "AGV IP NOT NULL"); - Integer port = Integer.parseInt(requireNonNull(vehicle.getProperties().get(LoopbackAdapterConstants.AGV_PORT), "AGV PORT NOT NULL")); - String authorizeCode = requireNonNull(vehicle.getProperties().get(LoopbackAdapterConstants.AGV_AUTHORIZE_CODE), "AGV AUTHORIZE_CODE NOT NULL"); - getProcessModel().setCommAdapterConnected(true); -// initAGV(); +// getProcessModel().setCommAdapterConnected(true); + initAGV(); } @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) { LOG.debug("Starting vehicle simulation for command: {}", command); Step step = command.getStep(); @@ -529,12 +617,54 @@ public class LoopbackCommunicationAdapter : 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. * * @param command The command to simulate. */ private void movementSimulation(MovementCommand command) { + //检查当前车辆模型的速度控制器是否有路径条目,若无则直接返回。 if (!getProcessModel().getVelocityController().hasWayEntries()) { return; } @@ -543,7 +673,9 @@ public class LoopbackCommunicationAdapter getProcessModel().getVelocityController().advanceTime(getSimulationTimeStep()); WayEntry currentWayEntry = getProcessModel().getVelocityController().getCurrentWayEntry(); //if we are still on the same way entry then reschedule to do it again + //获取当前路径条目并推进时间步长,检查是否仍处于同一路径条目: if (prevWayEntry == currentWayEntry) { + //若是,则重新调度当前方法以继续模拟。 getExecutor().schedule( () -> movementSimulation(command), SIMULATION_PERIOD, @@ -553,6 +685,7 @@ public class LoopbackCommunicationAdapter else { //if the way enties are different then we have finished this step //and we can move on. + //若否,更新车辆位置为上一路径条目的目标点,并根据命令是否有操作决定进入操作模拟或完成命令并模拟下一个命令。 getProcessModel().setPosition(prevWayEntry.getDestPointName()); LOG.debug("Movement simulation finished."); 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. + * 模拟移动命令的操作部分。 * * @param command The command to simulate. * @param timePassed The amount of time passed since starting the simulation. @@ -626,6 +769,7 @@ public class LoopbackCommunicationAdapter /** * Simulate recharging the vehicle. + * 模拟为车辆充电。 * * @param rechargePosition The vehicle position where the recharge simulation was started. * @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; } + /** + * 结束移动命令。 + * @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) { //Set the vehicle state to idle if (getSentCommands().size() <= 1 && getUnsentCommands().isEmpty()) { getProcessModel().setState(Vehicle.State.IDLE); } 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()); +// HybridNavigation.delUniqueOrderID(command); } else { 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() { if (getSentCommands().isEmpty() || getProcessModel().isSingleStepModeEnabled()) { LOG.debug("Vehicle simulation is done."); @@ -727,47 +916,133 @@ public class LoopbackCommunicationAdapter */ private void initAGV() { - //0xAF获取AGV状态 - QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command(); + if (true) { + //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"); + } - //设置订阅时间和上报间隔 - Date now = new Date(); - 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; + //开启0xAF订阅 + sub0xAF(); - //3 查询机器人运行状态(命令码:0x17),等待机器人定位状态为定位完成; - QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command(); - if (qryRobotRunStatusRsp.robotLocalizationState == 0) { + //开启0xB0订阅 +// sub0xB0() + +// //新:设置车辆姿势。(官方弃用设置车辆精确位置)-------------------目前车辆返回位置为固定值!!!!! +// long positionX = (long) qryRobotStatusRsp.locationStatusInfo.globalX; +// long positionY = (long) qryRobotStatusRsp.locationStatusInfo.globalY; +// Triple triple = new Triple(positionX, positionY, 0); +// double positionAngle = qryRobotStatusRsp.locationStatusInfo.absoluteDirecAngle; +// getProcessModel().setPose(new Pose(triple, positionAngle)); + + //3 查询机器人运行状态(命令码:0x17),等待机器人定位状态为定位完成; + System.out.println("=================---initAGV_0x17"); + QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command(); + + if (qryRobotRunStatusRsp == null) { + getProcessModel().setCommAdapterConnected(false); + throw new RuntimeException("initAGV 0x17 response is null"); + } + + if (qryRobotRunStatusRsp.robotLocalizationState == 0) { + getProcessModel().setCommAdapterConnected(false); + throw new RuntimeException("AGV定位失败,请执行手动定位"); + } + else if (qryRobotRunStatusRsp.robotLocalizationState == 2) { + getProcessModel().setCommAdapterConnected(false); + throw new RuntimeException("AGV定位中,请稍后再试"); + } + + //5 切换成自动模式(命令码:0x03,变量:NaviControl 修改为1); + System.out.println(); + System.out.println("=================---initAGV_0x03-----111111"); + SwitchAutomaticMode.command(); + getProcessModel().setState(Vehicle.State.IDLE); + + //打开通讯适配器连接 + getProcessModel().setCommAdapterConnected(true); + } else { + //0xAF获取AGV状态 + System.out.println("=================---initAGV_0xAF"); + QueryRobotStatusRsp qryRobotStatusRsp = QryRobotStatus.command(); + if (qryRobotStatusRsp == null) { + getProcessModel().setCommAdapterConnected(false); + throw new RuntimeException("initAGV 0xAF response is null"); + } + + //开启0xAF订阅 + sub0xAF(); + + //开启0xB0订阅 + sub0xB0(); + + //1 切换定位为手动模式(命令码:0x03,变量:NaviControl 修改为0); + 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); + 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); - throw new RuntimeException("AGV定位失败,执行手动定位中"); + //3 查询机器人运行状态(命令码:0x17),等待机器人定位状态为定位完成; + System.out.println("=================---initAGV_0x17"); + QueryRobotRunStatusRsp qryRobotRunStatusRsp = QryRobotRunStatus.command(); - } else if (qryRobotRunStatusRsp.robotLocalizationState == 2) { - throw new RuntimeException("AGV定位中"); + 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定位中,请稍后再试"); + } + + //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); - ConfirmRelocation.commnd(); + private void sub0xAF(){ + messageProcessingPool.submit(() -> { + Date now = new Date(); + sub0xafDeadline = now.getTime() + 10000; + SubRobotStatue.command(); + }); + } - //5 切换成自动模式(命令码:0x03,变量:NaviControl 修改为1); - SwitchAutomaticMode.command(); - - //打开通讯适配器连接 - getProcessModel().setCommAdapterConnected(true); + private void sub0xB0(){ + messageProcessingPool.submit(() -> { + Date now = new Date(); + sub0xb0Deadline = now.getTime() + 10000; + SubCargoStatus.command(); + }); } } diff --git a/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackVehicleModelTO.java b/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackVehicleModelTO.java index 3ab04a9..e43b0db 100644 --- a/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackVehicleModelTO.java +++ b/opentcs-commadapter-loopback/src/main/java/org/opentcs/virtualvehicle/LoopbackVehicleModelTO.java @@ -58,6 +58,11 @@ public class LoopbackVehicleModelTO return singleStepModeEnabled; } + /** + * 设置单步模式已启用. + * @param singleStepModeEnabled 启用单步模式 + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setSingleStepModeEnabled(boolean singleStepModeEnabled) { this.singleStepModeEnabled = singleStepModeEnabled; return this; @@ -67,6 +72,11 @@ public class LoopbackVehicleModelTO return loadOperation; } + /** + * 设置装载操作. + * @param loadOperation 状态 + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setLoadOperation(String loadOperation) { this.loadOperation = loadOperation; return this; @@ -76,6 +86,11 @@ public class LoopbackVehicleModelTO return unloadOperation; } + /** + * 设置卸载操作. + * @param unloadOperation 状态 + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setUnloadOperation(String unloadOperation) { this.unloadOperation = unloadOperation; return this; @@ -85,6 +100,11 @@ public class LoopbackVehicleModelTO return operatingTime; } + /** + * 设置运行时间. + * @param operatingTime 时间戳 + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setOperatingTime(int operatingTime) { this.operatingTime = operatingTime; return this; @@ -94,6 +114,11 @@ public class LoopbackVehicleModelTO return maxAcceleration; } + /** + * 设置最大加速度. + * @param maxAcceleration + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setMaxAcceleration(int maxAcceleration) { this.maxAcceleration = maxAcceleration; return this; @@ -103,6 +128,11 @@ public class LoopbackVehicleModelTO return maxDeceleration; } + /** + * 设置最大减速. + * @param maxDeceleration + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setMaxDeceleration(int maxDeceleration) { this.maxDeceleration = maxDeceleration; return this; @@ -112,6 +142,11 @@ public class LoopbackVehicleModelTO return maxFwdVelocity; } + /** + * 设置最大前驱速度. + * @param maxFwdVelocity + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setMaxFwdVelocity(int maxFwdVelocity) { this.maxFwdVelocity = maxFwdVelocity; return this; @@ -121,6 +156,11 @@ public class LoopbackVehicleModelTO return maxRevVelocity; } + /** + * 设置最大速度. + * @param maxRevVelocity + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setMaxRevVelocity(int maxRevVelocity) { this.maxRevVelocity = maxRevVelocity; return this; @@ -130,6 +170,11 @@ public class LoopbackVehicleModelTO return vehiclePaused; } + /** + * 将车辆设置为暂停. + * @param vehiclePaused + * @return LoopbackVehicleModelTO + */ public LoopbackVehicleModelTO setVehiclePaused(boolean vehiclePaused) { this.vehiclePaused = vehiclePaused; return this; diff --git a/opentcs-common/src/main/java/org/opentcs/common/GuestUserCredentials.java b/opentcs-common/src/main/java/org/opentcs/common/GuestUserCredentials.java index eaa299e..8f6f8d4 100644 --- a/opentcs-common/src/main/java/org/opentcs/common/GuestUserCredentials.java +++ b/opentcs-common/src/main/java/org/opentcs/common/GuestUserCredentials.java @@ -18,7 +18,7 @@ public interface GuestUserCredentials { /** * 主机IP */ - String IP = "192.168.0.106"; + String IP = "192.168.124.111"; /** * 内核开放端口 */ diff --git a/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java b/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java index 1299acb..83d91d5 100644 --- a/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java +++ b/opentcs-common/src/main/java/org/opentcs/common/LoopbackAdapterConstants.java @@ -53,5 +53,9 @@ public interface LoopbackAdapterConstants { * AGV 端口 */ String AGV_PORT = "AGV:PORT"; + /** + * 定制点位类型,1=WMS请求点位 + */ + String POINT_TYPE = "tcs:point"; } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/CaffeineUtil.java b/opentcs-common/src/main/java/org/opentcs/kc/common/CaffeineUtil.java index 476eaf8..5699178 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/CaffeineUtil.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/CaffeineUtil.java @@ -11,133 +11,136 @@ import org.opentcs.kc.common.byteutils.ByteUtils; 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 cache; - private static Cache cacheUUID; + private static Cache cache; + private static Cache cacheUUID; - /** - * 初始化Caffeine缓存配置 - */ - static { - //todo https://github.com/ben-manes/caffeine/wiki 研究一下,然后升级一下版本 - cache = Caffeine.newBuilder() - .maximumSize(MAXIMUM_SIZE) - .expireAfterWrite(EXPIRE_AFTER_WRITE_DURATION, EXPIRE_AFTER_WRITE_TIMEUNIT) - .build(); + /** + * 初始化Caffeine缓存配置 + */ + static { + //todo https://github.com/ben-manes/caffeine/wiki 研究一下,然后升级一下版本 + cache = Caffeine.newBuilder() + .maximumSize(MAXIMUM_SIZE) + .expireAfterWrite(EXPIRE_AFTER_WRITE_DURATION, EXPIRE_AFTER_WRITE_TIMEUNIT) + .build(); - cacheUUID = Caffeine.newBuilder() - .maximumSize(10) - .expireAfterWrite(Long.MAX_VALUE, EXPIRE_AFTER_WRITE_TIMEUNIT) - .build(); + cacheUUID = Caffeine.newBuilder() + .maximumSize(10) + .expireAfterWrite(Long.MAX_VALUE, EXPIRE_AFTER_WRITE_TIMEUNIT) + .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); } - - 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())); - + else { + if (uuid.get() >= 32000) { + cacheUUID.put("UUID", new AtomicInteger(1)); + return ByteUtils.intToBytes(1); + } + else { + return ByteUtils.intToBytes(uuid.incrementAndGet()); + } } + } - - - 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 { - if(uuid.get() >= 32000){ - cacheUUID.put("UUID",new AtomicInteger(1)); - return ByteUtils.intToBytes(1); - }else { - return ByteUtils.intToBytes(uuid.incrementAndGet()); - } - } + public static synchronized byte[] getUUIDAGV() { + AtomicInteger agvuuid = cacheUUID.getIfPresent("AGVUUID"); + if (agvuuid == null) { + //transationId 从1 开始,0留给心跳变量,这样就固定报文了 + cacheUUID.put("AGVUUID", new AtomicInteger(1)); + return ByteUtils.intToBytesS(1); } - - public static synchronized byte[] getUUIDAGV() { - AtomicInteger agvuuid = cacheUUID.getIfPresent("AGVUUID"); - if(agvuuid == null){ - //transationId 从1 开始,0留给心跳变量,这样就固定报文了 - cacheUUID.put("AGVUUID",new AtomicInteger(1)); - return ByteUtils.intToBytesS(1); - }else { - if(agvuuid.get() >= 32000){ - cacheUUID.put("AGVUUID",new AtomicInteger(1)); - return ByteUtils.intToBytesS(1); - }else { - 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 缓存键 - * @return 缓存值 - */ - public static Object get(String key) { - return cache.getIfPresent(key); - } + /** + * 获取缓存值 + * + * @param key 缓存键 + * @return 缓存值 + */ + public static Object get(String key) { + return cache.getIfPresent(key); + } - /** - * 设置缓存值 - * - * @param key 缓存键 - * @param value 缓存值 - */ - public static void put(String key, Object value) { - cache.put(key, value); - } + /** + * 设置缓存值 + * + * @param key 缓存键 + * @param value 缓存值 + */ + public static void put(String key, Object value) { + cache.put(key, value); + } - /** - * 移除缓存项 - * - * @param key 缓存键 - */ - public static void remove(String key) { - cache.invalidate(key); - } + /** + * 移除缓存项 + * + * @param key 缓存键 + */ + public static void remove(String key) { + cache.invalidate(key); + } - /** - * 清空缓存 - */ - public static void clear() { - cache.invalidateAll(); - } + /** + * 清空缓存 + */ + public static void clear() { + cache.invalidateAll(); + } - /** - * 获取缓存中的所有值 - * - * @return 缓存中的所有值集合 - */ - public static Collection getAllValues() { - return cache.asMap().values(); - } + /** + * 获取缓存中的所有值 + * + * @return 缓存中的所有值集合 + */ + public static Collection getAllValues() { + return cache.asMap().values(); + } - /** - * 清空缓存中的所有值 - */ - public static void removeAllValues() { - cache.invalidateAll(); - } + /** + * 清空缓存中的所有值 + */ + public static void removeAllValues() { + cache.invalidateAll(); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/Const.java b/opentcs-common/src/main/java/org/opentcs/kc/common/Const.java index d404334..f60f389 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/Const.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/Const.java @@ -6,34 +6,35 @@ package org.opentcs.kc.common; * 2017年3月30日 下午7:05:54 */ 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) { - String s = "123, 34, 104, 101, 97, 100, 101, 114, 34, 58, 123, 34, 116, 114, 97, 110, 115, 97, 99, 116, 105, 111, 110, 73, 100, 34, 58, 34, 50, 48, 50, 52, 48, 49, 48, 50, 49, 53, 52, 48, 50, 55, 95, 51, 100, 56, 49, 99, 34, 44, 34, 109, 101, 115, 115, 97, 103, 101, 84, 121, 112, 101, 34, 58, 51, 44, 34, 109, 101, 115, 115, 97, 103, 101, 78, 97, 109, 101, 34, 58, 34, 72, 101, 97, 114, 116, 66, 101, 97, 116, 34, 44, 34, 115, 101, 110, 100, 84, 105, 109, 101, 115, 116, 97, 109, 112, 34, 58, 34, 50, 48, 50, 52, 45, 48, 49, 45, 48, 50, 32, 49, 53, 58, 52, 48, 58, 50, 55, 34, 125, 44, 34, 98, 111, 100, 121, 34, 58, 34, 49, 34, 44, 34, 114, 101, 116, 117, 114, 110, 115, 34, 58, 110, 117, 108, 108, 125"; - String[] split = s.split(","); - System.out.println(split.length); - } + 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[] split = s.split(","); + System.out.println(split.length); + } - /** - * 监听端口 - */ - public static final int PORT = 6789; - //public static final int PORT = 9000; + /** + * 监听端口 + */ + public static final int PORT = 6789; + //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 NO_REPLY_TYPE = 2; - public static final int HEARTBEAT_TYPE = 3; + public static final int NEED_REPLY_TYPE = 1; + public static final int NO_REPLY_TYPE = 2; + public static final int HEARTBEAT_TYPE = 3; - public static final Integer REQUEST_TYPE = 1; - public static final Integer RESPONSE_TYPE = 2; + public static final Integer REQUEST_TYPE = 1; + public static final Integer RESPONSE_TYPE = 2; } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/Package.java b/opentcs-common/src/main/java/org/opentcs/kc/common/Package.java index e078b23..0b6bbef 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/Package.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/Package.java @@ -3,43 +3,38 @@ package org.opentcs.kc.common; import java.util.Arrays; -/** - * @Desc: "通用的数据传输底层类" - * @Author: caixiang - * @DATE: 2022/10/18 16:22 - */ public class Package { - private byte[] body; - private String transationId; + private byte[] body; + private String transationId; - public Package(byte[] body, String transationId) { - this.body = body; - this.transationId = transationId; - } + public Package(byte[] body, String transationId) { + this.body = body; + this.transationId = transationId; + } - public byte[] getBody() { - return body; - } + public byte[] getBody() { + return body; + } - public void setBody(byte[] body) { - this.body = body; - } + public void setBody(byte[] body) { + this.body = body; + } - public String getTransationId() { - return transationId; - } + public String getTransationId() { + return transationId; + } - public void setTransationId(String transationId) { - this.transationId = transationId; - } + public void setTransationId(String transationId) { + this.transationId = transationId; + } - @Override - public String toString() { - return "Package{" + - "body=" + Arrays.toString(body) + - ", transationId='" + transationId + '\'' + - '}'; - } + @Override + public String toString() { + return "Package{" + + "body=" + Arrays.toString(body) + + ", transationId='" + transationId + '\'' + + '}'; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/ParseDataException.java b/opentcs-common/src/main/java/org/opentcs/kc/common/ParseDataException.java index 1689b03..eb9b0f8 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/ParseDataException.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/ParseDataException.java @@ -1,64 +1,66 @@ /* -Copyright 2016 S7connector members (github.com/s7connector) - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ + * Copyright 2016 S7connector members (github.com/s7connector) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.opentcs.kc.common; /** * 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. */ - private static final long serialVersionUID = -4761415733559374116L; + /** The Constant serialVersionUID. */ + private static final long serialVersionUID = -4761415733559374116L; - /** - * Instantiates a new s7 exception. - */ - public ParseDataException() { - } + /** + * Instantiates a new s7 exception. + */ + public ParseDataException() { + } - /** - * Instantiates a new s7 exception. - * - * @param message - * the message - */ - public ParseDataException(final String message) { - super(message); - } + /** + * Instantiates a new s7 exception. + * + * @param message + * the message + */ + public ParseDataException(final String message) { + super(message); + } - /** - * Instantiates a new s7 exception. - * - * @param message - * the message - * @param cause - * the cause - */ - public ParseDataException(final String message, final Throwable cause) { - super(message, cause); - } + /** + * Instantiates a new s7 exception. + * + * @param message + * the message + * @param cause + * the cause + */ + public ParseDataException(final String message, final Throwable cause) { + super(message, cause); + } - /** - * Instantiates a new s7 exception. - * - * @param cause - * the cause - */ - public ParseDataException(final Throwable cause) { - super(cause); - } + /** + * Instantiates a new s7 exception. + * + * @param cause + * the cause + */ + public ParseDataException(final Throwable cause) { + super(cause); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/RcvPackage.java b/opentcs-common/src/main/java/org/opentcs/kc/common/RcvPackage.java index a5156d8..e54d76e 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/RcvPackage.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/RcvPackage.java @@ -1,49 +1,44 @@ package org.opentcs.kc.common; -/** - * @Desc: "通用的数据传输底层类" - * @Author: caixiang - * @DATE: 2022/10/18 16:22 - */ public class RcvPackage { - private boolean isOk; - private Object value; - private String content; + private boolean isOk; + private Object value; + private String content; - public RcvPackage(boolean isOk, Object value, String content) { - this.isOk = isOk; - this.value = value; - this.content = content; - } - public RcvPackage() { - } + public RcvPackage(boolean isOk, Object value, String content) { + this.isOk = isOk; + this.value = value; + this.content = content; + } - public boolean isOk() { - return isOk; - } + public RcvPackage() { + } - public void setValue(Object value) { - this.value = value; - } + public boolean isOk() { + return isOk; + } - public Object getValue() { - return value; - } + public void setValue(Object value) { + this.value = value; + } - public String getContent() { - return content; - } + public Object getValue() { + return value; + } + + public String getContent() { + return content; + } - - @Override - public String toString() { - return "RcvPackage{" + - "isOk=" + isOk + - ", value=" + value + - ", content='" + content + '\'' + - '}'; - } + @Override + public String toString() { + return "RcvPackage{" + + "isOk=" + isOk + + ", value=" + value + + ", content='" + content + '\'' + + '}'; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/Utils.java b/opentcs-common/src/main/java/org/opentcs/kc/common/Utils.java index c5557bf..dbee513 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/Utils.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/Utils.java @@ -6,73 +6,60 @@ import java.time.format.DateTimeFormatter; import java.util.Random; import java.util.UUID; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2022/10/24 16:27 - */ public class Utils { - /** - * java生成随机数字15位数 - * @return - */ - public static String getTransationId() { - String val = String.valueOf(System.currentTimeMillis()); - Random random = new Random(); - for (int i = 0; i < 2; i++) { - val += String.valueOf(random.nextInt(10)); - } - return val; + + public static String getTransationId() { + String val = String.valueOf(System.currentTimeMillis()); + Random random = new Random(); + for (int i = 0; i < 2; i++) { + val += String.valueOf(random.nextInt(10)); + } + return val; + } + + /** + * 获取指定长度的随机数 + * (获取指定长度uuid) + * + * @return + */ + public static String getUUID(int len) { + if (0 >= len) { + return null; } - /** - * 获取指定长度的随机数 - * (获取指定长度uuid) - * - * @return - */ - public static String getUUID(int len) - { - if(0 >= len) - { - return null; - } + String uuid = getUUID(); + StringBuffer str = new StringBuffer(); - String uuid = getUUID(); - StringBuffer str = new StringBuffer(); - - for (int i = 0; i < len; i++) - { - str.append(uuid.charAt(i)); - } - - return str.toString(); + for (int i = 0; i < len; i++) { + str.append(uuid.charAt(i)); } - /** - *32位默认长度的uuid - * (获取32位uuid) - * - * @return - */ - public static String getUUID() - { - return UUID.randomUUID().toString().replace("-", ""); + return str.toString(); + } + + /** + * 32位默认长度的uuid + * (获取32位uuid) + * + * @return + */ + 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")); } - - - - - /* - 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")); - } + else { + return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")); } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtil.java b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtil.java index de15900..b3454de 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtil.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtil.java @@ -4,346 +4,356 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2022/4/1 17:32 - */ -//对数字和字节进行转换。 假设数据存储是以大端模式存储的: -// byte: 字节类型 占8位二进制 00000000 -// char: 字符类型 占2个字节 16位二进制 byte[0] byte[1] -// 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] +// 对数字和字节进行转换。 假设数据存储是以大端模式存储的: +// byte: 字节类型 占8位二进制 00000000 +// char: 字符类型 占2个字节 16位二进制 byte[0] byte[1] +// 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 { - /** - * int转byte - * - * @param intValue int值 - * @return byte值 - */ - public static byte intToByte(int intValue) { - return (byte) intValue; + /** + * int转byte + * + * @param intValue int值 + * @return byte值 + */ + public static byte intToByte(int 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
+ * 默认以小端序转换 + * + * @param bytes byte数组 + * @return short值 + */ + public static short bytesToShort(byte[] bytes) { + return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte数组转short
+ * 自定义端序 + * + * @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数组
+ * 默认以小端序转换 + * + * @param shortValue short值 + * @return byte数组 + */ + public static byte[] shortToBytes(short shortValue) { + return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN); + } + + /** + * short转byte数组
+ * 自定义端序 + * + * @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值
+ * 默认以小端序转换 + * + * @param bytes byte数组 + * @return int值 + */ + public static int bytesToInt(byte[] bytes) { + return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN); + } + + /** + * byte[]转int值
+ * 自定义端序 + * + * @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 - * - * @param byteValue byte值 - * @return 无符号int值 - * @since 3.2.0 - */ - public static int byteToUnsignedInt(byte byteValue) { - // Java 总是把 byte 当做有符处理;我们可以通过将其和 0xFF 进行二进制与得到它的无符值 - return byteValue & 0xFF; - } + /** + * int转byte数组
+ * 默认以小端序转换 + * + * @param intValue int值 + * @return byte数组 + */ + public static byte[] intToBytes(int intValue) { + return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN); + } - /** - * - * 字符串转成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(); - } + /** + * int转byte数组
+ * 自定义端序 + * + * @param intValue int值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] intToBytes(int intValue, ByteOrder byteOrder) { - /** - * byte数组转short
- * 默认以小端序转换 - * - * @param bytes byte数组 - * @return short值 - */ - public static short bytesToShort(byte[] bytes) { - return bytesToShort(bytes, ByteOrder.LITTLE_ENDIAN); - } - - /** - * byte数组转short
- * 自定义端序 - * - * @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数组
- * 默认以小端序转换 - * - * @param shortValue short值 - * @return byte数组 - */ - public static byte[] shortToBytes(short shortValue) { - return shortToBytes(shortValue, ByteOrder.LITTLE_ENDIAN); - } - - /** - * short转byte数组
- * 自定义端序 - * - * @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值
- * 默认以小端序转换 - * - * @param bytes byte数组 - * @return int值 - */ - public static int bytesToInt(byte[] bytes) { - return bytesToInt(bytes, ByteOrder.LITTLE_ENDIAN); - } - - /** - * byte[]转int值
- * 自定义端序 - * - * @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; // - } + if (ByteOrder.LITTLE_ENDIAN == byteOrder) { + return new byte[]{ // + (byte) (intValue & 0xFF), // + (byte) ((intValue >> 8) & 0xFF), // + (byte) ((intValue >> 16) & 0xFF), // + (byte) ((intValue >> 24) & 0xFF) // + }; } - - /** - * int转byte数组
- * 默认以小端序转换 - * - * @param intValue int值 - * @return byte数组 - */ - public static byte[] intToBytes(int intValue) { - return intToBytes(intValue, ByteOrder.LITTLE_ENDIAN); + else { + return new byte[]{ // + (byte) ((intValue >> 24) & 0xFF), // + (byte) ((intValue >> 16) & 0xFF), // + (byte) ((intValue >> 8) & 0xFF), // + (byte) (intValue & 0xFF) // + }; } - /** - * int转byte数组
- * 自定义端序 - * - * @param intValue int值 - * @param byteOrder 端序 - * @return byte数组 - */ - public static byte[] intToBytes(int intValue, ByteOrder byteOrder) { + } - if (ByteOrder.LITTLE_ENDIAN == byteOrder) { - return new byte[]{ // - (byte) (intValue & 0xFF), // - (byte) ((intValue >> 8) & 0xFF), // - (byte) ((intValue >> 16) & 0xFF), // - (byte) ((intValue >> 24) & 0xFF) // - }; + /** + * long转byte数组
+ * 默认以小端序转换
+ * 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); + } - } else { - return new byte[]{ // - (byte) ((intValue >> 24) & 0xFF), // - (byte) ((intValue >> 16) & 0xFF), // - (byte) ((intValue >> 8) & 0xFF), // - (byte) (intValue & 0xFF) // - }; - } + /** + * long转byte数组
+ * 自定义端序
+ * from: + * https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @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
+ * 默认以小端序转换
+ * 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
+ * 自定义端序
+ * 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); + } } - /** - * long转byte数组
- * 默认以小端序转换
- * 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); - } + return values; + } - /** - * long转byte数组
- * 自定义端序
- * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java - * - * @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; - } + /** + * double转byte数组
+ * 默认以小端序转换
+ * + * @param doubleValue double值 + * @return byte数组 + */ + public static byte[] doubleToBytes(double doubleValue) { + return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN); + } - /** - * byte数组转long
- * 默认以小端序转换
- * 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); - } + /** + * double转byte数组
+ * 自定义端序
+ * from: + * https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java + * + * @param doubleValue double值 + * @param byteOrder 端序 + * @return byte数组 + */ + public static byte[] doubleToBytes(double doubleValue, ByteOrder byteOrder) { + return longToBytes(Double.doubleToLongBits(doubleValue), byteOrder); + } - /** - * byte数组转long
- * 自定义端序
- * 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); - } - } + /** + * byte数组转Double
+ * 默认以小端序转换
+ * + * @param bytes byte数组 + * @return long值 + */ + public static double bytesToDouble(byte[] bytes) { + return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN); + } - return values; - } + /** + * byte数组转double
+ * 自定义端序
+ * + * @param bytes byte数组 + * @param byteOrder 端序 + * @return long值 + */ + public static double bytesToDouble(byte[] bytes, ByteOrder byteOrder) { + return Double.longBitsToDouble(bytesToLong(bytes, byteOrder)); + } - /** - * double转byte数组
- * 默认以小端序转换
- * - * @param doubleValue double值 - * @return byte数组 - */ - public static byte[] doubleToBytes(double doubleValue) { - return doubleToBytes(doubleValue, ByteOrder.LITTLE_ENDIAN); - } + /** + * 将{@link Number}转换为 + * + * @param number 数字 + * @return bytes + */ + public static byte[] numberToBytes(Number number) { + return numberToBytes(number, ByteOrder.LITTLE_ENDIAN); + } - /** - * double转byte数组
- * 自定义端序
- * from: https://stackoverflow.com/questions/4485128/how-do-i-convert-long-to-byte-and-back-in-java - * - * @param doubleValue double值 - * @param byteOrder 端序 - * @return byte数组 - */ - public static byte[] doubleToBytes(double doubleValue, ByteOrder byteOrder) { - return longToBytes(Double.doubleToLongBits(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); } - - /** - * byte数组转Double
- * 默认以小端序转换
- * - * @param bytes byte数组 - * @return long值 - */ - public static double bytesToDouble(byte[] bytes) { - return bytesToDouble(bytes, ByteOrder.LITTLE_ENDIAN); + else if (number instanceof Long) { + return longToBytes((Long) number, byteOrder); } - - /** - * byte数组转double
- * 自定义端序
- * - * @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 Integer) { + return intToBytes((Integer) number, byteOrder); } - - /** - * 将{@link Number}转换为 - * - * @param number 数字 - * @return bytes - */ - public static byte[] numberToBytes(Number number) { - return numberToBytes(number, ByteOrder.LITTLE_ENDIAN); + else if (number instanceof Short) { + return shortToBytes((Short) number, 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); - } + else { + return doubleToBytes(number.doubleValue(), byteOrder); } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtils.java b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtils.java index 43ad0ea..8a738ef 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtils.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/ByteUtils.java @@ -21,76 +21,81 @@ import java.util.Stack; import org.opentcs.kc.common.ParseDataException; public class ByteUtils { - public static byte[] copyBytes(byte[] src, int start, int length) { - byte[] dest = new byte[length]; - System.arraycopy(src, start, dest, 0, length); - return dest; + public static byte[] copyBytes(byte[] src, int start, int length) { + byte[] dest = new byte[length]; + System.arraycopy(src, start, dest, 0, length); + return dest; + } + + /** + * 将 float 类型的数值按照小端模式转换为字节数组 + * + * @param value 要转换的 float 值 + * @return 转换后的字节数组 + */ + public static byte[] floatToBytes(float value) { + // 先将 float 转换为对应的 32 位整数表示 + int intBits = Float.floatToIntBits(value); + byte[] bytes = new byte[4]; + // 按照小端模式将整数的每一个字节存储到字节数组中 + for (int i = 0; i < 4; i++) { + bytes[i] = (byte) ((intBits >> (i * 8)) & 0xFF); } - /** - * 将 float 类型的数值按照小端模式转换为字节数组 - * @param value 要转换的 float 值 - * @return 转换后的字节数组 - */ - public static byte[] floatToBytes(float value) { - // 先将 float 转换为对应的 32 位整数表示 - int intBits = Float.floatToIntBits(value); - byte[] bytes = new byte[4]; - // 按照小端模式将整数的每一个字节存储到字节数组中 - for (int i = 0; i < 4; i++) { - bytes[i] = (byte) ((intBits >> (i * 8)) & 0xFF); - } - return bytes; + return bytes; + } + + /** + * 将字节数组中从指定偏移位置开始的指定长度的字节转换为字符串 + * + * @param src 字节数组 + * @param offset 起始偏移量 + * @param length 要转换的字节长度 + * @return 转换后的字符串,如果参数不合法则返回空字符串 + */ + public static String bytesToString(byte[] src, int offset, int length) { + // 检查字节数组是否为空 + if (src == null) { + return ""; } - /** - * 将字节数组中从指定偏移位置开始的指定长度的字节转换为字符串 - * @param src 字节数组 - * @param offset 起始偏移量 - * @param length 要转换的字节长度 - * @return 转换后的字符串,如果参数不合法则返回空字符串 - */ - public static String bytesToString(byte[] src, int offset, int length) { - // 检查字节数组是否为空 - if (src == null) { - return ""; - } - // 检查偏移量和长度是否合法 - if (offset < 0 || length < 0 || offset + length > src.length) { - return ""; - } - try { - // 创建一个新的字节数组,用于存储从指定偏移位置开始的指定长度的字节 - byte[] subArray = new byte[length]; - // 从原字节数组中复制指定范围的字节到新数组 - System.arraycopy(src, offset, subArray, 0, length); - // 使用 UTF-8 编码将字节数组转换为字符串 - return new String(subArray, "UTF-8"); - } catch (Exception e) { - e.printStackTrace(); - return ""; - } + // 检查偏移量和长度是否合法 + if (offset < 0 || length < 0 || offset + length > src.length) { + return ""; + } + try { + // 创建一个新的字节数组,用于存储从指定偏移位置开始的指定长度的字节 + byte[] subArray = new byte[length]; + // 从原字节数组中复制指定范围的字节到新数组 + System.arraycopy(src, offset, subArray, 0, length); + // 使用 UTF-8 编码将字节数组转换为字符串 + return new String(subArray, "UTF-8"); + } + catch (Exception e) { + e.printStackTrace(); + return ""; + } + } + + public static double bytesToDouble(byte[] src, int offset) { + // 确保字节数组长度足够 + if (src.length - offset < 8) { + throw new IllegalArgumentException("字节数组长度不足"); } - public static double bytesToDouble(byte[] src, int offset) { - // 确保字节数组长度足够 - if (src.length - offset < 8) { - throw new IllegalArgumentException("字节数组长度不足"); - } + // 使用ByteBuffer并设置为小端模式 + ByteBuffer bb = ByteBuffer.wrap(src, offset, 8).order(ByteOrder.LITTLE_ENDIAN); + // 直接获取double值 + return bb.getDouble(); + } - // 使用ByteBuffer并设置为小端模式 - ByteBuffer bb = ByteBuffer.wrap(src, offset, 8).order(ByteOrder.LITTLE_ENDIAN); - // 直接获取double值 - return bb.getDouble(); - } - - // 将short转换为小端模式的byte数组 - public static byte[] shortToBytes(short intervalTime) { - byte[] bytes = new byte[2]; - // 取低8位 - bytes[0] = (byte) (intervalTime & 0xFF); - // 取高8位 - bytes[1] = (byte) (intervalTime >> 8); - return bytes; - } + // 将short转换为小端模式的byte数组 + public static byte[] shortToBytes(short intervalTime) { + byte[] bytes = new byte[2]; + // 取低8位 + bytes[0] = (byte) (intervalTime & 0xFF); + // 取高8位 + bytes[1] = (byte) (intervalTime >> 8); + return bytes; + } // //2个字节的byte数组 转成short // public static short bytesToShort(byte[] bytes) { // if (bytes == null || bytes.length < 2) { @@ -102,45 +107,46 @@ public class ByteUtils { // return result; // } - public static short bytesToShort(byte[] bytes,int isBigEndian) { - // 确保字节数组长度至少为 2,因为 short 类型是 2 字节 - if (bytes == null || bytes.length < 2) { - throw new IllegalArgumentException("Input byte array must have at least 2 bytes."); - } - // 先将低字节转换为无符号整数,再左移 0 位(实际上不移动) - int lowByte = bytes[0] & 0xFF; - // 将高字节转换为无符号整数,再左移 8 位 - int highByte = (bytes[1] & 0xFF) << 8; - // 将低字节和高字节进行按位或操作得到最终结果,并转换为 short 类型 - return (short) (lowByte | highByte); + public static short bytesToShort(byte[] bytes, int isBigEndian) { + // 确保字节数组长度至少为 2,因为 short 类型是 2 字节 + if (bytes == null || bytes.length < 2) { + throw new IllegalArgumentException("Input byte array must have at least 2 bytes."); + } + // 先将低字节转换为无符号整数,再左移 0 位(实际上不移动) + int lowByte = bytes[0] & 0xFF; + // 将高字节转换为无符号整数,再左移 8 位 + int highByte = (bytes[1] & 0xFF) << 8; + // 将低字节和高字节进行按位或操作得到最终结果,并转换为 short 类型 + return (short) (lowByte | highByte); + } + + /** + * 将字节数组按照小端模式转换为 short 类型 + * + * @param src 字节数组 + * @param offset 起始偏移量 + * @return 转换后的 short 值 + */ + public static short bytesToShortLitt(byte[] src, int offset) { + // 检查字节数组长度是否足够,short 类型占 2 个字节 + if (src.length - offset < 2) { + throw new IllegalArgumentException("字节数组长度不足,无法转换为 short 类型"); + } + // 使用 ByteBuffer 包装字节数组,并设置为小端模式 + ByteBuffer bb = ByteBuffer.wrap(src, offset, 2).order(ByteOrder.LITTLE_ENDIAN); + // 从 ByteBuffer 中获取 short 值 + return bb.getShort(); + } + + + public static double bytes2Double(byte[] arr) { + long value = 0; + for (int i = 0; i < 8; i++) { + value |= ((long) (arr[i] & 0xff)) << (8 * i); } - /** - * 将字节数组按照小端模式转换为 short 类型 - * @param src 字节数组 - * @param offset 起始偏移量 - * @return 转换后的 short 值 - */ - public static short bytesToShortLitt(byte[] src, int offset) { - // 检查字节数组长度是否足够,short 类型占 2 个字节 - if (src.length - offset < 2) { - throw new IllegalArgumentException("字节数组长度不足,无法转换为 short 类型"); - } - // 使用 ByteBuffer 包装字节数组,并设置为小端模式 - ByteBuffer bb = ByteBuffer.wrap(src, offset, 2).order(ByteOrder.LITTLE_ENDIAN); - // 从 ByteBuffer 中获取 short 值 - return bb.getShort(); - } - - - public static double bytes2Double(byte[] arr) { - long value = 0; - for (int i = 0; i < 8; i++) { - value |= ((long) (arr[i] & 0xff)) << (8 * i); - } - - return Double.longBitsToDouble(value); - } + return Double.longBitsToDouble(value); + } // public static Boolean toBoolean(byte[] bytes){ // if(bytes.length ==0){ @@ -153,200 +159,212 @@ public class ByteUtils { // } // } - public static byte[] toByteArrayAndInvert(byte b){ - byte[] arr=new byte[8]; - int len=arr.length; - for(int i=0;i>(len-1-i))&0x1); - } - return invert(arr); + public static byte[] toByteArrayAndInvert(byte b) { + byte[] arr = new byte[8]; + int len = arr.length; + for (int i = 0; i < len; i++) { + arr[i] = (byte) ((b >> (len - 1 - i)) & 0x1); } - public static Boolean toBoolean(byte[] bytes){ - if(bytes.length ==0){ - return null; - } - //只要!=0,那就是大于等于1 ,其实读单个bool变量 ,读取到的byte[] 数组长度都是1. - byte[] byteArrayAndInvert = toByteArrayAndInvert(bytes[0]); - if(byteArrayAndInvert[0] == 1){ - return true; - }else { - return false; - } + return invert(arr); + } + + public static Boolean toBoolean(byte[] bytes) { + if (bytes.length == 0) { + return null; + } + //只要!=0,那就是大于等于1 ,其实读单个bool变量 ,读取到的byte[] 数组长度都是1. + byte[] byteArrayAndInvert = toByteArrayAndInvert(bytes[0]); + if (byteArrayAndInvert[0] == 1) { + return true; + } + else { + return false; + } + } + + public static Boolean toBoolean(byte bytes) { + if (bytes == 1) { + return true; + } + else { + return false; + } + } + + public static String addDate(String timeParam, Long day) { + SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式 + Date date = null; + try { + date = dateFormat.parse(timeParam); // 指定日期 + } + catch (Exception e) { + throw new ParseDataException("ByteUtils.addDate error:", e); } - public static Boolean toBoolean(byte bytes){ - if(bytes == 1){ - return true; - }else { - return false; - } - } - - public static String addDate(String timeParam, Long day) { - SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式 - Date date = null; - try { - date = dateFormat.parse(timeParam); // 指定日期 - }catch (Exception e){ - throw new ParseDataException("ByteUtils.addDate error:", e); - } - - long time = date.getTime(); // 得到指定日期的毫秒数 - day = day * 24 * 60 * 60 * 1000; // 要加上的天数转换成毫秒数 - time += day; // 相加得到新的毫秒数 - Date newDate = new Date(time); - return dateFormat.format(newDate); // 将毫秒数转换成日期 - } + long time = date.getTime(); // 得到指定日期的毫秒数 + day = day * 24 * 60 * 60 * 1000; // 要加上的天数转换成毫秒数 + time += day; // 相加得到新的毫秒数 + Date newDate = new Date(time); + return dateFormat.format(newDate); // 将毫秒数转换成日期 + } - public static byte[] invert(byte[] a){ - byte[] b = new byte[a.length]; - Stack st = new Stack(); - for(int i=0;i st = new Stack(); + for (int i = 0; i < a.length; i++) { + st.push(a[i]); } + for (int i = 0; i < a.length; i++) { + b[i] = st.pop(); + } + return b; + } - /** - * 1个字节byte[] 转成有符号的Integer - * */ - public static Integer toInt(byte bytes) { - return Integer.valueOf(Byte.toString(bytes)); - } - /** - * 1个字节byte[] 转成无符号的Integer - * */ - public static Integer toUInt(byte bytes) { - int i = Byte.toUnsignedInt(bytes); - return Integer.valueOf(i); - } + /** + * 1个字节byte[] 转成有符号的Integer + */ + public static Integer toInt(byte bytes) { + return Integer.valueOf(Byte.toString(bytes)); + } + + /** + * 1个字节byte[] 转成无符号的Integer + */ + public static Integer toUInt(byte bytes) { + int i = Byte.toUnsignedInt(bytes); + return Integer.valueOf(i); + } - /** - * 2个字节byte[] 转成有符号的Integer - * 默认大端 - * */ - public static Integer toInt(byte byte1,byte byte2) { - byte[] bytes = new byte[2]; - bytes[0] = byte1; - bytes[1] = byte2; + /** + * 2个字节byte[] 转成有符号的Integer + * 默认大端 + */ + public static Integer toInt(byte byte1, byte byte2) { + byte[] bytes = new byte[2]; + bytes[0] = byte1; + bytes[1] = byte2; - return Integer.valueOf(Short.toString(ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN))); - } - /** - * 2个字节byte[] 转成无符号的Integer - * 默认大端 - * */ - public static Integer toUInt(byte byte1,byte byte2) { - byte[] bytes = new byte[2]; - bytes[0] = byte1; - bytes[1] = byte2; - short i = ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN); - return Short.toUnsignedInt(i); - } + return Integer.valueOf(Short.toString(ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN))); + } + + /** + * 2个字节byte[] 转成无符号的Integer + * 默认大端 + */ + public static Integer toUInt(byte byte1, byte byte2) { + byte[] bytes = new byte[2]; + bytes[0] = byte1; + bytes[1] = byte2; + short i = ByteUtil.bytesToShort(bytes, ByteOrder.BIG_ENDIAN); + return Short.toUnsignedInt(i); + } - /** - * 4个字节byte[] 转成有符号的Integer - * 默认大端 - * */ - public static Integer toInt(byte byte1,byte byte2,byte byte3,byte byte4) { - byte[] bytes = new byte[4]; - bytes[0] = byte1; - bytes[1] = byte2; - bytes[2] = byte3; - bytes[3] = byte4; - return ByteUtil.bytesToInt(bytes, ByteOrder.BIG_ENDIAN); - } - /** - * 4个字节byte[] 转成无符号的Long(因为如果首位为1 Integer就不满足长度了) - * 默认大端 - * */ - public static Long toUInt(byte byte1,byte byte2,byte byte3,byte byte4) { - byte[] bytes = new byte[8]; - bytes[0] = 0; - bytes[1] = 0; - bytes[2] = 0; - bytes[3] = 0; - bytes[4] = byte1; - bytes[5] = byte2; - bytes[6] = byte3; - bytes[7] = byte4; - long l = ByteUtil.bytesToLong(bytes, ByteOrder.BIG_ENDIAN); - return l; - } + /** + * 4个字节byte[] 转成有符号的Integer + * 默认大端 + */ + public static Integer toInt(byte byte1, byte byte2, byte byte3, byte byte4) { + byte[] bytes = new byte[4]; + bytes[0] = byte1; + bytes[1] = byte2; + bytes[2] = byte3; + bytes[3] = byte4; + return ByteUtil.bytesToInt(bytes, ByteOrder.BIG_ENDIAN); + } - /** - * - * 4个字节byte[] 转成有符号的Double - * 默认大端 - * */ - public static Float forReal(byte[] bytes) { - return Float.intBitsToFloat(toInt(bytes[0],bytes[1],bytes[2],bytes[3])); - } - /** - * - * 8个字节byte[] 转成有符号的Double - * 默认大端 - * */ - public static Double forLReal(byte[] bytes) { - return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN); - } + /** + * 4个字节byte[] 转成无符号的Long(因为如果首位为1 Integer就不满足长度了) + * 默认大端 + */ + public static Long toUInt(byte byte1, byte byte2, byte byte3, byte byte4) { + byte[] bytes = new byte[8]; + bytes[0] = 0; + bytes[1] = 0; + bytes[2] = 0; + bytes[3] = 0; + bytes[4] = byte1; + bytes[5] = byte2; + bytes[6] = byte3; + bytes[7] = byte4; + long l = ByteUtil.bytesToLong(bytes, ByteOrder.BIG_ENDIAN); + return l; + } - /** - * - * 8个字节byte[] 转成有符号的Double - * 默认大端 - * */ - public static Double lrealbytesToDouble(byte[] bytes) { - return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN); + /** + * + * 4个字节byte[] 转成有符号的Double + * 默认大端 + */ + public static Float forReal(byte[] bytes) { + return Float.intBitsToFloat(toInt(bytes[0], bytes[1], bytes[2], bytes[3])); + } + + /** + * + * 8个字节byte[] 转成有符号的Double + * 默认大端 + */ + public static Double forLReal(byte[] bytes) { + return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN); + } + + /** + * + * 8个字节byte[] 转成有符号的Double + * 默认大端 + */ + public static Double lrealbytesToDouble(byte[] bytes) { + return ByteUtil.bytesToDouble(bytes, ByteOrder.BIG_ENDIAN); + } + + public static List toLrealArray(byte[] bytes) { + List list = new ArrayList<>(); + int i = 0; + while (i < bytes.length) { + list.add(ByteBuffer.allocate(8).put(bytes, i, 8).flip().getDouble()); + i += 8; } - public static List toLrealArray(byte[] bytes) { - List list = new ArrayList<>(); - int i=0; - while (i doubleValue) { + List bytes = new ArrayList<>(); + for (Double b : doubleValue) { + byte[] array = ByteBuffer.allocate(8).putDouble(b).array(); + for (int i = 0; i < array.length; i++) { + bytes.add(array[i]); + } } - public static byte[] lrealToBytes(double doubleValue) { - return ByteUtil.doubleToBytes(doubleValue, ByteOrder.BIG_ENDIAN); - //return double2Bytes(doubleValue); - } - public static byte[] lrealArrayToBytes(List doubleValue) { - List bytes = new ArrayList<>(); - for(Double b : doubleValue){ - byte[] array = ByteBuffer.allocate(8).putDouble(b).array(); - for(int i=0;i(b.length-2)){ @@ -370,154 +388,153 @@ public class ByteUtils { // // String s = new String(content); // return ascii; // } - public static String toStr(byte[] b) { - Integer length = Byte.toUnsignedInt(b[1]); - if(length>(b.length-2)){ - return null; - } - List content = new ArrayList<>(); - for(int i=0;i (b.length - 2)) { + return null; } - - public static List toStrArray(byte[] value) { - int cur = 0; - List res= new ArrayList<>(); - while (cur content = new ArrayList<>(); + for (int i = 0; i < length; i++) { + content.add(b[i + 2]); } - - - public static String[] toStrArray(byte[] b,Integer length,Integer strSize) { - String[] res = new String[length]; - strSize+=2; - for(int i=0;i toStrArray(byte[] value) { + int cur = 0; + List res = new ArrayList<>(); + while (cur < value.length) { + Integer length = ByteUtils.toInt(value[cur]) + 2; + byte[] bytes = new byte[length]; + System.arraycopy(value, cur, bytes, 0, length); + cur += length; + res.add(ByteUtils.toStr(bytes)); + } + return res; + } - public static boolean[] getBooleanArray(byte b,boolean returns) { - boolean[] array = new boolean[8]; + public static String[] toStrArray(byte[] b, Integer length, Integer strSize) { + String[] res = new String[length]; + strSize += 2; + for (int i = 0; i < length; i++) { + byte[] one = new byte[strSize]; + System.arraycopy(b, i * strSize, one, 0, strSize); + res[i] = toStr(one); + } + return res; + } - for (int i = 7; i >= 0; i--) { //对于byte的每bit进行判定 + /** + * 将byte转换为一个长度为8的boolean数组(每bit代表一个boolean值) + * + * @param b byte, return(将数组翻转过来) + * @return boolean数组 + */ - array[i] = (b & 1) == 1; //判定byte的最后一位是否为1,若为1,则是true;否则是false + public static boolean[] getBooleanArray(byte b, boolean returns) { - b = (byte) (b >> 1); //将byte右移一位 + boolean[] array = new boolean[8]; - } - if(returns){ - boolean[] array1 = new boolean[8]; - array1[0] = array[7]; - array1[1] = array[6]; - array1[2] = array[5]; - array1[3] = array[4]; - array1[4] = array[3]; - array1[5] = array[2]; - array1[6] = array[1]; - array1[7] = array[0]; - array = array1; - } + for (int i = 7; i >= 0; i--) { //对于byte的每bit进行判定 - return array; + array[i] = (b & 1) == 1; //判定byte的最后一位是否为1,若为1,则是true;否则是false + + b = (byte) (b >> 1); //将byte右移一位 } - /** - * desc : 获取字节 最高位的符号位 - * return - * 负数 true - * 正数 false - */ - public static boolean getByteSignbit(byte b,boolean returns) { - return getBooleanArray(b, false)[0]; + if (returns) { + boolean[] array1 = new boolean[8]; + array1[0] = array[7]; + array1[1] = array[6]; + array1[2] = array[5]; + array1[3] = array[4]; + array1[4] = array[3]; + array1[5] = array[2]; + array1[6] = array[1]; + array1[7] = array[0]; + array = array1; } + return array; - public static Byte fromBooleanArray(boolean[] a) { - byte b = 0; - if (a[7]) - b += 1; - if (a[6]) - b += 2; - if (a[5]) - b += 4; - if (a[4]) - b += 8; - if (a[3]) - b += 16; - if (a[2]) - b += 32; - if (a[1]) - b += 64; - if (a[0]) - b += (byte) 128; - return b; + } + + /** + * desc : 获取字节 最高位的符号位 + * return + * 负数 true + * 正数 false + */ + public static boolean getByteSignbit(byte b, boolean returns) { + return getBooleanArray(b, false)[0]; + } + + + public static Byte fromBooleanArray(boolean[] a) { + byte b = 0; + if (a[7]) + b += 1; + if (a[6]) + b += 2; + if (a[5]) + b += 4; + if (a[4]) + b += 8; + if (a[3]) + b += 16; + if (a[2]) + b += 32; + if (a[1]) + b += 64; + if (a[0]) + b += (byte) 128; + return b; + } + + public static List toBoolArray(byte[] b) { + List res = new ArrayList<>(); + for (int i = 0; i < b.length; i++) { + boolean[] booleanArray = getBooleanArray(b[i], true); + for (int j = 0; j < booleanArray.length; j++) { + res.add(booleanArray[j]); + } + } + return res; + } + + public static List toBoolArray(byte[] b, Integer length) { + List res = new ArrayList<>(); + for (int i = 0; i < length; i++) { + boolean[] booleanArray = getBooleanArray(b[i], true); + for (int j = 0; j < booleanArray.length; j++) { + res.add(booleanArray[j]); + } } - public static List toBoolArray(byte[] b) { - List res = new ArrayList<>(); - for(int i=0;i toBoolArray(byte[] b,Integer length) { - List res = new ArrayList<>(); - for(int i=0;i toBoolArray(byte[] b) throws UnsupportedEncodingException { @@ -528,813 +545,826 @@ public class ByteUtils { // return res; // } - public static List toByteArray(byte[] b) { - List res = new ArrayList<>(); - for(int i=0;i toByteArray(byte[] b) { + List res = new ArrayList<>(); + for (int i = 0; i < b.length; i++) { + res.add((b[i])); + } + return res; + } + + public static List toCharArray(byte[] b) { + List res = new ArrayList<>(); + for (int i = 0; i < b.length; i++) { + res.add(toChar(b[i])); + } + return res; + } + + //toWord + /** + * 默认:word => 有符号的整形 + */ + public static List toWordArray(byte[] b) { + List res = new ArrayList<>(); + int i = 0; + while ((i + 2) <= b.length) { + res.add( + toInt(b[i], b[i + 1]) + ); + i += 2; + } + return res; + } + + //toDWord + /** + * 默认:dword => 有符号的整形 + */ + public static List toDWordArray(byte[] b) { + List res = new ArrayList<>(); + int i = 0; + while ((i + 4) <= b.length) { + res.add( + toInt(b[i], b[i + 1], b[i + 2], b[i + 3]) + ); + i += 4; + } + return res; + } + + /** + * + * 4个字节byte[] 转成有符号的Double + * 默认大端 + */ + public static Float realbytesToFloat(byte[] bytes) { + + return Float.intBitsToFloat(toInt(bytes[0], bytes[1], bytes[2], bytes[3])); + } + + public static List toRealArray(byte[] bytes) { + List res = new ArrayList<>(); + int i = 0; + while (i < bytes.length) { + res.add(ByteBuffer.allocate(4).put(bytes, i, 4).flip().getFloat()); + i += 4; + } + return res; + } + + + public static byte[] realToBytes(Float f) { + return invert(float2byte(f)); + } + + public static byte[] realArrayToBytes(List list) { + List res = new ArrayList<>(); + for (Float f : list) { + byte[] invert = invert(float2byte(f)); + for (int j = 0; j < invert.length; j++) { + res.add(invert[j]); + } + } + byte[] bytes = new byte[res.size()]; + for (int i = 0; i < res.size(); i++) { + bytes[i] = res.get(i); + } + return bytes; + } + + /** + * 浮点转换为字节 + * + * @param f + * @return + */ + private static byte[] float2byte(float f) { + + // 把float转换为byte[] + int fbit = Float.floatToIntBits(f); + + byte[] b = new byte[4]; + for (int i = 0; i < 4; i++) { + b[i] = (byte) (fbit >> (24 - i * 8)); } - public static List toCharArray(byte[] b) { - List res = new ArrayList<>(); - for(int i=0;i 有符号的整形 - * */ - public static List toWordArray(byte[] b) { - List res = new ArrayList<>(); - int i=0; - while ((i+2)<=b.length){ - res.add( - toInt(b[i],b[i+1]) - ); - i+=2; - } - return res; + return dest; + + } + + //toUInt + /** + * USInt 无符号整形 1个字节 =》 Integer + */ + public static List toUSIntArray(byte[] b) { + List res = new ArrayList<>(); + for (int i = 0; i < b.length; i++) { + res.add(toUInt(b[i])); + } + return res; + } + + /** + * UInt 无符号整形 2个字节 =》 Integer + */ + public static List toUIntArray(byte[] b) { + List res = new ArrayList<>(); + int i = 0; + while ((i + 2) <= b.length) { + res.add( + toUInt(b[i], b[i + 1]) + ); + i += 2; + } + return res; + } + + /** + * UDInt 无符号整形 4个字节 =》 Long + */ + public static List toUDIntArray(byte[] b) { + List res = new ArrayList<>(); + int i = 0; + while ((i + 4) <= b.length) { + res.add( + toUInt(b[i], b[i + 1], b[i + 2], b[i + 3]) + ); + i += 4; + } + return res; + } + + /** + * SInt 无符号整形 1个字节 =》 Integer + */ + public static List toSIntArray(byte[] b) { + List res = new ArrayList<>(); + for (int i = 0; i < b.length; i++) { + res.add(toInt(b[i])); + } + return res; + } + + /** + * Int 无符号整形 2个字节 =》 Integer + */ + public static List toIntArray(byte[] b) { + List res = new ArrayList<>(); + int i = 0; + while ((i + 2) <= b.length) { + res.add( + toInt(b[i], b[i + 1]) + ); + i += 2; + } + return res; + } + + /** + * DInt 无符号整形 4个字节 =》 Integer + */ + public static List toDIntArray(byte[] b) { + List res = new ArrayList<>(); + int i = 0; + while ((i + 4) <= b.length) { + res.add( + toInt(b[i], b[i + 1], b[i + 2], b[i + 3]) + ); + i += 4; + } + return res; + } + + /** + * sint(1个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] sintToBytes(Integer i) { + byte[] res = new byte[1]; + res[0] = Byte.valueOf(i.toString()); + return res; + } + + /** + * sintArray(1个字节) =》 byte[] + * + */ + public static byte[] sintArrayToBytes(int[] sintArray) { + byte[] res = new byte[sintArray.length]; + for (int i = 0; i < sintArray.length; i++) { + int i1 = sintArray[i]; + res[i] = sintToBytes(i1)[0]; + } + return res; + } + + /** + * int(2个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] intToBytes(Integer i) { + Number shortNumber = Short.valueOf(i.toString()); + return ByteUtil.numberToBytes(shortNumber, ByteOrder.BIG_ENDIAN); + } + + public static byte[] intToBytesS(Integer i) { + Number shortNumber = Short.valueOf(i.toString()); + return ByteUtil.numberToBytes(shortNumber, ByteOrder.LITTLE_ENDIAN); + } + + // 将 int 类型数据以小端模式转换为 byte 数组,转成4个字节的 byte[] + public static byte[] intToBytes(int intervalTime, int byteLength) { + byte[] bytes = new byte[4]; + // 取最低 8 位 + bytes[0] = (byte) (intervalTime & 0xFF); + // 右移 8 位后取 8 位 + bytes[1] = (byte) ((intervalTime >> 8) & 0xFF); + // 右移 16 位后取 8 位 + bytes[2] = (byte) ((intervalTime >> 16) & 0xFF); + // 右移 24 位后取 8 位 + bytes[3] = (byte) ((intervalTime >> 24) & 0xFF); + return bytes; + } + + + /** + * intArray(2个字节) =》 byte[] + */ + public static byte[] intArrayToBytes(int[] intArray) { + byte[] res = new byte[intArray.length * 2]; + for (int i = 0; i < intArray.length; i++) { + byte[] bytes = intToBytes(intArray[i]); + res[i * 2] = bytes[0]; + res[i * 2 + 1] = bytes[1]; + } + return res; + } + + /** + * int(2个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] dintToBytes(Integer i) { + Number intNumber = i; + return ByteUtil.numberToBytes(intNumber, ByteOrder.BIG_ENDIAN); + } + + /** + * intArray(2个字节) =》 byte[] + */ + public static byte[] dintArrayToBytes(int[] dintArray) { + byte[] res = new byte[dintArray.length * 4]; + for (int i = 0; i < dintArray.length; i++) { + byte[] bytes = dintToBytes(dintArray[i]); + res[i * 4] = bytes[0]; + res[i * 4 + 1] = bytes[1]; + res[i * 4 + 2] = bytes[2]; + res[i * 4 + 3] = bytes[3]; + + } + return res; + } + + /** + * sint(1个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] usintToBytes(Integer i) { + if (i < 0) { + return null; + } + byte[] res = new byte[1]; + res[0] = Byte.valueOf(i.toString()); + return res; + } + + public static byte usintTo1Byte(Integer i) { + if (i < 0 || i >= 256) { + return 0x00; + } + return Byte.valueOf(i.toString()); + } + + /** + * usintArrayToBytes =》 byte[] + * 默认大端模式 + */ + public static byte[] usintArrayToBytes(int[] usintArray) { + byte[] res = new byte[usintArray.length]; + for (int i = 0; i < usintArray.length; i++) { + byte[] bytes = usintToBytes(usintArray[i]); + if (bytes == null) { + return null; + } + res[i] = bytes[0]; + } + return res; + } + + + /** + * int(2个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] uintToBytes(Integer i) { + if (i < 0) { + return null; + } + Number shortNumber = Short.valueOf(i.toString()); + return ByteUtil.numberToBytes(shortNumber, ByteOrder.BIG_ENDIAN); + } + + public static byte[] uintToBytes(Integer value, ByteOrder byteOrder) { + if (byteOrder == ByteOrder.BIG_ENDIAN) { + ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); + buffer.putInt(value); + return buffer.array(); + } + else { + ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); + buffer.putInt(value); + return buffer.array(); + } + } + + + public static byte[] uintArrayToBytes(int[] uintArray) { + byte[] res = new byte[uintArray.length * 2]; + for (int i = 0; i < uintArray.length; i++) { + byte[] bytes = uintToBytes(uintArray[i]); + if (bytes == null) { + return null; + } + res[i * 2] = bytes[0]; + res[i * 2 + 1] = bytes[1]; + } + return res; + } + + /** + * int(2个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] udintToBytes(Integer i) { + if (i < 0) { + return null; + } + Number intNumber = i; + return ByteUtil.numberToBytes(intNumber, ByteOrder.BIG_ENDIAN); + } + + /** + * long(8个字节) =》 byte[] + * 默认大端模式 + */ + public static byte[] longToBytes(Long i) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); + buffer.putLong(i); + byte[] array = buffer.array(); + return array; + } + + public static byte[] longArrayToBytes(List longs) { + ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES * longs.size()); + for (Long i : longs) { + buffer.putLong(i); + } + byte[] array = buffer.array(); + return array; + } + + public static Long toLong(byte[] input, int offset, boolean littleEndian) { + // 将byte[] 封装为 ByteBuffer + ByteBuffer buffer = ByteBuffer.wrap(input, offset, 8); + if (littleEndian) { + // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN) + // ByteBuffer 默认为大端(BIG_ENDIAN)模式 + buffer.order(ByteOrder.LITTLE_ENDIAN); + } + return buffer.getLong(); + } + + /** + * @param source 来源 + * @param littleEndian 输入数组是否小端模式 + */ + public static List toLongArray(byte[] source, boolean littleEndian) { + List res = new ArrayList<>(); + + int fortimes = source.length / 8; + for (int i = 0; i < fortimes; i++) { + ByteBuffer buffer = ByteBuffer.wrap(source, i * 8, 8); + if (littleEndian) { + // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN) + // ByteBuffer 默认为大端(BIG_ENDIAN)模式 + buffer.order(ByteOrder.LITTLE_ENDIAN); + } + res.add(buffer.getLong()); + } + return res; + } + + + public static byte[] udintArrayToBytes(int[] udintArray) { + byte[] res = new byte[udintArray.length * 4]; + for (int i = 0; i < udintArray.length; i++) { + byte[] bytes = udintToBytes(udintArray[i]); + if (bytes == null) { + return null; + } + res[i * 4] = bytes[0]; + res[i * 4 + 1] = bytes[1]; + res[i * 4 + 2] = bytes[2]; + res[i * 4 + 3] = bytes[3]; + } + return res; + } + + /** + * boolean =》 byte[] + * 默认大端模式 + */ + public static byte[] boolToBytes(Boolean bool) { + byte[] res = new byte[2]; + //之所以这样是为了撑大 newValue数组,,因为 modbus tcp 最小单元 就是1个word(2 byte). + res[1] = 0x00; + if (bool) { + res[0] = 1; + return res; + } + else { + res[0] = 0; + return res; + } + } + + /** + * booleanArray =》 byte[] + */ + public static byte[] booleanArrayToBytes(boolean[] boolArray) { + byte[] res = new byte[boolArray.length]; + for (int i = 0; i < boolArray.length; i++) { + boolean b = boolArray[i]; + if (b) { + res[i] = 1; + } + else { + res[i] = 0; + } + } + return res; + } + + public static byte[] toByteArray(boolean[] b) { + Integer byteLength = CommonFunctions.exactDivision(b.length, 8); + byte[] res = new byte[byteLength]; + Queue queue = new LinkedList(); + for (int i = 0; i < b.length; i++) { + queue.add(b[i]); } - //toDWord - /** - * 默认:dword => 有符号的整形 - * */ - public static List toDWordArray(byte[] b) { - List res = new ArrayList<>(); - int i=0; - while ((i+4)<=b.length){ - res.add( - toInt(b[i],b[i+1],b[i+2],b[i+3]) - ); - i+=4; - } - return res; - } - /** - * - * 4个字节byte[] 转成有符号的Double - * 默认大端 - * */ - public static Float realbytesToFloat(byte[] bytes) { + //todo + int z = 0; + Integer boolLength = queue.size(); + while (boolLength > 0) { + boolean[] input = new boolean[8]; - return Float.intBitsToFloat(toInt(bytes[0],bytes[1],bytes[2],bytes[3])); - } - public static List toRealArray(byte[] bytes) { - List res = new ArrayList<>(); - int i=0; - while (i list) { - List res = new ArrayList<>(); - for(Float f : list){ - byte[] invert = invert(float2byte(f)); - for(int j=0;j> (24 - i * 8)); + if (boolLength >= 8) { + for (int i = 0; i < 8; i++) { + input[i] = queue.poll(); } - // 翻转数组 - int len = b.length; - // 建立一个与源数组元素类型相同的数组 - byte[] dest = new byte[len]; - // 为了防止修改源数组,将源数组拷贝一份副本 - System.arraycopy(b, 0, dest, 0, len); - byte temp; - // 将顺位第i个与倒数第i个交换 - for (int i = 0; i < len / 2; ++i) { - temp = dest[i]; - dest[i] = dest[len - i - 1]; - dest[len - i - 1] = temp; + + Byte aByte = fromBooleanArray(reverse(input)); + res[z] = aByte; + z++; + } + else { + for (int i = 0; i < boolLength; i++) { + input[i] = queue.poll(); } - - return dest; - + Byte aByte = fromBooleanArray(reverse(input)); + res[z] = aByte; + z++; + } + boolLength = boolLength - 8; } + return res; + } - //toUInt - /** - * USInt 无符号整形 1个字节 =》 Integer - * */ - public static List toUSIntArray(byte[] b) { - List res = new ArrayList<>(); - for(int i=0;i toUIntArray(byte[] b) { - List res = new ArrayList<>(); - int i=0; - while ((i+2)<=b.length){ - res.add( - toUInt(b[i],b[i+1]) - ); - i+=2; - } - return res; - } - /** - * UDInt 无符号整形 4个字节 =》 Long - * */ - public static List toUDIntArray(byte[] b) { - List res = new ArrayList<>(); - int i=0; - while ((i+4)<=b.length){ - res.add( - toUInt(b[i],b[i+1],b[i+2],b[i+3]) - ); - i+=4; - } - return res; - } - - /** - * SInt 无符号整形 1个字节 =》 Integer - * */ - public static List toSIntArray(byte[] b) { - List res = new ArrayList<>(); - for(int i=0;i toIntArray(byte[] b) { - List res = new ArrayList<>(); - int i=0; - while ((i+2)<=b.length){ - res.add( - toInt(b[i],b[i+1]) - ); - i+=2; - } - return res; - } - /** - * DInt 无符号整形 4个字节 =》 Integer - * */ - public static List toDIntArray(byte[] b) { - List res = new ArrayList<>(); - int i=0; - while ((i+4)<=b.length){ - res.add( - toInt(b[i],b[i+1],b[i+2],b[i+3]) - ); - i+=4; - } - return res; - } - - /** - * sint(1个字节) =》 byte[] - * 默认大端模式 - * */ - public static byte[] sintToBytes(Integer i){ - byte[] res = new byte[1]; - res[0] = Byte.valueOf(i.toString()); - return res; - } - /** - * sintArray(1个字节) =》 byte[] - * - * */ - public static byte[] sintArrayToBytes(int[] sintArray) { - byte[] res = new byte[sintArray.length]; - for(int i=0;i> 8) & 0xFF); - // 右移 16 位后取 8 位 - bytes[2] = (byte) ((intervalTime >> 16) & 0xFF); - // 右移 24 位后取 8 位 - bytes[3] = (byte) ((intervalTime >> 24) & 0xFF); - return bytes; + /** + * charArray =》 byte[] + */ + public static byte[] charArrayToBytes(char[] charArray) { + byte[] res = new byte[charArray.length]; + for (int i = 0; i < charArray.length; i++) { + byte[] bytes = charToByte(charArray[i]); + if (bytes[0] != 0) { + return null; + } + else { + res[i] = bytes[1]; + } } + return res; + } - - /** - * intArray(2个字节) =》 byte[] - * */ - public static byte[] intArrayToBytes(int[] intArray) { - byte[] res = new byte[intArray.length*2]; - for(int i=0 ; i< intArray.length ; i++){ - byte[] bytes = intToBytes(intArray[i]); - res[i*2] = bytes[0]; - res[i*2+1] = bytes[1]; - } - return res; - } - - /** - * int(2个字节) =》 byte[] - * 默认大端模式 - * */ - public static byte[] dintToBytes(Integer i) { - Number intNumber = i; - return ByteUtil.numberToBytes(intNumber,ByteOrder.BIG_ENDIAN); - } - - /** - * intArray(2个字节) =》 byte[] - * */ - public static byte[] dintArrayToBytes(int[] dintArray) { - byte[] res = new byte[dintArray.length*4]; - for(int i=0 ; i< dintArray.length ; i++){ - byte[] bytes = dintToBytes(dintArray[i]); - res[i*4] = bytes[0]; - res[i*4+1] = bytes[1]; - res[i*4+2] = bytes[2]; - res[i*4+3] = bytes[3]; - - } - return res; - } - - /** - * sint(1个字节) =》 byte[] - * 默认大端模式 - * */ - public static byte[] usintToBytes(Integer i){ - if(i<0){ - return null; - } - byte[] res = new byte[1]; - res[0] = Byte.valueOf(i.toString()); - return res; - } - public static byte usintTo1Byte(Integer i){ - if(i<0 || i>=256){ - return 0x00; - } - return Byte.valueOf(i.toString()); - } - - /** - * usintArrayToBytes =》 byte[] - * 默认大端模式 - * */ - public static byte[] usintArrayToBytes(int[] usintArray) { - byte[] res = new byte[usintArray.length]; - for(int i=0 ; i< usintArray.length ; i++){ - byte[] bytes = usintToBytes(usintArray[i]); - if(bytes == null){ - return null; - } - res[i] = bytes[0]; - } - return res; - } - - - /** - * int(2个字节) =》 byte[] - * 默认大端模式 - * */ - public static byte[] uintToBytes(Integer i) { - if(i<0){ - return null; - } - Number shortNumber = Short.valueOf(i.toString()); - return ByteUtil.numberToBytes(shortNumber,ByteOrder.BIG_ENDIAN); - } - - public static byte[] uintToBytes(Integer value, ByteOrder byteOrder) { - if (byteOrder == ByteOrder.BIG_ENDIAN) { - ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.BIG_ENDIAN); - buffer.putInt(value); - return buffer.array(); - }else { - ByteBuffer buffer = ByteBuffer.allocate(4).order(ByteOrder.LITTLE_ENDIAN); - buffer.putInt(value); - return buffer.array(); - } - } - - - public static byte[] uintArrayToBytes(int[] uintArray) { - byte[] res = new byte[uintArray.length*2]; - for(int i=0 ; i< uintArray.length ; i++){ - byte[] bytes = uintToBytes(uintArray[i]); - if(bytes == null){ - return null; - } - res[i*2] = bytes[0]; - res[i*2+1] = bytes[1]; - } - return res; - } - - /** - * int(2个字节) =》 byte[] - * 默认大端模式 - * */ - public static byte[] udintToBytes(Integer i) { - if(i<0){ - return null; - } - Number intNumber = i; - return ByteUtil.numberToBytes(intNumber,ByteOrder.BIG_ENDIAN); - } - - /** - * long(8个字节) =》 byte[] - * 默认大端模式 - * */ - public static byte[] longToBytes(Long i) { - ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES); - buffer.putLong(i); - byte[] array = buffer.array(); - return array; - } - public static byte[] longArrayToBytes(List longs) { - ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES*longs.size()); - for(Long i:longs){ - buffer.putLong(i); - } - byte[] array = buffer.array(); - return array; - } - - public static Long toLong(byte[] input, int offset, boolean littleEndian) { - // 将byte[] 封装为 ByteBuffer - ByteBuffer buffer = ByteBuffer.wrap(input,offset,8); - if(littleEndian){ - // ByteBuffer.order(ByteOrder) 方法指定字节序,即大小端模式(BIG_ENDIAN/LITTLE_ENDIAN) - // ByteBuffer 默认为大端(BIG_ENDIAN)模式 - buffer.order(ByteOrder.LITTLE_ENDIAN); - } - return buffer.getLong(); - } - /** - * byte[] ==> List(8个字节) - * @param source - * @param littleEndian 输入数组是否小端模式 - * @return - */ - public static List toLongArray(byte[] source, boolean littleEndian) { - List res = new ArrayList<>(); - - int fortimes = source.length/8; - for(int i=0;i queue = new LinkedList(); - for(int i=0;i0){ - boolean[] input = new boolean[8]; - - if(boolLength>=8){ - for(int i = 0;i<8;i++){ - input[i]= queue.poll(); - } - - - Byte aByte = fromBooleanArray(reverse(input)); - res[z] = aByte; - z++; - }else { - for(int i=0;i strList) { + List byteList = new ArrayList<>(); + for (String s : strList) { + byte[] bytes = strToBytes(s); + for (int i = 0; i < bytes.length; i++) { + byteList.add(bytes[i]); + } } - - /** - * dwordArray =》 byte[] - * */ - public static byte[] dwordArrayToBytes(int[] intArray) { - byte[] res = new byte[intArray.length*4]; - for(int i=0 ; i< intArray.length ; i++){ - byte[] bytes = dwordToBytes(intArray[i]); - res[i*4] = bytes[0]; - res[i*4+1] = bytes[1]; - res[i*4+2] = bytes[2]; - res[i*4+3] = bytes[3]; - } - return res; + byte[] res = new byte[byteList.size()]; + for (int i = 0; i < byteList.size(); i++) { + res[i] = byteList.get(i); } + return res; + } - /** - * char(1字节) =》 byte[] - * - * */ - public static byte[] charToBytes(Character c) { - return String.valueOf(c).getBytes(); + + /** + * 将字符串转换为指定字节长度的字节数组 + * + * @param strValue 待转换的字符串 + * @param byteSize 指定的字节长度 + * @return 转换后的字节数组 + */ + public static byte[] stringToBytes(String strValue, int byteSize) { + // 如果输入的字符串为 null,将其转换为空字符串 + if (strValue == null) { + strValue = ""; } - public static byte[] wcharToBytes(Character c) { - return charToByte(c); + // 将字符串转换为字节数组,使用 UTF-8 编码 + byte[] originalBytes = strValue.getBytes(); + // 创建一个指定长度的字节数组,初始值都为 0 + byte[] result = new byte[byteSize]; + + // 计算需要复制的字节数,取原字节数组长度和指定长度的较小值 + int lengthToCopy = Math.min(originalBytes.length, byteSize); + // 将原字节数组的内容复制到结果数组中 + System.arraycopy(originalBytes, 0, result, 0, lengthToCopy); + + return result; + } + + /** + * desc + * 入参: + * 一般来说 plc中 string变量都是会设置 长度的,如 var1 = String[18],这里的strSize就是18 + * 返回: + * 返回的字节流是包含2个头字节的,也就是 strSize+2 个长度的字节流。 + */ + public static byte[] strToBytes(String s, Integer strSize) { + if (s == null || (strSize <= 0)) { + return null; } - - //如果plc中没有设置 strSize,那么 这个字符串变量的 最大长度默认是 254(字节就是-2 ) - /** - * 这个函数就用于 非str类型转bytes使用,string类型转bytes 用strToBytes(String s,Integer strSize) 这个方法。 - * */ - public static byte[] strToBytes(String s) { - byte[] bytes = s.getBytes(StandardCharsets.UTF_8); - byte[] res = new byte[bytes.length+2]; - res[0] = -2; - res[1] = Integer.valueOf(bytes.length).byteValue(); - for(int i=0;i strSize) { + res[1] = strSize.byteValue(); + for (int i = 0; i < strSize; i++) { + res[i + 2] = bytes[i]; + } } - public static byte[] strArrayToBytes(List strList) { - List byteList = new ArrayList<>(); - for(String s : strList){ - byte[] bytes = strToBytes(s); - for (int i = 0; i < bytes.length; i++) { - byteList.add(bytes[i]); - } - } - byte[] res = new byte[byteList.size()]; - for(int i=0;istrSize){ - res[1] = strSize.byteValue(); - for(int i=0;i 0) { + a += 1; } + return intToBytes(a); + } + public static void main(String[] args) { + long i = 23288; + byte[] bytes = longToBytes(i); + long l = toLong(bytes, 0, false); + List longs = new ArrayList<>(); + longs.add(1l); + longs.add(23288l); + longs.add(-3l); + byte[] bytes1 = longArrayToBytes(longs); + List longs1 = toLongArray(bytes1, false); + System.out.println(Arrays.asList(bytes)); + System.out.println(Arrays.asList(bytes1)); + } - //取余 - public static byte[] remainders(Integer i){ - int a = i/2; - int z = i%2; - if(z==1){ - a+=1; - } - return intToBytes(a); - } - public static byte[] remainderForBool(Integer i){ - int a = i/16; - int z = i%16; - if(z > 0){ - a+=1; - } - return intToBytes(a); - } - - public static void main(String[] args) { - long i = 23288; - byte[] bytes = longToBytes(i); - long l = toLong(bytes, 0, false); - List longs = new ArrayList<>(); - longs.add(1l); - longs.add(23288l); - longs.add(-3l); - byte[] bytes1 = longArrayToBytes(longs); - List longs1 = toLongArray(bytes1, false); - System.out.println(Arrays.asList(bytes)); - System.out.println(Arrays.asList(bytes1)); - } - - /** - * 参数 - * desc : 把字符串数组 ==> byte[] [x,x,..,..,..,..,... x,x,..,..,..,..,... ...] - * array : 就是需要被写入plc的内容,, array.length 就是你要写入数组的长度。 注意array.length必须小于plc中设置的 “数组变量” length - * strSize : 就是数组中某个变量的长度 比如 String str = new String[18] 这里的18就是strSize,但是在博图偏移量地址上可以发现它已经把你+2了,就是你设置最大string长度18 但偏移量=18+2=20;; - * 而上面的array.length是 List list = new ArrayList<>; 的list.length - * 返回 - * byte[] 就是整个数组字符串的 总的字节流 - * - * */ - public static byte[] strArrayToBytes(String[] array,Integer strSize) { - //str0 [18, 17, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53] - //str1 [18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 49] - //str2 [18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 50] - - //list [18, 17, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 0, 18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 49, 18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 50] - //strSize+2 以后就是 实际plc 变量的字节数了。 - Integer allStrSize = strSize+2; - byte[] res = new byte[array.length*allStrSize]; - for(int i=0;i byte[] [x,x,..,..,..,..,... x,x,..,..,..,..,... ...] + * array : 就是需要被写入plc的内容,, array.length 就是你要写入数组的长度。 注意array.length必须小于plc中设置的 “数组变量” length + * strSize : 就是数组中某个变量的长度 比如 String str = new String[18] + * 这里的18就是strSize,但是在博图偏移量地址上可以发现它已经把你+2了,就是你设置最大string长度18 但偏移量=18+2=20;; + */ + public static byte[] strArrayToBytes(String[] array, Integer strSize) { + //str0 [18, 17, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53] + //str1 [18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 49] + //str2 [18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 50] + + //list [18, 17, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 0, 18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 49, 18, 18, 51, 48, 49, 49, 48, 48, 49, 50, 49, 48, 53, 51, 48, 49, 49, 49, 53, 50] + //strSize+2 以后就是 实际plc 变量的字节数了。 + Integer allStrSize = strSize + 2; + byte[] res = new byte[array.length * allStrSize]; + for (int i = 0; i < array.length; i++) { + byte[] bytes = strToBytes(array[i], strSize); + System.arraycopy(bytes, 0, res, i * allStrSize, bytes.length); } + return res; + } + //for private - //for private + private static byte[] charToByte(char c) { + byte[] b = new byte[2]; + b[0] = (byte) ((c & 0xFF00) >> 8); + b[1] = (byte) (c & 0xFF); + return b; + } - private static byte[] charToByte(char c) { - byte[] b = new byte[2]; - b[0] = (byte) ((c & 0xFF00) >> 8); - b[1] = (byte) (c & 0xFF); - return b; - } - private static char byteToChar(byte[] b) { - char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF)); - return c; - } - private static char byteToChar(byte b) { - char c = (char) (b & 0xFF); - return c; - } + private static char byteToChar(byte[] b) { + char c = (char) (((b[0] & 0xFF) << 8) | (b[1] & 0xFF)); + return c; + } - /** - * 4个字节 ==> float,小端模式 - * */ - public static float bytesToFloat(byte[] src, int offset) { + private static char byteToChar(byte b) { + char c = (char) (b & 0xFF); + return c; + } + + /** + * 4个字节 ==> float,小端模式 + */ + public static float bytesToFloat(byte[] src, int offset) { // int i = ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF); // return Float.intBitsToFloat(i); - // 使用ByteBuffer,指定字节序为小端 - ByteBuffer buffer = ByteBuffer.wrap(src, offset, 4).order(ByteOrder.LITTLE_ENDIAN); - // 从ByteBuffer中读取float值 - return buffer.getFloat(); + // 使用ByteBuffer,指定字节序为小端 + ByteBuffer buffer = ByteBuffer.wrap(src, offset, 4).order(ByteOrder.LITTLE_ENDIAN); + // 从ByteBuffer中读取float值 + return buffer.getFloat(); + } + + /** + * 4个字节 ==> int,小端模式 + */ + public static int bytesToInt(byte[] src, int offset) { + //return ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF); + + // 将字节数组包装到 ByteBuffer 中 + ByteBuffer buffer = ByteBuffer.wrap(src, offset, 4); + // 设置字节序为小端模式 + buffer.order(ByteOrder.LITTLE_ENDIAN); + // 从 ByteBuffer 中读取 int 值 + return buffer.getInt(); + } + + public static byte[] copyOfRange(byte[] src, int from, int to) { + if (src == null) { + throw new IllegalArgumentException("src cannot be null"); + } + if (from < 0 || from > src.length) { + throw new IllegalArgumentException("from index is out of range"); + } + if (to < 0 || to > src.length) { + throw new IllegalArgumentException("to index is out of range"); + } + if (from > to) { + throw new IllegalArgumentException("from index cannot be greater than to index"); } - /** - * 4个字节 ==> int,小端模式 - * */ - public static int bytesToInt(byte[] src, int offset) { - //return ((src[offset] & 0xFF) << 24) | ((src[offset + 1] & 0xFF) << 16) | ((src[offset + 2] & 0xFF) << 8) | (src[offset + 3] & 0xFF); - - // 将字节数组包装到 ByteBuffer 中 - ByteBuffer buffer = ByteBuffer.wrap(src, offset, 4); - // 设置字节序为小端模式 - buffer.order(ByteOrder.LITTLE_ENDIAN); - // 从 ByteBuffer 中读取 int 值 - return buffer.getInt(); - } - - public static byte[] copyOfRange(byte[] src, int from, int to) { - if (src == null) { - throw new IllegalArgumentException("src cannot be null"); - } - if (from < 0 || from > src.length) { - throw new IllegalArgumentException("from index is out of range"); - } - if (to < 0 || to > src.length) { - throw new IllegalArgumentException("to index is out of range"); - } - if (from > to) { - throw new IllegalArgumentException("from index cannot be greater than to index"); - } - - int newLength = to - from; - byte[] dest = new byte[newLength]; - System.arraycopy(src, from, dest, 0, newLength); - return dest; - } + int newLength = to - from; + byte[] dest = new byte[newLength]; + System.arraycopy(src, from, dest, 0, newLength); + return dest; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/CommonFunctions.java b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/CommonFunctions.java index 4f41225..20ba5a7 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/CommonFunctions.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/CommonFunctions.java @@ -1,21 +1,16 @@ package org.opentcs.kc.common.byteutils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2022/12/5 11:11 - */ public class CommonFunctions { - /** - * a 整除 b ,如果有余数+1 - * */ - public static Integer exactDivision(Integer a,Integer b) { + /** + * a 整除 b ,如果有余数+1 + */ + public static Integer exactDivision(Integer a, Integer b) { - int c = a/b; + int c = a / b; - if(a%b!=0){ - c = a/b+1; - } - return c; + if (a % b != 0) { + c = a / b + 1; } + return c; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/StringArrayStruc.java b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/StringArrayStruc.java index 174b2f4..d22faa1 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/StringArrayStruc.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/byteutils/StringArrayStruc.java @@ -1,32 +1,27 @@ package org.opentcs.kc.common.byteutils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024-05-08 11:02 - */ public class StringArrayStruc { - private String[] content; - private Integer strSize; + private String[] content; + private Integer strSize; - public StringArrayStruc(String[] content, Integer strSize) { - this.content = content; - this.strSize = strSize; - } + public StringArrayStruc(String[] content, Integer strSize) { + this.content = content; + this.strSize = strSize; + } - public String[] getContent() { - return content; - } + public String[] getContent() { + return content; + } - public void setContent(String[] content) { - this.content = content; - } + public void setContent(String[] content) { + this.content = content; + } - public Integer getStrSize() { - return strSize; - } + public Integer getStrSize() { + return strSize; + } - public void setStrSize(Integer strSize) { - this.strSize = strSize; - } + public void setStrSize(Integer strSize) { + this.strSize = strSize; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/common/enmuc/ModbusFC.java b/opentcs-common/src/main/java/org/opentcs/kc/common/enmuc/ModbusFC.java index b7a5072..be3e472 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/common/enmuc/ModbusFC.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/common/enmuc/ModbusFC.java @@ -1,34 +1,34 @@ package org.opentcs.kc.common.enmuc; public enum ModbusFC { - //心跳变量(这个可以要求电控同事加一个,不和业务关联,只用于通讯) - MB_HOLD_REG((byte) 0x03, (byte) 0x10), - Q_OUT((byte) 0x01, (byte) 0x05), - I_IN((byte) 0x02, null), - IW_IN((byte) 0x04, null), - ; + //心跳变量(这个可以要求电控同事加一个,不和业务关联,只用于通讯) + MB_HOLD_REG((byte) 0x03, (byte) 0x10), + Q_OUT((byte) 0x01, (byte) 0x05), + I_IN((byte) 0x02, null), + IW_IN((byte) 0x04, null), + ; - private Byte fread; - private Byte fwrite; + private Byte fread; + private Byte fwrite; - ModbusFC(Byte fread, Byte fwrite){ - this.fread = fread; - this.fwrite = fwrite; - } + ModbusFC(Byte fread, Byte fwrite) { + this.fread = fread; + this.fwrite = fwrite; + } - public Byte getFread() { - return fread; - } + public Byte getFread() { + return fread; + } - public void setFread(Byte fread) { - this.fread = fread; - } + public void setFread(Byte fread) { + this.fread = fread; + } - public Byte getFwrite() { - return fwrite; - } + public Byte getFwrite() { + return fwrite; + } - public void setFwrite(Byte fwrite) { - this.fwrite = fwrite; - } + public void setFwrite(Byte fwrite) { + this.fwrite = fwrite; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/syn/AsyncFuture.java b/opentcs-common/src/main/java/org/opentcs/kc/syn/AsyncFuture.java index 20daa73..c52812f 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/syn/AsyncFuture.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/syn/AsyncFuture.java @@ -5,61 +5,62 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * @Author: 蔡翔 - * @Date: 2019/11/6 14:11 - * @Version 1.0 - * - * (重点) - * AsyncFuture 这个类就是票据, 刚拿到这个票据是没有信息的,当done == true 的时候,这个票据 上就自动有信息了 - * 这个结果类设计的比较神奇 + * (重点). + * AsyncFuture 这个类就是票据, 刚拿到这个票据是没有信息的,当done == true 的时候,这个票据 上就自动有信息了. + * 这个结果类设计的比较神奇. */ -public class AsyncFuture implements Future { +public class AsyncFuture + implements + Future { - private static final Logger logger = LoggerFactory.getLogger(AsyncFuture.class); - private volatile boolean done = false; - private Object oldRequest; - private Object result; + private static final Logger logger = LoggerFactory.getLogger(AsyncFuture.class); + private volatile boolean done = false; + private Object oldRequest; + private Object result; - public AsyncFuture(Object oldRequest) { - this.oldRequest = oldRequest; - } - public AsyncFuture() { - } - - public void done(Object result){ - synchronized (this){ - this.result = result; - this.done = true; - //注意这里的notifyAll只能唤醒 本锁的所有 下的所有 wait(),这里的锁就是 AsyncFuture这个类 - notifyAll(); - } + public AsyncFuture(Object oldRequest) { + this.oldRequest = oldRequest; + } + + public AsyncFuture() { + } + + public void done(Object result) { + synchronized (this) { + this.result = result; + this.done = true; + //注意这里的notifyAll只能唤醒 本锁的所有 下的所有 wait(),这里的锁就是 AsyncFuture这个类 + notifyAll(); } + } - @Override - public Object get(Long timeout) throws Exception { - return null; - } + @Override + public Object get(Long timeout) + throws Exception { + return null; + } - @Override - public Object get(Long timeout, String transationId) throws Exception { - synchronized (this){ - //其实有 synchronize就相当于有一个阻塞队列,当有线程执行了wait 方法,就会把执行wait的这个线程给加入wait 队列, - //当有线程执行notify方法的时候,就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了 + @Override + public Object get(Long timeout, String transationId) + throws Exception { + synchronized (this) { + //其实有 synchronize就相当于有一个阻塞队列,当有线程执行了wait 方法,就会把执行wait的这个线程给加入wait 队列, + //当有线程执行notify方法的时候,就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了 // System.out.println("get"); - // 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。 wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify() - // * 当线程执行notify()/notifyAll()方法时,会唤醒一个处于等待状态该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁 - this.wait(timeout); - if(!done){ - //logger.error("T3 timeout , request information: "+oldRequest.toString()); - SendedList.remove(transationId); - throw new Exception("T3 timeout , request information: "+oldRequest.toString()); - } - - //因为上面的代码是加锁的,所以这里的代码也是加锁的。 - return result; - } + // 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。 wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify() + // * 当线程执行notify()/notifyAll()方法时,会唤醒一个处于等待状态该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁 + this.wait(timeout); + if (!done) { + //logger.error("T3 timeout , request information: "+oldRequest.toString()); + SendedList.remove(transationId); + throw new Exception("T3 timeout , request information: " + oldRequest.toString()); + } + //因为上面的代码是加锁的,所以这里的代码也是加锁的。 + return result; } + + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/syn/Future.java b/opentcs-common/src/main/java/org/opentcs/kc/syn/Future.java index 88201ef..bdc1af2 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/syn/Future.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/syn/Future.java @@ -1,14 +1,11 @@ package org.opentcs.kc.syn; -/** - * @Author: 蔡翔 - * @Date: 2019/11/6 13:49 - * @Version 1.0 - */ public interface Future { - //别人调用我的时候,我先给他们返回一个结果, - 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; } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/syn/Main.java b/opentcs-common/src/main/java/org/opentcs/kc/syn/Main.java index 75e8c32..d49cbaa 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/syn/Main.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/syn/Main.java @@ -1,13 +1,6 @@ package org.opentcs.kc.syn; - - -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2021/8/17 14:35 - */ public class Main { // public static void main(String[] args) throws Exception { diff --git a/opentcs-common/src/main/java/org/opentcs/kc/syn/SendedList.java b/opentcs-common/src/main/java/org/opentcs/kc/syn/SendedList.java index 2fc8c07..088bc3d 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/syn/SendedList.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/syn/SendedList.java @@ -4,12 +4,6 @@ package org.opentcs.kc.syn; import org.opentcs.kc.common.CaffeineUtil; import org.opentcs.kc.common.Package; - -/** - * @Desc: "MES端 发送远程指令列表" - * @Author: caixiang - * @DATE: 2021/8/17 14:14 - */ public class SendedList { // private static HashMap> list = new HashMap<>(); // public static synchronized AsyncFuture get(String transitionId){ @@ -19,33 +13,33 @@ public class SendedList { // list.put(transitionId,asyncFuture); // } - public static synchronized AsyncFuture add(String transitionId, Package PackageRequest) { - AsyncFuture objectAsyncFuture = new AsyncFuture<>(PackageRequest); - //list.put(transitionId,objectAsyncFuture); - CaffeineUtil.put(transitionId,objectAsyncFuture); - return objectAsyncFuture; + public static synchronized AsyncFuture add(String transitionId, Package PackageRequest) { + AsyncFuture objectAsyncFuture = new AsyncFuture<>(PackageRequest); + //list.put(transitionId,objectAsyncFuture); + CaffeineUtil.put(transitionId, 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 mqMessageAsyncFuture = list.get(transitionId); + AsyncFuture mqMessageAsyncFuture = (AsyncFuture) CaffeineUtil.get( + transitionId + ); + if (mqMessageAsyncFuture == null) { + return false; } - - //如果超时了,那么让外部把这个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 mqMessageAsyncFuture = list.get(transitionId); - AsyncFuture mqMessageAsyncFuture = (AsyncFuture)CaffeineUtil.get(transitionId); - if(mqMessageAsyncFuture == null){ - return false; - } - mqMessageAsyncFuture.done(message); - //清除 ,防止这个hashMap过大。 - CaffeineUtil.remove(transitionId); - return true; - } - - + mqMessageAsyncFuture.done(message); + //清除 ,防止这个hashMap过大。 + CaffeineUtil.remove(transitionId); + return true; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogConst.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogConst.java index 9f3ad60..0ac28e9 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogConst.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogConst.java @@ -13,23 +13,24 @@ import java.util.Random; * 类说明:日志信息,用String数组代替 */ public class LogConst { - public final static int MONITOR_SIDE_PORT = 9998; - private static final String[] LOG_INFOS = { - "晨光微好,暖在夕阳。幽幽的巷子里,有着岁月酝酿的酒,愈久愈淳。一笔墨香,一盏明灯,记千帆过浪,数不尽的悲欢离合,待那水莲花开。", - "未来无期,静在安好。一剪寒梅,纷扰了岁月,抚平了伤痕。摆动的双桨,拨动了心的潭水。陌上花开,落一地秋霜,红枫染了红尘,便许了你十里红装。", - "离别的风,风干了月的泪。夜里的美", - "是梦的呢喃低语,挥走一片彩云,段落成珠。拂袖离去,乘鹤而来,古道西风瘦马。斑驳的树影中,眉目如画的眼,轻语告别了往事如烟。", - "无言的殇,几世沧桑,几生悲凉。一起剪了西窗烛,听了夜来风吹雨。昨日的叹息,今日的迷离,执一伞,存了一世一笔的温情。一曲长歌,唱尽了一世繁华,一世缘……", - "一世恋书,那便十里花开。一生凄凉,那便霜花十里。" , - "一抹浓烟,便翻页书,展颜一笑,是时间带来遥远的梦。细数树的年轮,感受昨日惆怅,留一半清醒,梦一半叶落。在指尖流过的沙,海边浪花一朵朵,不相遇,才有不约而同。", - "这世俗,太多牵挂留在心间,一点朱砂泪,一曲相诗歌。岁月朦胧,梦醒了人生,风雨相容,演绎了一段风情。雪亦梦,雨亦梦,万张红纸从天洒来。惊动了山,撼动了天。" + - "一纸情愁,一指烟凉。一相思,一思量,水漫岸头,我们都有着自己不同的三生故事。迎一夜秋风,送一世暖阳,一切冰雪里的花开,是我一生的柔情。" + - "记忆中的短笛,有着清风须来的气息,那时我们面向大海,海风在耳边述说着大海边缘的温暖故事。安好一轮冷月,静好了一残红日,这便是我的语言,我的情丝。" + - "一漫山水,一段情,留在了岁月,拭去了风,晴雨清风,倒是暖阳拂绿草。" + - "这便,晨光微好,花开静好……"}; + public final static int MONITOR_SIDE_PORT = 9998; + private static final String[] LOG_INFOS = { + "晨光微好,暖在夕阳。幽幽的巷子里,有着岁月酝酿的酒,愈久愈淳。一笔墨香,一盏明灯,记千帆过浪,数不尽的悲欢离合,待那水莲花开。", + "未来无期,静在安好。一剪寒梅,纷扰了岁月,抚平了伤痕。摆动的双桨,拨动了心的潭水。陌上花开,落一地秋霜,红枫染了红尘,便许了你十里红装。", + "离别的风,风干了月的泪。夜里的美", + "是梦的呢喃低语,挥走一片彩云,段落成珠。拂袖离去,乘鹤而来,古道西风瘦马。斑驳的树影中,眉目如画的眼,轻语告别了往事如烟。", + "无言的殇,几世沧桑,几生悲凉。一起剪了西窗烛,听了夜来风吹雨。昨日的叹息,今日的迷离,执一伞,存了一世一笔的温情。一曲长歌,唱尽了一世繁华,一世缘……", + "一世恋书,那便十里花开。一生凄凉,那便霜花十里。", + "一抹浓烟,便翻页书,展颜一笑,是时间带来遥远的梦。细数树的年轮,感受昨日惆怅,留一半清醒,梦一半叶落。在指尖流过的沙,海边浪花一朵朵,不相遇,才有不约而同。", + "这世俗,太多牵挂留在心间,一点朱砂泪,一曲相诗歌。岁月朦胧,梦醒了人生,风雨相容,演绎了一段风情。雪亦梦,雨亦梦,万张红纸从天洒来。惊动了山,撼动了天。" + + "一纸情愁,一指烟凉。一相思,一思量,水漫岸头,我们都有着自己不同的三生故事。迎一夜秋风,送一世暖阳,一切冰雪里的花开,是我一生的柔情。" + + "记忆中的短笛,有着清风须来的气息,那时我们面向大海,海风在耳边述说着大海边缘的温暖故事。安好一轮冷月,静好了一残红日,这便是我的语言,我的情丝。" + + "一漫山水,一段情,留在了岁月,拭去了风,晴雨清风,倒是暖阳拂绿草。" + + "这便,晨光微好,花开静好……"}; - private final static Random r = new Random(); - public static String getLogInfo(){ - return LOG_INFOS[r.nextInt(LOG_INFOS.length-1)]; - } + private final static Random r = new Random(); + + public static String getLogInfo() { + return LOG_INFOS[r.nextInt(LOG_INFOS.length - 1)]; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventBroadcaster.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventBroadcaster.java index 3c1039a..a6d2bc5 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventBroadcaster.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventBroadcaster.java @@ -19,56 +19,66 @@ import java.net.InetSocketAddress; * 类说明:日志的广播端 ( Client 端 ) */ public class LogEventBroadcaster { - private final EventLoopGroup group; - private final Bootstrap bootstrap; + private final EventLoopGroup group; + private final Bootstrap bootstrap; - public LogEventBroadcaster(InetSocketAddress remoteAddress) { - group = new NioEventLoopGroup(); - bootstrap = new Bootstrap(); - //引导该 NioDatagramChannel(无连接的) - bootstrap.group(group).channel(NioDatagramChannel.class) - //todo 设置 SO_BROADCAST 套接字选项(option so_broadcast差异,这里和单播 是有差异的) - .option(ChannelOption.SO_BROADCAST, true) - .handler(new LogEventEncoder(remoteAddress)); + public LogEventBroadcaster(InetSocketAddress remoteAddress) { + group = new NioEventLoopGroup(); + bootstrap = new Bootstrap(); + //引导该 NioDatagramChannel(无连接的) + bootstrap.group(group).channel(NioDatagramChannel.class) + //todo 设置 SO_BROADCAST 套接字选项(option so_broadcast差异,这里和单播 是有差异的) + .option(ChannelOption.SO_BROADCAST, true) + .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 { - //绑定 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 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(); } - - public void 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(); - } + finally { + broadcaster.stop(); } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventDecoder.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventDecoder.java index d5a3a52..a660dd8 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventDecoder.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventDecoder.java @@ -18,30 +18,38 @@ import java.util.List; * 作者:DarkKIng * 类说明:解码,将DatagramPacket解码为实际的日志实体类 */ -public class LogEventDecoder extends MessageToMessageDecoder { +public class LogEventDecoder + extends + MessageToMessageDecoder { - @Override - protected void decode(ChannelHandlerContext ctx, - DatagramPacket datagramPacket, List out) - throws Exception { - //获取对 DatagramPacket 中的数据(ByteBuf)的引用 - ByteBuf data = datagramPacket.content(); - long time = new Date().getTime(); + @Override + protected void decode( + ChannelHandlerContext ctx, + DatagramPacket datagramPacket, List out + ) + throws Exception { + //获取对 DatagramPacket 中的数据(ByteBuf)的引用 + ByteBuf data = datagramPacket.content(); + long time = new Date().getTime(); - System.out.println(time+" 接受到发送的消息:"); - //获得消息的id - long msgId = data.readLong(); - //获得分隔符SEPARATOR - byte sepa = data.readByte(); - //获取读索引的当前位置,就是分隔符的索引+1 - int idx = data.readerIndex(); - //提取日志消息,从读索引开始,到最后为日志的信息 - String sendMsg = data.slice(idx , - data.readableBytes()).toString(CharsetUtil.UTF_8); - //构建一个新的 LogMsg 对象,并且将它添加到(已经解码的消息的)列表中 - LogMsg event = new LogMsg(datagramPacket.sender(), - msgId, sendMsg); - //作为本handler的处理结果,交给后面的handler进行处理 - out.add(event); - } + System.out.println(time + " 接受到发送的消息:"); + //获得消息的id + long msgId = data.readLong(); + //获得分隔符SEPARATOR + byte sepa = data.readByte(); + //获取读索引的当前位置,就是分隔符的索引+1 + int idx = data.readerIndex(); + //提取日志消息,从读索引开始,到最后为日志的信息 + String sendMsg = data.slice( + idx, + data.readableBytes() + ).toString(CharsetUtil.UTF_8); + //构建一个新的 LogMsg 对象,并且将它添加到(已经解码的消息的)列表中 + LogMsg event = new LogMsg( + datagramPacket.sender(), + msgId, sendMsg + ); + //作为本handler的处理结果,交给后面的handler进行处理 + out.add(event); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventEncoder.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventEncoder.java index 99b2319..2a6f9ad 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventEncoder.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventEncoder.java @@ -18,31 +18,36 @@ import java.util.List; * 作者:DarkKIng * 类说明:编码,将实际的日志实体类编码为DatagramPacket */ -public class LogEventEncoder extends MessageToMessageEncoder { - private final InetSocketAddress remoteAddress; +public class LogEventEncoder + extends + MessageToMessageEncoder { + private final InetSocketAddress remoteAddress; - //LogEventEncoder 创建了即将被发送到指定的 InetSocketAddress - // 的 DatagramPacket 消息 - public LogEventEncoder(InetSocketAddress remoteAddress) { - this.remoteAddress = remoteAddress; - } + //LogEventEncoder 创建了即将被发送到指定的 InetSocketAddress + // 的 DatagramPacket 消息 + public LogEventEncoder(InetSocketAddress remoteAddress) { + this.remoteAddress = remoteAddress; + } - @Override - protected void encode(ChannelHandlerContext channelHandlerContext, - LogMsg logMsg, List out) throws Exception { - byte[] msg = logMsg.getMsg().getBytes(CharsetUtil.UTF_8); - //容量的计算:两个long型+消息的内容+分割符 - ByteBuf buf = channelHandlerContext.alloc() - .buffer(8*2 + msg.length + 1); - //将发送时间写入到 ByteBuf中 - buf.writeLong(logMsg.getTime()); - //将消息id写入到 ByteBuf中 - buf.writeLong(logMsg.getMsgId()); - //添加一个 SEPARATOR - buf.writeByte(LogMsg.SEPARATOR); - //将日志消息写入 ByteBuf中 - buf.writeBytes(msg); - //将一个拥有数据和目的地地址的新 DatagramPacket 添加到出站的消息列表中 - out.add(new DatagramPacket(buf, remoteAddress)); - } + @Override + protected void encode( + ChannelHandlerContext channelHandlerContext, + LogMsg logMsg, List out + ) + throws Exception { + byte[] msg = logMsg.getMsg().getBytes(CharsetUtil.UTF_8); + //容量的计算:两个long型+消息的内容+分割符 + ByteBuf buf = channelHandlerContext.alloc() + .buffer(8 * 2 + msg.length + 1); + //将发送时间写入到 ByteBuf中 + buf.writeLong(logMsg.getTime()); + //将消息id写入到 ByteBuf中 + buf.writeLong(logMsg.getMsgId()); + //添加一个 SEPARATOR + buf.writeByte(LogMsg.SEPARATOR); + //将日志消息写入 ByteBuf中 + buf.writeBytes(msg); + //将一个拥有数据和目的地地址的新 DatagramPacket 添加到出站的消息列表中 + out.add(new DatagramPacket(buf, remoteAddress)); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventHandler.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventHandler.java index 399e2ed..e7f19e5 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventHandler.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventHandler.java @@ -14,29 +14,36 @@ import io.netty.channel.SimpleChannelInboundHandler; * 类说明:日志的业务处理类,实际的业务处理,接受日志信息 */ public class LogEventHandler - extends SimpleChannelInboundHandler { + extends + SimpleChannelInboundHandler { - @Override - public void exceptionCaught(ChannelHandlerContext ctx, - Throwable cause) throws Exception { - //当异常发生时,打印栈跟踪信息,并关闭对应的 Channel - cause.printStackTrace(); - ctx.close(); - } + @Override + public void exceptionCaught( + ChannelHandlerContext ctx, + Throwable cause + ) + throws Exception { + //当异常发生时,打印栈跟踪信息,并关闭对应的 Channel + cause.printStackTrace(); + ctx.close(); + } - @Override - public void channelRead0(ChannelHandlerContext ctx, - LogMsg event) throws Exception { - //创建 StringBuilder,并且构建输出的字符串 - StringBuilder builder = new StringBuilder(); - builder.append(event.getTime()); - builder.append(" ["); - builder.append(event.getSource().toString()); - builder.append("] :["); - builder.append(event.getMsgId()); - builder.append("] :"); - builder.append(event.getMsg()); - //打印 LogMsg 的数据 - System.out.println(builder.toString()); - } + @Override + public void channelRead0( + ChannelHandlerContext ctx, + LogMsg event + ) + throws Exception { + //创建 StringBuilder,并且构建输出的字符串 + StringBuilder builder = new StringBuilder(); + builder.append(event.getTime()); + builder.append(" ["); + builder.append(event.getSource().toString()); + builder.append("] :["); + builder.append(event.getMsgId()); + builder.append("] :"); + builder.append(event.getMsg()); + //打印 LogMsg 的数据 + System.out.println(builder.toString()); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventMonitor.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventMonitor.java index 144ba5e..882d217 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventMonitor.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogEventMonitor.java @@ -6,58 +6,55 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioDatagramChannel; import java.net.InetSocketAddress; -/** - * @Desc: "" - * @Author: caixiang ( Server 端,接受消息 ) - * @DATE: 2024/12/15 10:57 - */ - public class LogEventMonitor { - private final EventLoopGroup group; - private final Bootstrap bootstrap; + private final EventLoopGroup group; + private final Bootstrap bootstrap; - public LogEventMonitor(InetSocketAddress address) { - group = new NioEventLoopGroup(); - bootstrap = new Bootstrap(); - //引导该 NioDatagramChannel - bootstrap.group(group) - .channel(NioDatagramChannel.class) - //设置套接字选项 SO_BROADCAST - .option(ChannelOption.SO_BROADCAST, true) - //允许重用 - .option(ChannelOption.SO_REUSEADDR,true) - .handler( new ChannelInitializer() { - @Override - protected void initChannel(Channel channel) - throws Exception { - ChannelPipeline pipeline = channel.pipeline(); - pipeline.addLast(new LogEventDecoder()); - pipeline.addLast(new LogEventHandler()); - } - } ) - .localAddress(address); - } + public LogEventMonitor(InetSocketAddress address) { + group = new NioEventLoopGroup(); + bootstrap = new Bootstrap(); + //引导该 NioDatagramChannel + bootstrap.group(group) + .channel(NioDatagramChannel.class) + //设置套接字选项 SO_BROADCAST + .option(ChannelOption.SO_BROADCAST, true) + //允许重用 + .option(ChannelOption.SO_REUSEADDR, true) + .handler(new ChannelInitializer() { + @Override + protected void initChannel(Channel channel) + throws Exception { + ChannelPipeline pipeline = channel.pipeline(); + pipeline.addLast(new LogEventDecoder()); + pipeline.addLast(new LogEventHandler()); + } + }) + .localAddress(address); + } - public Channel bind() { - //绑定 Channel。注意,DatagramChannel 是无连接的 - return bootstrap.bind().syncUninterruptibly().channel(); - } + public Channel bind() { + //绑定 Channel。注意,DatagramChannel 是无连接的 + return bootstrap.bind().syncUninterruptibly().channel(); + } - public void stop() { - group.shutdownGracefully(); - } + public void stop() { + group.shutdownGracefully(); + } - public static void main(String[] args) throws Exception { - //构造一个新的 UdpAnswerSide并指明监听端口 - LogEventMonitor monitor = new LogEventMonitor( - new InetSocketAddress(LogConst.MONITOR_SIDE_PORT)); - try { - //绑定本地监听端口 - Channel channel = monitor.bind(); - System.out.println("UdpAnswerSide running"); - channel.closeFuture().sync(); - } finally { - monitor.stop(); - } + public static void main(String[] args) + throws Exception { + //构造一个新的 UdpAnswerSide并指明监听端口 + LogEventMonitor monitor = new LogEventMonitor( + new InetSocketAddress(LogConst.MONITOR_SIDE_PORT) + ); + try { + //绑定本地监听端口 + Channel channel = monitor.bind(); + System.out.println("UdpAnswerSide running"); + channel.closeFuture().sync(); } + finally { + monitor.stop(); + } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogMsg.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogMsg.java index 0b8e0ec..2f998f3 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogMsg.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/GB/LogMsg.java @@ -13,51 +13,53 @@ import java.net.InetSocketAddress; * 类说明:日志实体类 */ public final class LogMsg { - public static final byte SEPARATOR = (byte) ':'; - /*源的 InetSocketAddress*/ - private final InetSocketAddress source; - /*消息内容*/ - private final String msg; - /*消息id*/ - private final long msgId; - /*消息发送的时间*/ - private final long time; + public static final byte SEPARATOR = (byte) ':'; + /* 源的 InetSocketAddress */ + private final InetSocketAddress source; + /* 消息内容 */ + private final String msg; + /* 消息id */ + private final long msgId; + /* 消息发送的时间 */ + private final long time; - //用于传入消息的构造函数 - public LogMsg(String msg) { - this(null, msg,-1,System.currentTimeMillis()); - } + //用于传入消息的构造函数 + public LogMsg(String msg) { + this(null, msg, -1, System.currentTimeMillis()); + } - //用于传出消息的构造函数 - public LogMsg(InetSocketAddress source, long msgId, - String msg) { - this(source,msg,msgId,System.currentTimeMillis()); - } + //用于传出消息的构造函数 + public LogMsg( + InetSocketAddress source, long msgId, + String msg + ) { + this(source, msg, msgId, System.currentTimeMillis()); + } - public LogMsg(InetSocketAddress source, String msg, long msgId, long time) { - this.source = source; - this.msg = msg; - this.msgId = msgId; - this.time = time; - } + public LogMsg(InetSocketAddress source, String msg, long msgId, long time) { + this.source = source; + this.msg = msg; + this.msgId = msgId; + this.time = time; + } - //返回发送 LogMsg 的源的 InetSocketAddress - public InetSocketAddress getSource() { - return source; - } + //返回发送 LogMsg 的源的 InetSocketAddress + public InetSocketAddress getSource() { + return source; + } - //返回消息内容 - public String getMsg() { - return msg; - } + //返回消息内容 + public String getMsg() { + return msg; + } - //返回消息id - public long getMsgId() { - return msgId; - } + //返回消息id + public long getMsgId() { + return msgId; + } - //返回消息中的时间 - public long getTime() { - return time; - } + //返回消息中的时间 + public long getTime() { + return time; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/KCCommandDemo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/KCCommandDemo.java index 064b326..911aaf5 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/KCCommandDemo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/KCCommandDemo.java @@ -3,12 +3,13 @@ package org.opentcs.kc.udp; import java.nio.ByteOrder; import java.util.ArrayList; import java.util.List; -//import org.opentcs.kc.udp.agv.param.AgvEvent; import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.udp.agv.param.AgvEvent; 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.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.read.ReadParam; 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.WriteValueMember; 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.io.UDPClient; -import org.opentcs.kc.udp.agv.param.AgvEvent; /** - * * AGV启动: - * 0xAF(查询机器人状态) 👌 - * 0xB1(下发订阅信令) 👌 + * 0xAF(查询机器人状态) 👌 + * 0xB1(下发订阅信令) 👌 * 初始化: - * 0x03(切换手自动) 👌 - * 0x14(手动定位) 👌 - * 0x17(查询机器人运行状态) 👌 - * 0x1F(确认初始位置) 👌 + * 0x03(切换手自动) 👌 + * 0x14(手动定位) 👌 + * 0x17(查询机器人运行状态) 👌 + * 0x1F(确认初始位置) 👌 * 运行: * 0xAE(导航控制导航点控制) 👌 - * - * - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/17 16:25 */ public class KCCommandDemo { - public static void main(String [] args) throws Exception{ + public static void main(String[] args) + throws Exception { // { // //0xAF(查询机器人状态) // AgvEvent agvEvent = queryStatus(); // printInfo(agvEvent); // RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); // 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()); -// System.out.println(); -// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); -// for (byte b:rcv.getValue()){ -// System.out.print(byteToHex(b)+" "); -// } // }else { // System.out.println(); // System.out.println("received transationId : "+ "isok:"+rcv.isOk()); @@ -86,6 +87,10 @@ public class KCCommandDemo { // if(rcv.isOk()){ // System.out.println(); // System.out.println("received transationId : "+ "isok:"+rcv.isOk()); +// for (byte b:rcv.getDataBytes()) { +// System.out.print(byteToHex(b)+" "); +// } +// // SubscribeRsp subscribeRsp = new SubscribeRsp(rcv.getDataBytes()); // if(subscribeRsp.isOk()){ // //... @@ -142,26 +147,26 @@ public class KCCommandDemo { // } -// { -// //0x14(手动定位) -// AgvEvent agvEvent = manualLocation(); -// printInfo(agvEvent); -// RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); -// if(rcv.isOk()){ -// System.out.println(); -// System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:"); -// printInfo(rcv); -// if(rcv.isOk()){ -// //get and parse value -// System.out.println("0x14 ok"); -// }else { -// System.out.println("0x14 failed"); -// } -// }else { -// System.out.println(); -// System.out.println("received transationId : "+ "isok:"+rcv.isOk()); -// } -// } + { + //0x14(手动定位) + AgvEvent agvEvent = manualLocation(); + printInfo(agvEvent); + RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); + if(rcv.isOk()){ + System.out.println(); + System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:"); + printInfo(rcv); + if(rcv.isOk()){ + //get and parse value + System.out.println("0x14 ok"); + }else { + System.out.println("0x14 failed"); + } + }else { + System.out.println(); + System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + } + } // { @@ -170,33 +175,40 @@ public class KCCommandDemo { // printInfo(agvEvent); // RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); // 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()); // QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp(rcv.getDataBytes()); // 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 { // System.out.println(); // System.out.println("received transationId : "+ "isok:"+rcv.isOk()); // } // } - { - //0x1F(确认初始位置) - AgvEvent agvEvent = confirmInitialPosition(); - printInfo(agvEvent); - RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ - System.out.println("0x1F ok"); - }else { - System.out.println(); - System.out.println("0x1F fail"); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); - } - } +// { +// //0x1F(确认初始位置) +// AgvEvent agvEvent = confirmInitialPosition(); +// printInfo(agvEvent); +// RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); +// if (rcv.isOk()) { +// System.out.println("0x1F ok"); +// } +// else { +// System.out.println(); +// System.out.println("0x1F fail"); +// System.out.println("received transationId : " + "isok:" + rcv.isOk()); +// } +// } // { // //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 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) { + System.out.println("sended transationId : " + agvEvent.getTransationIdString()); + for (byte b : agvEvent.toBytes().getBody()) { + System.out.print(byteToHex(b) + " "); } + } - public static void printInfo(AgvEvent agvEvent){ - System.out.println("sended transationId : "+agvEvent.getTransationIdString()); - for (byte b:agvEvent.toBytes().getBody()){ - System.out.print(byteToHex(b)+" "); - } + public static void printInfo(RcvEventPackage rcv) { + + for (byte b : rcv.getDataBytes()) { + 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 readValueMemberList = new ArrayList<>(); + ReadValueMember readValueMember1 = new ReadValueMember(Short.valueOf("0"), Short.valueOf("1")); + readValueMemberList.add(readValueMember1); - for (byte b: rcv.getDataBytes()){ - System.out.print(byteToHex(b)+" "); - } - } + List readStrValueList = new ArrayList<>(); + ReadStrValue readStrValue = new ReadStrValue("Battry_SOC", 1, readValueMemberList); + readStrValueList.add(readStrValue); - /** - * decs: read操作 - * 指令:0x02 - * author: caixiang - * date: 2025/1/17 16:25 - * */ - public static AgvEvent readValue() { - AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_READ); - List readValueMemberList = new ArrayList<>(); - ReadValueMember readValueMember1 = new ReadValueMember(Short.valueOf("0"),Short.valueOf("1")); - readValueMemberList.add(readValueMember1); + ReadParam readParam = new ReadParam(agvEvent.getTransationId(), readStrValueList); + agvEvent.setBody(readParam.toBytes()); - List readStrValueList = new ArrayList<>(); - ReadStrValue readStrValue = new ReadStrValue("Battry_SOC", 1, readValueMemberList); - readStrValueList.add(readStrValue); + return agvEvent; + } - 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 valueMemberList = new ArrayList<>(); + WriteValueMember valueMember1 = new WriteValueMember( + Short.valueOf("0"), Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN) + ); + valueMemberList.add(valueMember1); - /** - * decs: write操作 - * 指令:0x03 - * author: caixiang - * date: 2025/1/17 16:25 - * */ - public static AgvEvent writeValue() { - AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE); + List strValueList = new ArrayList<>(); + WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList); + strValueList.add(strValue); - List valueMemberList = new ArrayList<>(); - WriteValueMember valueMember1 = new WriteValueMember(Short.valueOf("0"),Short.valueOf("4"), ByteUtils.uintToBytes(3, ByteOrder.LITTLE_ENDIAN)); - valueMemberList.add(valueMember1); + WriteParam param = new WriteParam(1, strValueList); + agvEvent.setBody(param.toBytes()); - List strValueList = new ArrayList<>(); - WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList); - strValueList.add(strValue); - - WriteParam param = new WriteParam(1,strValueList ); - agvEvent.setBody(param.toBytes()); - - return agvEvent; - } + 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: 查询机器人状态 - * 指令: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: 查询载货状态 + * 指令: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: 导航控制 - * 指令: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: 查询载货状态 - * 指令: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 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; - } + /** + * decs: 下发订阅信息 + * 指令:0xB1 + * author: caixiang + * date: 2025/1/17 16:25 + */ + public static AgvEvent issueSubscribe() { + List 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; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/BaseCommand.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/BaseCommand.java index 7b6f52f..0abf3a2 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/BaseCommand.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/BaseCommand.java @@ -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.rsp.RcvEventPackage; -/** - * @author xzh - * @date 2025/2/21 - * @desc 命令基类 - */ public class BaseCommand { public static String byteToHex(byte b) { @@ -22,17 +17,17 @@ public class BaseCommand { return hexString; } - public static void printInfo(AgvEvent agvEvent){ - System.out.println("sended transationId : "+agvEvent.getTransationIdString()); - for (byte b:agvEvent.toBytes().getBody()){ - System.out.print(byteToHex(b)+" "); + public static void printInfo(AgvEvent agvEvent) { + System.out.println("sended transationId : " + agvEvent.getTransationIdString()); + for (byte b : agvEvent.toBytes().getBody()) { + System.out.print(byteToHex(b) + " "); } } - public static void printInfo(RcvEventPackage rcv){ + public static void printInfo(RcvEventPackage rcv) { - for (byte b: rcv.getDataBytes()){ - System.out.print(byteToHex(b)+" "); + for (byte b : rcv.getDataBytes()) { + System.out.print(byteToHex(b) + " "); } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ConfirmRelocation.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ConfirmRelocation.java index cc33b10..1c69ea0 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ConfirmRelocation.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ConfirmRelocation.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 确认位置 0x1F - */ -public class ConfirmRelocation extends BaseCommand{ +public class ConfirmRelocation + extends + BaseCommand { /** - * decs: 确认机器人位置 - * 指令:0x1F - * author: caixiang - * date: 2025/1/17 16:25 - * */ + * 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; @@ -28,12 +25,13 @@ public class ConfirmRelocation extends BaseCommand{ AgvEvent agvEvent = confirmInitialPosition(); printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { System.out.println("0x1F ok"); - }else { + } + else { System.out.println(); System.out.println("0x1F fail"); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); } } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/HybridNavigation.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/HybridNavigation.java index 7dafe12..94aa879 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/HybridNavigation.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/HybridNavigation.java @@ -1,5 +1,7 @@ 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.udp.agv.param.AgvEvent; 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.io.UDPClient; -public class HybridNavigation extends BaseCommand{ +public class HybridNavigation + extends + BaseCommand { /** * 测试模式:true=开启测试,false=关闭测试 @@ -38,6 +42,14 @@ public class HybridNavigation extends BaseCommand{ * 用于定位段在整个任务中的位置。目的是区分同一个段ID是否在一个任务中出现多次。从1开始奇数递增,例如:1->3->5->7…… */ private static Integer pathSerialNum = 1; + /** + * 订单名映射int类型数据. + */ + private static HashMap orderNameMap = new HashMap<>(); + /** + * 订单映射最大订单ID. + */ + private static int currentMaxiOrderId = 0; /** @@ -45,45 +57,37 @@ public class HybridNavigation extends BaseCommand{ * 指令:0xAE * author: caixiang * date: 2025/1/17 16:25 - * */ - public static AgvEvent navigationControl(Integer sourcePoint, Integer destinationPoint, Integer pathID, String operation) { - AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_QUERY_ROBOT_STATUS); + */ + public static AgvEvent navigationControl( + Integer sourcePoint, Integer destinationPoint, Integer pathID, String operation + ) { + AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_MIXED_ISSUANCE_TASK); //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; pointSerialNum += 2; Point[] points = new Point[]{ - new Point(oldPointSerialNum, sourcePoint, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions1.length),pointActions1), - new Point(pointSerialNum, destinationPoint, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions2.length),pointActions2) -// new Point(4, 3, 1f, (byte)0x00, ByteUtils.usintTo1Byte(pointActions3.length),pointActions3) + new Point( + oldPointSerialNum, sourcePoint, 0f, (byte) 0x00, ByteUtils.usintTo1Byte(0), null + ), + 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[]{ - new Path(pathSerialNum,pathID,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) , + new Path( + 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()); return agvEvent; @@ -96,16 +100,24 @@ public class HybridNavigation extends BaseCommand{ * @param destinationPoint 下发终点 * @param operation 执行操作 */ - public static void command(String orderName, String sourcePoint, String destinationPoint, String operation) { - if (TEST_MODEL) { - return; - } + public static void command( + String orderName, String sourcePoint, String destinationPoint, String operation + ) { +// if (TEST_MODEL) { +// return; +// } - Integer newOrderName = Integer.parseInt(orderName); + Integer newOrderName = getUniqueOrderID(orderName); Integer newSourcePoint = Integer.parseInt(sourcePoint); Integer newDestinationPoint = Integer.parseInt(destinationPoint); //拼接起点终点字符串转为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)) { //切换订单重置参数 @@ -116,17 +128,19 @@ public class HybridNavigation extends BaseCommand{ AgvEvent agvEvent = navigationControl(newSourcePoint, newDestinationPoint, pathID, operation); printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { System.out.println("0xAE ok"); - }else { + } + else { System.out.println(); System.out.println("0xAE fail"); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); } } /** * 初始化参数 + * * @param newOrderName 新的订单ID */ private static void initParams(Integer newOrderName) { @@ -136,4 +150,34 @@ public class HybridNavigation extends BaseCommand{ 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); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ManualPosition.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ManualPosition.java index 9c776b0..36178d9 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ManualPosition.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/ManualPosition.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 手动定位 0x14 - */ -public class ManualPosition extends BaseCommand{ +public class ManualPosition + extends + BaseCommand { public static AgvEvent manualLocation(double agvX, double agvY, double agvAngle) { AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_ROBOT_SET_POSITION); @@ -27,19 +24,21 @@ public class ManualPosition extends BaseCommand{ AgvEvent agvEvent = manualLocation(agvX, agvY, agvAngle); printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { System.out.println(); - System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:"); + System.out.println("received " + "isok:" + rcv.isOk() + " dataBytes:"); printInfo(rcv); - if(rcv.isOk()){ + if (rcv.isOk()) { //get and parse value System.out.println("0x14 ok"); - }else { + } + else { System.out.println("0x14 failed"); } - }else { + } + else { System.out.println(); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); throw new RuntimeException("0x14 failed"); } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotRunStatus.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotRunStatus.java index 663140e..8be3578 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotRunStatus.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotRunStatus.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 获取AGV运行状态 - */ -public class QryRobotRunStatus extends BaseCommand{ +public class QryRobotRunStatus + extends + BaseCommand { /** - * decs: 查询机器人运行状态 + * 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; @@ -29,19 +26,22 @@ public class QryRobotRunStatus extends BaseCommand{ AgvEvent agvEvent = queryRobotRunStatus(); printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { //QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes()); - QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp(rcv.getDataBytes()); + QueryRobotRunStatusRsp queryRobotRunStatusRsp = new QueryRobotRunStatusRsp( + rcv.getDataBytes() + ); 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)+" "); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); + for (byte b : rcv.getValue()) { + System.out.print(byteToHex(b) + " "); } return queryRobotRunStatusRsp; - }else { + } + else { System.out.println(); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); throw new RuntimeException("0x17 fail"); } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotStatus.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotStatus.java index 062aede..f5df7f9 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotStatus.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/QryRobotStatus.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 查询机器人状态 - */ public class QryRobotStatus - extends BaseCommand { + extends + BaseCommand { + /** * 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; @@ -31,16 +28,22 @@ public class QryRobotStatus printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); if(rcv.isOk()){ - QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes()); System.out.println(); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); - return queryRobotStatusRsp; -// for (byte b:rcv.getValue()){ -// 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("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); throw new RuntimeException("0xAF fail"); } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubCargoStatus.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubCargoStatus.java index 61eaafa..b1b430f 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubCargoStatus.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubCargoStatus.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 订阅载货状态 - */ -public class SubCargoStatus extends BaseCommand{ +public class SubCargoStatus + extends + BaseCommand { + + public static final int intervalTime = 1000; /** * decs: 下发订阅信息 * 指令:0xB1 * author: caixiang * date: 2025/1/17 16:25 - * */ + */ public static AgvEvent issueSubscribe() { List 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); + SubscribeInfo subscribeInfo = new SubscribeInfo( + new byte[]{(byte) 0xb0, (byte) 0x00}, (short) intervalTime, 10000 + ); subscribeInfoList.add(subscribeInfo); 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; } - public static void command() - { + public static void command() { // 0xB1(订阅信息) AgvEvent agvEvent = issueSubscribe(); printInfo(agvEvent); //todo 订阅参数构建完毕 去写 回调部分 RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { 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()); - if(subscribeRsp.isOk()){ - //... - }else { + if (subscribeRsp.isOk()) { //... } - }else { + else { + //... + } + } + else { 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); //修改载货状态 if (queryCargoStatusRsp.isCargo == 0) { //未载货 - } else if (queryCargoStatusRsp.isCargo == 1) { + } + else if (queryCargoStatusRsp.isCargo == 1) { //载货 } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubRobotStatue.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubRobotStatue.java index c057294..c83e76c 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubRobotStatue.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SubRobotStatue.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 订阅机器人状态 - */ -public class SubRobotStatue extends BaseCommand { +public class SubRobotStatue + extends + BaseCommand { + public static final int intervalTime = 1000; /** * decs: 下发订阅信息 * 指令:0xB1 * author: caixiang * date: 2025/1/17 16:25 - * */ + */ public static AgvEvent issueSubscribe() { List 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); subscribeInfoList.add(subscribeInfo); 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; } @@ -40,18 +42,20 @@ public class SubRobotStatue extends BaseCommand { printInfo(agvEvent); //todo 订阅参数构建完毕 去写 回调部分 RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { 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()); - if(subscribeRsp.isOk()){ - //... - }else { + if (subscribeRsp.isOk()) { //... } - }else { + else { + //... + } + } + else { System.out.println(); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); } } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchAutomaticMode.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchAutomaticMode.java index 5489ef1..de910c3 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchAutomaticMode.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchAutomaticMode.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 切换自动模式 - */ -public class SwitchAutomaticMode extends BaseCommand{ +public class SwitchAutomaticMode + extends + BaseCommand { /** * decs: write操作 * 指令:0x03 * author: caixiang * date: 2025/1/17 16:25 - * */ + */ public static AgvEvent writeValue() { AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE); List 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); List strValueList = new ArrayList<>(); WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList); strValueList.add(strValue); - WriteParam param = new WriteParam(1,strValueList ); + WriteParam param = new WriteParam(1, strValueList); agvEvent.setBody(param.toBytes()); return agvEvent; @@ -47,19 +46,21 @@ public class SwitchAutomaticMode extends BaseCommand{ AgvEvent agvEvent = writeValue(); printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { System.out.println(); - System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:"); + System.out.println("received " + "isok:" + rcv.isOk() + " dataBytes:"); printInfo(rcv); - if(rcv.isOk()){ + if (rcv.isOk()) { //get and parse value System.out.println("write ok"); - }else { + } + else { System.out.println("write failed"); } - }else { + } + else { System.out.println(); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); } } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchManualMode.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchManualMode.java index 3b3a8b4..1d8a306 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchManualMode.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/Service/SwitchManualMode.java @@ -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.io.UDPClient; -/** - * @author xzh - * @date 2025/2/21 - * @desc 切换手动模式 - */ -public class SwitchManualMode extends BaseCommand{ +public class SwitchManualMode + extends + BaseCommand { /** * decs: write操作 * 指令:0x03 * author: caixiang * date: 2025/1/17 16:25 - * */ + */ public static AgvEvent writeValue() { AgvEvent agvEvent = new AgvEvent(AgvEventConstant.CommandCode_WRITE); List 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); List strValueList = new ArrayList<>(); WriteStrValue strValue = new WriteStrValue("TestRW", 1, valueMemberList); strValueList.add(strValue); - WriteParam param = new WriteParam(1,strValueList ); + WriteParam param = new WriteParam(1, strValueList); agvEvent.setBody(param.toBytes()); return agvEvent; @@ -47,19 +46,21 @@ public class SwitchManualMode extends BaseCommand{ AgvEvent agvEvent = writeValue(); printInfo(agvEvent); RcvEventPackage rcv = UDPClient.localAGV.send(agvEvent); - if(rcv.isOk()){ + if (rcv.isOk()) { System.out.println(); - System.out.println("received "+ "isok:"+rcv.isOk()+" dataBytes:"); + System.out.println("received " + "isok:" + rcv.isOk() + " dataBytes:"); printInfo(rcv); - if(rcv.isOk()){ + if (rcv.isOk()) { //get and parse value System.out.println("write ok"); - }else { + } + else { System.out.println("write failed"); } - }else { + } + else { System.out.println(); - System.out.println("received transationId : "+ "isok:"+rcv.isOk()); + System.out.println("received transationId : " + "isok:" + rcv.isOk()); } } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/codec/AgvUdpChannelInitializer.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/codec/AgvUdpChannelInitializer.java index 1804759..0482ac0 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/codec/AgvUdpChannelInitializer.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/codec/AgvUdpChannelInitializer.java @@ -7,20 +7,23 @@ import org.opentcs.kc.udp.io.UDPClient; /** * 作者:蔡翔 */ -public class AgvUdpChannelInitializer extends ChannelInitializer { - private UDPClient client; +public class AgvUdpChannelInitializer + extends + ChannelInitializer { + private UDPClient client; - public AgvUdpChannelInitializer(UDPClient client) { - System.out.println(client.getHost()); - this.client = client; - } + public AgvUdpChannelInitializer(UDPClient client) { + System.out.println(client.getHost()); + this.client = client; + } - @Override - protected void initChannel(NioDatagramChannel channel) throws Exception { - // Modbus - // 在管道中添加我们自己的接收数据实现方法 - //todo 到时候这里改成 FixedLengthFrameDecoder 资料:https://www.cnblogs.com/java-chen-hao/p/11571229.html + @Override + protected void initChannel(NioDatagramChannel channel) + throws Exception { + // Modbus + // 在管道中添加我们自己的接收数据实现方法 + //todo 到时候这里改成 FixedLengthFrameDecoder 资料:https://www.cnblogs.com/java-chen-hao/p/11571229.html // channel.pipeline().addLast( // new LengthFieldBasedFrameDecoder( // 200, @@ -30,7 +33,7 @@ public class AgvUdpChannelInitializer extends ChannelInitializer { +public class AgvUdpDecode + extends + SimpleChannelInboundHandler { - private UDPClient client; + private UDPClient client; - //授权码16字节 + 报文头8个字节 + 报文数据长度2个字节 + 保留2字节 = 28字节 - private static final int HEADER_SIZE = 28; + //授权码16字节 + 报文头8个字节 + 报文数据长度2个字节 + 保留2字节 = 28字节 + private static final int HEADER_SIZE = 28; - public AgvUdpDecode(UDPClient client) { - this.client = client; + public AgvUdpDecode(UDPClient 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 - 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"); - } - - 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); - } - } + int dataLength = in.getShortLE(24); + if (dataLength < 0) { + throw new Exception( + "bodyLength [" + dataLength + "] is not right, remote:" + ctx.channel().remoteAddress() + ); } - @Override - public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) - throws Exception { - cause.printStackTrace(); - ctx.close(); + 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 || 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(); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEvent.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEvent.java index ae20cf1..91715a5 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEvent.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEvent.java @@ -5,89 +5,90 @@ import java.util.Arrays; import java.util.List; 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; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024/12/27 15:59 - */ -public class AgvEvent extends AgvEventHeader implements IAgvEvent, Serializable { - private byte[] bodyLength; - private byte[] retain; - private byte[] body; +public class AgvEvent + extends + AgvEventHeader + implements + IAgvEvent, + Serializable { + private byte[] bodyLength; + private byte[] retain; + private byte[] body; - //for Request - //有content 传,没有content 传new byte[] - public AgvEvent(Byte commandCode) { - super(commandCode); - //初始化 - bodyLength = new byte[]{0x00,0x00}; - retain = new byte[]{0x00,0x00}; - 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; - } - } + //for Request + //有content 传,没有content 传new byte[] + public AgvEvent(Byte commandCode) { + super(commandCode); + //初始化 + bodyLength = new byte[]{0x00, 0x00}; + retain = new byte[]{0x00, 0x00}; + body = new byte[]{}; + } - public void setBody(byte[] body) { - this.bodyLength = ByteUtil.shortToBytes((short) body.length); - this.body = body; + 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; } + } - //for Response - public AgvEvent(Byte serviceCode, Byte commandCode, Byte executionCode) { - super(serviceCode, commandCode, executionCode); - } + public void setBody(byte[] body) { + this.bodyLength = ByteUtil.shortToBytes((short) body.length); + this.body = body; + } - @Override - public Package toBytes() { - List 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()); - } + //for Response + public AgvEvent(Byte serviceCode, Byte commandCode, Byte executionCode) { + super(serviceCode, commandCode, executionCode); + } - public String getTransationIdString() { - return transationId[0]+"-"+transationId[1]; + @Override + public Package toBytes() { + List 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 Package toBytes(Object newValue) { - return null; - } + public String getTransationIdString() { + return transationId[0] + "-" + transationId[1]; + } - @Override - public String toString() { - return "AgvEvent{" + - "Header=" + headerToString() + - ", bodyLength=" + Arrays.toString(bodyLength) + - ", body=" + Arrays.toString(body) + - '}'; - } + @Override + public Package toBytes(Object newValue) { + return null; + } - @Override - public String protocolName() { - return ""; - } + @Override + public String toString() { + return "AgvEvent{" + + "Header=" + headerToString() + + ", bodyLength=" + Arrays.toString(bodyLength) + + ", body=" + Arrays.toString(body) + + '}'; + } + + @Override + public String protocolName() { + return ""; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventConstant.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventConstant.java index afd9d75..5ef0f1e 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventConstant.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventConstant.java @@ -1,38 +1,35 @@ package org.opentcs.kc.udp.agv.param; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024/12/27 10:19 - */ 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 MSGTypeRequest = 0x00; - public static final byte MSGTypeResponse = 0x01; + public static final byte VersionNum = 0x01; + public static final byte MSGTypeRequest = 0x00; + 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_WRITE = 0x03; - 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_CARRY_STATUS = (byte) 0xB0; - public static final byte CommandCode_ISSUE_SUBSCRIPTION = (byte) 0xB1; - public static final byte CommandCode_ACT_IMMEDIATELY = (byte) 0xB2; - public static final byte CommandCode_SET_ABILITY= (byte) 0xB7; - 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_NAVIGATION_CONTROL= (byte) 0x16; - 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_CONFIRM_ROBOT_POSITION= (byte) 0x1F; - //命令码 结束 + public static final byte CommandCode_READ = 0x02; + public static final byte CommandCode_WRITE = 0x03; + 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_CARRY_STATUS = (byte) 0xB0; + public static final byte CommandCode_ISSUE_SUBSCRIPTION = (byte) 0xB1; + public static final byte CommandCode_ACT_IMMEDIATELY = (byte) 0xB2; + public static final byte CommandCode_SET_ABILITY = (byte) 0xB7; + 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_NAVIGATION_CONTROL = (byte) 0x16; + 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_CONFIRM_ROBOT_POSITION = (byte) 0x1F; + //命令码 结束 } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventHeader.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventHeader.java index 8f920c2..8589f8f 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventHeader.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/AgvEventHeader.java @@ -6,107 +6,102 @@ import java.util.List; import org.opentcs.kc.common.CaffeineUtil; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024-06-07 13:29 - */ public class AgvEventHeader { - //常量区域 开始 - //授权码 - public byte[] authorizationCode; - //header 开始 - //版本号 - public byte versionNum; - //报文类型 0x00:请求报文 ; 0x01:应答报文 - public byte msgType; - //request 和 response ,transationId一致,2个字节 - public byte[] transationId; - //服务码 - public byte serviceCode; - //命令码,用于区分不同命令,request 和 response 相同 - public byte commandCode; - //执行码,应答报文填写,表明命令执行情况,请求数据包置 0 - public byte executionCode; - //保留 - public byte retain; + //常量区域 开始 + //授权码 + public byte[] authorizationCode; + //header 开始 + //版本号 + public byte versionNum; + //报文类型 0x00:请求报文 ; 0x01:应答报文 + public byte msgType; + //request 和 response ,transationId一致,2个字节 + public byte[] transationId; + //服务码 + public byte serviceCode; + //命令码,用于区分不同命令,request 和 response 相同 + public byte commandCode; + //执行码,应答报文填写,表明命令执行情况,请求数据包置 0 + public byte executionCode; + //保留 + public byte retain; - //header 结束 - //常量区域 结束 + //header 结束 + //常量区域 结束 - //request - public AgvEventHeader(Byte commandCode) { - this.authorizationCode = AgvEventConstant.AuthorizationCode; - this.versionNum = AgvEventConstant.VersionNum; - this.msgType = AgvEventConstant.MSGTypeRequest; + //request + public AgvEventHeader(Byte commandCode) { + this.authorizationCode = AgvEventConstant.AuthorizationCode; + this.versionNum = AgvEventConstant.VersionNum; + this.msgType = AgvEventConstant.MSGTypeRequest; - this.transationId = CaffeineUtil.getUUIDAGV(); - this.serviceCode = 0x10; - this.commandCode = commandCode; - this.executionCode = 0x00; - this.retain = 0x00; + this.transationId = CaffeineUtil.getUUIDAGV(); + this.serviceCode = 0x10; + this.commandCode = commandCode; + this.executionCode = 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 getHeaderBytes() { + List bytes = new ArrayList<>(); + //add 授权码 + for (byte b : authorizationCode) { + bytes.add(b); } - - 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 getHeaderBytes(){ - List 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; + //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; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/IAgvEvent.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/IAgvEvent.java index 10e2836..b7a0a2b 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/IAgvEvent.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/IAgvEvent.java @@ -1,12 +1,14 @@ package org.opentcs.kc.udp.agv.param; -import org.opentcs.kc.common.byteutils.ByteUtil; import org.opentcs.kc.common.Package; -public interface IAgvEvent { - //read sended - public Package toBytes(); - //write sended - public Package toBytes(Object newValue); +import org.opentcs.kc.common.byteutils.ByteUtil; - public String protocolName(); +public interface IAgvEvent { + //read sended + public Package toBytes(); + + //write sended + public Package toBytes(Object newValue); + + public String protocolName(); } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/AbnormalEventStatusInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/AbnormalEventStatusInfo.java index 4e8d02e..820313e 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/AbnormalEventStatusInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/AbnormalEventStatusInfo.java @@ -2,24 +2,19 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/21 10:03 - */ public class AbnormalEventStatusInfo { - private byte[] src; - //事件码,2个字节 - public byte[] eventCode; - //异常等级,2个字节 - public byte[] abnormalLevel; - //remain,8个字节 - public byte[] remain; + private byte[] src; + //事件码,2个字节 + public byte[] eventCode; + //异常等级,2个字节 + public byte[] abnormalLevel; + //remain,8个字节 + public byte[] remain; - public AbnormalEventStatusInfo(byte[] src) { - this.src = src; - this.eventCode = ByteUtils.copyBytes(src, 0, 2); - this.abnormalLevel = ByteUtils.copyBytes(src, 2, 2); - this.remain = ByteUtils.copyBytes(src, 4, 8); - } + public AbnormalEventStatusInfo(byte[] src) { + this.src = src; + this.eventCode = ByteUtils.copyBytes(src, 0, 2); + this.abnormalLevel = ByteUtils.copyBytes(src, 2, 2); + this.remain = ByteUtils.copyBytes(src, 4, 8); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/ActionInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/ActionInfo.java index 70698b0..5a4c5f7 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/ActionInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/ActionInfo.java @@ -2,24 +2,19 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/21 10:38 - */ public class ActionInfo { - private byte[] src; - //动作 ID,4个字节 - public byte[] actionId; - //动作状态,1个字节 - public byte actionStatus; - //预留,7个字节 - public byte[] remain; + private byte[] src; + //动作 ID,4个字节 + public byte[] actionId; + //动作状态,1个字节 + public byte actionStatus; + //预留,7个字节 + public byte[] remain; - public ActionInfo(byte[] src) { - this.src = src; - this.actionId = ByteUtils.copyBytes(src, 0, 4); - this.actionStatus = src[4]; - this.remain = ByteUtils.copyBytes(src,5,7); - } + public ActionInfo(byte[] src) { + this.src = src; + this.actionId = ByteUtils.copyBytes(src, 0, 4); + this.actionStatus = src[4]; + this.remain = ByteUtils.copyBytes(src, 5, 7); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/BatteryStatusInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/BatteryStatusInfo.java index 385fdc1..5c4b837 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/BatteryStatusInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/BatteryStatusInfo.java @@ -2,34 +2,30 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 16:28 - */ public class BatteryStatusInfo { - //src - private byte[] src; - //电量百分比 - public float batteryPercentage; - //电压 - public float voltage; - //电流 - public float electricCurrent; - //充电情况,1个字节 - public byte chargingState; - //预留,7个字节 - public byte[] remain; - public BatteryStatusInfo(byte[] src) { - this.src = src; - this.batteryPercentage = ByteUtils.bytesToFloat(src, 0); - this.voltage = ByteUtils.bytesToFloat(src, 4); - this.electricCurrent = ByteUtils.bytesToFloat(src, 8); - this.chargingState = src[12]; - this.remain=new byte[7]; - for (int i = 0; i < 7; i++) { - this.remain[i]=src[13+i]; - } + //src + private byte[] src; + //电量百分比 + public float batteryPercentage; + //电压 + public float voltage; + //电流 + public float electricCurrent; + //充电情况,1个字节 + public byte chargingState; + //预留,7个字节 + public byte[] remain; + + public BatteryStatusInfo(byte[] src) { + this.src = src; + this.batteryPercentage = ByteUtils.bytesToFloat(src, 0); + this.voltage = ByteUtils.bytesToFloat(src, 4); + this.electricCurrent = ByteUtils.bytesToFloat(src, 8); + this.chargingState = src[12]; + this.remain = new byte[7]; + for (int i = 0; i < 7; i++) { + this.remain[i] = src[13 + i]; } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/LocationStatusInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/LocationStatusInfo.java index a15f27e..eeadc59 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/LocationStatusInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/LocationStatusInfo.java @@ -2,79 +2,74 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 14:56 - */ public class LocationStatusInfo { - private byte[] src; - //4个字节,车 全局x,单位 m - public float globalX; - //4个字节,车 全局y,单位 m - public float globalY; - //机器人绝对车体方向角,单位 rad - public float absoluteDirecAngle; - //最后通过点 ID - public Integer lastPassPointId; - //最后通过edge ID - public Integer lastPassEdgeId; - //最后通过点在任务中的序列号 - public Integer serialNumber; - //置信度,1个字节 - public byte confidenceLevel; - //预留8个字节 - public byte[] remain; + private byte[] src; + //4个字节,车 全局x,单位 m + public float globalX; + //4个字节,车 全局y,单位 m + public float globalY; + //机器人绝对车体方向角,单位 rad + public float absoluteDirecAngle; + //最后通过点 ID + public Integer lastPassPointId; + //最后通过edge ID + public Integer lastPassEdgeId; + //最后通过点在任务中的序列号 + public Integer serialNumber; + //置信度,1个字节 + public byte confidenceLevel; + //预留8个字节 + public byte[] remain; - public static void main(String[] args) { - byte[] src = new byte[32]; - src[0] = (byte) 0x73; - src[1] = (byte) 0xde; - src[2] = (byte) 0xba; - src[3] = (byte) 0xbd; + public static void main(String[] args) { + byte[] src = new byte[32]; + src[0] = (byte) 0x73; + src[1] = (byte) 0xde; + src[2] = (byte) 0xba; + src[3] = (byte) 0xbd; - src[4] = (byte) 0x34; - src[5] = (byte) 0xbf; - src[6] = (byte) 0xd0; - src[7] = (byte) 0x40; + src[4] = (byte) 0x34; + src[5] = (byte) 0xbf; + src[6] = (byte) 0xd0; + src[7] = (byte) 0x40; - src[8] = (byte) 0x59; - src[9] = (byte) 0x3c; - src[10] = (byte) 0x1d; - src[11] = (byte) 0x3d; - System.out.println("x: "+ByteUtils.bytesToFloat(src, 0)); - System.out.println("y: "+ByteUtils.bytesToFloat(src, 4)); - System.out.println("z: "+ByteUtils.bytesToFloat(src, 8)); + src[8] = (byte) 0x59; + src[9] = (byte) 0x3c; + src[10] = (byte) 0x1d; + src[11] = (byte) 0x3d; + System.out.println("x: " + ByteUtils.bytesToFloat(src, 0)); + System.out.println("y: " + ByteUtils.bytesToFloat(src, 4)); + System.out.println("z: " + ByteUtils.bytesToFloat(src, 8)); + } + + public LocationStatusInfo(byte[] src) { + this.src = src; + for (byte b : src) { + System.out.print(byteToHex(b) + " "); } - - 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] - this.globalX = ByteUtils.bytesToFloat(src, 0); - this.globalY = ByteUtils.bytesToFloat(src, 4); - this.absoluteDirecAngle = ByteUtils.bytesToFloat(src, 8); - this.lastPassPointId = ByteUtils.bytesToInt(src, 12); - 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]; - } + //[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.globalX = ByteUtils.bytesToFloat(src, 0); + this.globalY = ByteUtils.bytesToFloat(src, 4); + this.absoluteDirecAngle = ByteUtils.bytesToFloat(src, 8); + this.lastPassPointId = ByteUtils.bytesToInt(src, 12); + 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) { - // 将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 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; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PathStateSequence.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PathStateSequence.java index 89ab406..3322f2f 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PathStateSequence.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PathStateSequence.java @@ -2,21 +2,17 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 15:49 - */ public class PathStateSequence { - //src - private byte[] src; - //序列号,4个字节 - public Integer serialNumber; - //序列号 - public Integer pathId; - public PathStateSequence(byte[] src) { - this.src = src; - this.serialNumber = ByteUtils.bytesToInt(src, 0); - this.pathId = ByteUtils.bytesToInt(src, 4); - } + //src + private byte[] src; + //序列号,4个字节 + public Integer serialNumber; + //序列号 + public Integer pathId; + + public PathStateSequence(byte[] src) { + this.src = src; + this.serialNumber = ByteUtils.bytesToInt(src, 0); + this.pathId = ByteUtils.bytesToInt(src, 4); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PointStateSequence.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PointStateSequence.java index 8d1c3e8..5128cad 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PointStateSequence.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/PointStateSequence.java @@ -2,21 +2,17 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 15:49 - */ public class PointStateSequence { - //src - private byte[] src; - //序列号,4个字节 - public Integer serialNumber; - //序列号 - public Integer pointId; - public PointStateSequence(byte[] src) { - this.src = src; - this.serialNumber = ByteUtils.bytesToInt(src, 0); - this.pointId = ByteUtils.bytesToInt(src, 4); - } + //src + private byte[] src; + //序列号,4个字节 + public Integer serialNumber; + //序列号 + public Integer pointId; + + public PointStateSequence(byte[] src) { + this.src = src; + this.serialNumber = ByteUtils.bytesToInt(src, 0); + this.pointId = ByteUtils.bytesToInt(src, 4); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/QueryRobotStatusRsp.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/QueryRobotStatusRsp.java index 1e6de1b..01900e1 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/QueryRobotStatusRsp.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/QueryRobotStatusRsp.java @@ -1,50 +1,65 @@ package org.opentcs.kc.udp.agv.param.function.af; +import java.util.ArrayList; import java.util.List; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 14:55 - */ public class QueryRobotStatusRsp { - private byte[] src; - public byte abnormal_size; - public byte action_size; - //预留2个字节 - public byte[] remain; - public LocationStatusInfo locationStatusInfo; - public RunningStatusInfo runningStatusInfo; - public TaskStatusInfo taskStatusInfo; - public BatteryStatusInfo batteryStatusInfo; - public List abnormalEventStatusInfoList; - public List 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;i0){ - for(int i=0;i abnormalEventStatusInfoList; + public List actionInfoList; + 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 + ) + ) + ); + } + } + + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/RunningStatusInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/RunningStatusInfo.java index f9ea826..2b8d49a 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/RunningStatusInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/RunningStatusInfo.java @@ -2,39 +2,34 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 15:22 - */ public class RunningStatusInfo { - private byte[] src; - //4个字节,车 轴x 速度,单位 m/s - public float speedX; - //4个字节,车 轴y 速度,单位 m/s - public float speedY; - //车角速度,单位 rad/s - public float angularSpeed; - //工作模式 - public byte workMode; - //agv 状态,1个字节 - public byte agvStatus; - //机器人能力集设置状态,1个字节 - public byte abilitySetStatus; - //预留,5个字节 - public byte[] remain; + private byte[] src; + //4个字节,车 轴x 速度,单位 m/s + public float speedX; + //4个字节,车 轴y 速度,单位 m/s + public float speedY; + //车角速度,单位 rad/s + public float angularSpeed; + //工作模式 + public byte workMode; + //agv 状态,1个字节 + public byte agvStatus; + //机器人能力集设置状态,1个字节 + public byte abilitySetStatus; + //预留,5个字节 + public byte[] remain; - public RunningStatusInfo(byte[] src) { - this.src = src; - this.speedX = ByteUtils.bytesToFloat(src, 0); - this.speedY = ByteUtils.bytesToFloat(src, 4); - this.angularSpeed = ByteUtils.bytesToFloat(src, 8); - this.workMode = src[12]; - this.agvStatus = src[13]; - this.abilitySetStatus = src[14]; - this.remain = new byte[5]; - for (int i = 0; i < 5; i++) { - this.remain[i] = src[15 + i]; - } + public RunningStatusInfo(byte[] src) { + this.src = src; + this.speedX = ByteUtils.bytesToFloat(src, 0); + this.speedY = ByteUtils.bytesToFloat(src, 4); + this.angularSpeed = ByteUtils.bytesToFloat(src, 8); + this.workMode = src[12]; + this.agvStatus = src[13]; + this.abilitySetStatus = src[14]; + this.remain = new byte[5]; + for (int i = 0; i < 5; i++) { + this.remain[i] = src[15 + i]; } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/TaskStatusInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/TaskStatusInfo.java index d946bef..999e473 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/TaskStatusInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/af/TaskStatusInfo.java @@ -2,48 +2,44 @@ package org.opentcs.kc.udp.agv.param.function.af; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/20 15:22 - */ public class TaskStatusInfo { - private byte[] src; - //订单 ID - public Integer orderId; - //任务 KEY - public Integer taskKey; - //点状态序列数量 - public Integer pointStatusNum; - //段状态序列数量 - public Integer edgeStatusNum; - //预留,2个字节 - public byte[] remain; - //点状态序列 - public PointStateSequence[] pointStatusInfo; - //段状态序列 - public PathStateSequence[] pathStatusInfo; + private byte[] src; + //订单 ID + public Integer orderId; + //任务 KEY + public Integer taskKey; + //点状态序列数量 + public Integer pointStatusNum; + //段状态序列数量 + public Integer edgeStatusNum; + //预留,2个字节 + public byte[] remain; + //点状态序列 + public PointStateSequence[] pointStatusInfo; + //段状态序列 + public PathStateSequence[] pathStatusInfo; - public TaskStatusInfo(byte[] src) { - this.src = src; - this.orderId = ByteUtils.bytesToInt(src, 0); - this.taskKey = ByteUtils.bytesToInt(src, 4); + public TaskStatusInfo(byte[] src) { + this.src = src; + this.orderId = ByteUtils.bytesToInt(src, 0); + this.taskKey = ByteUtils.bytesToInt(src, 4); - this.pointStatusNum = ByteUtils.toInt(src[8]); - this.edgeStatusNum = ByteUtils.toInt(src[9]); - this.remain = ByteUtils.copyBytes(src, 10, 2); - if (pointStatusNum > 0) { - this.pointStatusInfo = new PointStateSequence[pointStatusNum]; - for (int i = 0; i < pointStatusNum; i++) { - 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)); - } - } + this.pointStatusNum = ByteUtils.toInt(src[8]); + this.edgeStatusNum = ByteUtils.toInt(src[9]); + this.remain = ByteUtils.copyBytes(src, 10, 2); + if (pointStatusNum > 0) { + this.pointStatusInfo = new PointStateSequence[pointStatusNum]; + for (int i = 0; i < pointStatusNum; i++) { + 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) + ); + } + } + } } - diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b0/QueryCargoStatusRsp.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b0/QueryCargoStatusRsp.java index 44d463a..b7539fb 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b0/QueryCargoStatusRsp.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b0/QueryCargoStatusRsp.java @@ -2,22 +2,17 @@ package org.opentcs.kc.udp.agv.param.function.b0; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/23 13:34 - */ public class QueryCargoStatusRsp { - //src - private byte[] src; - //是否载货 - public byte isCargo; - //预留,3个字节 - public byte[] reserved; + //src + private byte[] src; + //是否载货 + public byte isCargo; + //预留,3个字节 + public byte[] reserved; - public QueryCargoStatusRsp(byte[] src) { - this.src = src; - this.isCargo = src[0]; - this.reserved = ByteUtils.copyBytes(src, 1, 3); - } + public QueryCargoStatusRsp(byte[] src) { + this.src = src; + this.isCargo = src[0]; + this.reserved = ByteUtils.copyBytes(src, 1, 3); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeInfo.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeInfo.java index 29c9b23..68ab311 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeInfo.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeInfo.java @@ -2,25 +2,20 @@ package org.opentcs.kc.udp.agv.param.function.b1; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/23 14:30 - */ public class SubscribeInfo { - //站控协议命令码,2个字节 - public byte[] commandCode; - //上报间隔时间 ,单位ms ,2个字节 - public byte[] intervalTime; - //上报持续时间,单位ms ,4个字节 - public byte[] durationTime; - //预留,8个字节 - public byte[] reserved; + //站控协议命令码,2个字节 + public byte[] commandCode; + //上报间隔时间 ,单位ms ,2个字节 + public byte[] intervalTime; + //上报持续时间,单位ms ,4个字节 + public byte[] durationTime; + //预留,8个字节 + public byte[] reserved; - public SubscribeInfo(byte[] commandCode, Short intervalTime, Integer durationTime) { - this.commandCode = commandCode; - this.intervalTime = ByteUtils.shortToBytes(intervalTime); - this.durationTime = ByteUtils.intToBytes(durationTime,4); - this.reserved = new byte[8]; - } + public SubscribeInfo(byte[] commandCode, Short intervalTime, Integer durationTime) { + this.commandCode = commandCode; + this.intervalTime = ByteUtils.shortToBytes(intervalTime); + this.durationTime = ByteUtils.intToBytes(durationTime, 4); + this.reserved = new byte[8]; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeParam.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeParam.java index 02a7b21..ddf108a 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeParam.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeParam.java @@ -4,67 +4,63 @@ import java.security.SecureRandom; import java.util.ArrayList; import java.util.List; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/1/23 14:23 - */ public class SubscribeParam { - private byte[] src; - private List subscribeInfoList; - //uuid,64个字节 - private byte[] uuid; - public SubscribeParam(List subscribeInfoList) { - this.subscribeInfoList = subscribeInfoList; - this.uuid = generate64ByteUUID(); + private byte[] src; + private List subscribeInfoList; + //uuid,64个字节 + private byte[] uuid; + + public SubscribeParam(List subscribeInfoList) { + 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 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() { - return uuid; + 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]; } - // 生成 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 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; - } + return src; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeRsp.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeRsp.java index 6b808ec..eaabde5 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeRsp.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/b1/SubscribeRsp.java @@ -2,32 +2,29 @@ package org.opentcs.kc.udp.agv.param.function.b1; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/5 14:21 - */ public class SubscribeRsp { - //源数组 - private byte[] src; - //uuid 64个字节 - private byte[] uuid; - //errCode 1个字节 - private byte errCode; - //reserved 3个字节 - 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); - } + //源数组 + private byte[] src; + //uuid 64个字节 + private byte[] uuid; + //errCode 1个字节 + private byte errCode; + //reserved 3个字节 + private byte[] reserved; - public boolean isOk(){ - if(this.errCode==0){ - return true; - }else { - return false; - } + 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() { + if (this.errCode == 0) { + return true; } + else { + return false; + } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Action.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Action.java index c628dcc..3d9e6b3 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Action.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Action.java @@ -4,50 +4,47 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/8 10:05 - */ public class Action { - //动作类型,2个字节 - private byte[] actionType; - //执行动作并行方式,1个字节 - private byte actionParallel; - //预留,1个字节 - private byte actionRetain; - //动作 id,4个字节,actionId 自己定义不要重复就行,可以从0开始累加 - private byte[] actionId; - //参数长度,1个字节 - private byte paramSize; - //预留,3个字节 - private byte[] paramRetain2; - //参数内容,这里的长度 是 paramSize 长度,todo 注意 这里的paramContent 需要字节去构建一下 ,目前 这里还没有 - private byte[] paramContent; + //动作类型,2个字节 + private byte[] actionType; + //执行动作并行方式,1个字节 + private byte actionParallel; + //预留,1个字节 + private byte actionRetain; + //动作 id,4个字节,actionId 自己定义不要重复就行,可以从0开始累加 + private byte[] actionId; + //参数长度,1个字节 + private byte paramSize; + //预留,3个字节 + private byte[] paramRetain2; + //参数内容,这里的长度 是 paramSize 长度,todo 注意 这里的paramContent 需要字节去构建一下 ,目前 这里还没有 + private byte[] paramContent; - public Action(byte actionType, byte actionParallel, Integer actionId, Integer paramSize, byte[] paramContent) { - this.actionType = new byte[]{actionType, (byte)0x00}; - this.actionParallel = actionParallel; - this.actionRetain = (byte)0x00; - this.actionId = ByteUtils.intToBytes(actionId,1); - this.paramSize = ByteUtils.usintTo1Byte(paramSize); - this.paramRetain2 = new byte[]{(byte)0x00, (byte)0x00,(byte)0x00}; - this.paramContent = paramContent; - } + public Action( + byte actionType, byte actionParallel, Integer actionId, Integer paramSize, byte[] paramContent + ) { + this.actionType = new byte[]{actionType, (byte) 0x00}; + this.actionParallel = actionParallel; + this.actionRetain = (byte) 0x00; + this.actionId = ByteUtils.intToBytes(actionId, 1); + this.paramSize = ByteUtils.usintTo1Byte(paramSize); + this.paramRetain2 = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00}; + this.paramContent = paramContent; + } - public byte[] toBytes() { - ByteBuf byteBuf = Unpooled.buffer(); - byteBuf.writeBytes(actionType); - byteBuf.writeByte(actionParallel); - byteBuf.writeByte(actionRetain); - byteBuf.writeBytes(actionId); - byteBuf.writeByte(paramSize); - byteBuf.writeBytes(paramRetain2); - byteBuf.writeBytes(paramContent); - int i = byteBuf.writerIndex(); - byte[] bytes = new byte[i]; - byteBuf.readBytes(bytes); - return bytes; - } + public byte[] toBytes() { + ByteBuf byteBuf = Unpooled.buffer(); + byteBuf.writeBytes(actionType); + byteBuf.writeByte(actionParallel); + byteBuf.writeByte(actionRetain); + byteBuf.writeBytes(actionId); + byteBuf.writeByte(paramSize); + byteBuf.writeBytes(paramRetain2); + byteBuf.writeBytes(paramContent); + int i = byteBuf.writerIndex(); + byte[] bytes = new byte[i]; + byteBuf.readBytes(bytes); + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/ActionSet.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/ActionSet.java index 0aad093..d76058a 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/ActionSet.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/ActionSet.java @@ -4,74 +4,71 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/10 8:56 - */ public class ActionSet { - public static void main(String[] args) { - byte[] stop = stop0x01(1, (byte) 0x01); - System.out.println(); - } + public static void main(String[] args) { + byte[] stop = stop0x01(1, (byte) 0x01); + System.out.println(); + } - public static byte stop0x01 = 0x01; - public static byte recover0x02 = 0x02; - public static byte cancelTask0x03 = 0x03; - public static byte forkliftElevation0x12 = 0x12; - public static byte trayElevation0x16 = 0x16; + public static byte stop0x01 = 0x01; + public static byte recover0x02 = 0x02; + public static byte cancelTask0x03 = 0x03; + public static byte forkliftElevation0x12 = 0x12; + public static byte trayElevation0x16 = 0x16; - public static Integer stop0x01_paramsize = 8; - public static Integer recover0x02_paramsize = 8; - public static Integer cancelTask0x03_paramsize = 8; - public static Integer forkliftElevation0x12_paramsize = 8; - public static Integer trayElevation0x16_paramsize = 4; + public static Integer stop0x01_paramsize = 8; + public static Integer recover0x02_paramsize = 8; + public static Integer cancelTask0x03_paramsize = 8; + public static Integer forkliftElevation0x12_paramsize = 8; + public static Integer trayElevation0x16_paramsize = 4; - public static byte[] stop0x01(Integer orderId,byte isStopImmediately){ - ByteBuf byteBuf = Unpooled.buffer(8); - byteBuf.writeBytes(ByteUtils.intToBytes(orderId,1)); - byteBuf.writeByte(isStopImmediately); - return byteBuf.array(); - } + public static byte[] stop0x01(Integer orderId, byte isStopImmediately) { + ByteBuf byteBuf = Unpooled.buffer(8); + byteBuf.writeBytes(ByteUtils.intToBytes(orderId, 1)); + byteBuf.writeByte(isStopImmediately); + return byteBuf.array(); + } - public static byte[] recover0x02(Integer orderId,Integer taskKey){ - ByteBuf byteBuf = Unpooled.buffer(8); - byteBuf.writeBytes(ByteUtils.intToBytes(orderId,1)); - byteBuf.writeBytes(ByteUtils.intToBytes(taskKey,1)); - return byteBuf.array(); - } + public static byte[] recover0x02(Integer orderId, Integer taskKey) { + ByteBuf byteBuf = Unpooled.buffer(8); + byteBuf.writeBytes(ByteUtils.intToBytes(orderId, 1)); + byteBuf.writeBytes(ByteUtils.intToBytes(taskKey, 1)); + return byteBuf.array(); + } - //取消任务 - public static byte[] cancelTask0x03(Integer orderId,byte isStopImmediately){ - ByteBuf byteBuf = Unpooled.buffer(8); - byteBuf.writeBytes(ByteUtils.intToBytes(orderId,1)); - byteBuf.writeByte(isStopImmediately); - return byteBuf.array(); - } + //取消任务 + public static byte[] cancelTask0x03(Integer orderId, byte isStopImmediately) { + ByteBuf byteBuf = Unpooled.buffer(8); + byteBuf.writeBytes(ByteUtils.intToBytes(orderId, 1)); + byteBuf.writeByte(isStopImmediately); + return byteBuf.array(); + } - /** - * desc:叉齿升降 - * 支持的命令:0xAE 0xB2 - * - * */ + /** + * desc:叉齿升降 + * 支持的命令:0xAE 0xB2 + * + */ - public static byte[] forkliftElevation0x12(float lifitingHeight,byte hightMean,byte moveType, byte taskOperationType){ - ByteBuf byteBuf = Unpooled.buffer(8); - byteBuf.writeBytes(ByteUtils.floatToBytes(lifitingHeight)); - byteBuf.writeByte(hightMean); - byteBuf.writeByte(moveType); - byteBuf.writeByte(taskOperationType); - return byteBuf.array(); - } + public static byte[] forkliftElevation0x12( + float lifitingHeight, byte hightMean, byte moveType, byte taskOperationType + ) { + ByteBuf byteBuf = Unpooled.buffer(8); + byteBuf.writeBytes(ByteUtils.floatToBytes(lifitingHeight)); + byteBuf.writeByte(hightMean); + byteBuf.writeByte(moveType); + byteBuf.writeByte(taskOperationType); + return byteBuf.array(); + } - //托盘升降 - public static byte[] trayElevation0x16(byte palletMovementMode){ - ByteBuf byteBuf = Unpooled.buffer(4); - byteBuf.writeByte(palletMovementMode); - return byteBuf.array(); - } + //托盘升降 + public static byte[] trayElevation0x16(byte palletMovementMode) { + ByteBuf byteBuf = Unpooled.buffer(4); + byteBuf.writeByte(palletMovementMode); + return byteBuf.array(); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/NavigationParam.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/NavigationParam.java index b2532a0..03c85c6 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/NavigationParam.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/NavigationParam.java @@ -4,54 +4,51 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "0xAE 导航参数" - * @Author: caixiang - * @DATE: 2024/12/30 15:44 - */ public class NavigationParam { - //订单 ID,4个字节 ,Integer,从1开始依次累加 - private byte[] orderId; - //任务 KEY,4个字节,Integer,从1开始依次累加 - private byte[] taskKey; - //路径点信息个数(单条任务最大支持 8 个路径点),1个字节 ,byte - private byte pointNum; - //路径信息个数(单条任务最大支持 8 个路径点),1个字节,byte - private byte pathNum; - //保留,2个字节 - private byte[] retain; - //任务中路径点信息结构体,长度 pointNum - private Point[] points; - //任务中路径信息结构体,长度 pathNum - private Path[] paths; + //订单 ID,4个字节 ,Integer,从1开始依次累加 + private byte[] orderId; + //任务 KEY,4个字节,Integer,从1开始依次累加 + private byte[] taskKey; + //路径点信息个数(单条任务最大支持 8 个路径点),1个字节 ,byte + private byte pointNum; + //路径信息个数(单条任务最大支持 8 个路径点),1个字节,byte + private byte pathNum; + //保留,2个字节 + private byte[] retain; + //任务中路径点信息结构体,长度 pointNum + private Point[] points; + //任务中路径信息结构体,长度 pathNum + private Path[] paths; - public NavigationParam(Integer orderId, Integer taskKey, byte pointNum, byte pathNum, Point[] points, Path[] paths) { - this.orderId = ByteUtils.intToBytes(orderId,1); - this.taskKey = ByteUtils.intToBytes(taskKey,1); - this.pointNum = pointNum; - this.pathNum = pathNum; - this.retain = new byte[]{(byte)0x00, (byte)0x00}; - this.points = points; - this.paths = paths; + public NavigationParam( + Integer orderId, Integer taskKey, byte pointNum, byte pathNum, Point[] points, Path[] paths + ) { + this.orderId = ByteUtils.intToBytes(orderId, 1); + this.taskKey = ByteUtils.intToBytes(taskKey, 1); + this.pointNum = pointNum; + this.pathNum = pathNum; + 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()); } - - 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) { - byteBuf.writeBytes(path.toBytes()); - } - int i = byteBuf.writerIndex(); - byte[] bytes = new byte[i]; - byteBuf.readBytes(bytes); - return bytes; + for (Path path : paths) { + byteBuf.writeBytes(path.toBytes()); } + int i = byteBuf.writerIndex(); + byte[] bytes = new byte[i]; + byteBuf.readBytes(bytes); + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Path.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Path.java index 2b60b5e..be53c99 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Path.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Path.java @@ -4,71 +4,71 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/8 9:39 - */ public class Path { - //序列号,4个字节,Integer,用于定位段在整个任务中的位置,从 1 开始奇数递增(如 1、3、5......)(point 2 4 6,这样path 和point就可以结合起来了),以区分同一个段 ID 在任务中是否多次出现 - private byte[] serialNum; - //段 ID,4个字节,Integer - private byte[] pathId; - //指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效 - private byte[] angle; - //是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定 - private byte isSpecifyAngle; + //序列号,4个字节,Integer,用于定位段在整个任务中的位置,从 1 开始奇数递增(如 1、3、5......)(point 2 4 6,这样path 和point就可以结合起来了),以区分同一个段 ID 在任务中是否多次出现 + private byte[] serialNum; + //段 ID,4个字节,Integer + private byte[] pathId; + //指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效 + private byte[] angle; + //是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定 + private byte isSpecifyAngle; - //行驶姿态,1个字节,byte - private byte drivePose; - //任务中边上动作信息个数,1个字节,byte - private byte pathActionSize; - //保留,1个字节 - private byte pathRetain; - //指定的目标最大速度,4个字节,float - private byte[] maxSpeed; - //指定的目标最大角速度,4个字节,float - private byte[] maxAngularSpeed; - //预留,4个字节 - private byte[] pathRetain2; + //行驶姿态,1个字节,byte + private byte drivePose; + //任务中边上动作信息个数,1个字节,byte + private byte pathActionSize; + //保留,1个字节 + private byte pathRetain; + //指定的目标最大速度,4个字节,float + private byte[] maxSpeed; + //指定的目标最大角速度,4个字节,float + private byte[] maxAngularSpeed; + //预留,4个字节 + private byte[] pathRetain2; - //任务中点上动作结构体,这里数组的长度是 pathActionSize 长度 - private Action[] actions; + //任务中点上动作结构体,这里数组的长度是 pathActionSize 长度 + private Action[] actions; - public Path(Integer serialNum, Integer pathId, float angle, byte isSpecifyAngle, byte drivePose, byte pathActionSize, float maxSpeed, float maxAngularSpeed, Action[] actions) { - this.serialNum = ByteUtils.intToBytes(serialNum,1); - this.pathId = ByteUtils.intToBytes(pathId,1); - this.angle = ByteUtils.floatToBytes(angle); - this.isSpecifyAngle = isSpecifyAngle; - this.drivePose = drivePose; - this.pathActionSize = pathActionSize; - this.pathRetain = (byte)0x00; - this.maxSpeed = ByteUtils.floatToBytes(maxSpeed); - this.maxAngularSpeed = ByteUtils.floatToBytes(maxAngularSpeed); - this.pathRetain2 = new byte[]{(byte)0x00, (byte)0x00,(byte)0x00,(byte)0x00}; - this.actions = actions; - } - - public byte[] toBytes() { - ByteBuf byteBuf = Unpooled.buffer(); - byteBuf.writeBytes(serialNum); - byteBuf.writeBytes(pathId); - byteBuf.writeBytes(angle); - byteBuf.writeByte(isSpecifyAngle); - byteBuf.writeByte(drivePose); - byteBuf.writeByte(pathActionSize); - byteBuf.writeByte(pathRetain); - byteBuf.writeBytes(maxSpeed); - byteBuf.writeBytes(maxAngularSpeed); - byteBuf.writeBytes(pathRetain2); - for (Action action : actions) { - byteBuf.writeBytes(action.toBytes()); - } - int i = byteBuf.writerIndex(); - byte[] bytes = new byte[i]; - byteBuf.readBytes(bytes); - return bytes; + public Path( + Integer serialNum, Integer pathId, float angle, byte isSpecifyAngle, byte drivePose, + byte pathActionSize, float maxSpeed, float maxAngularSpeed, Action[] actions + ) { + this.serialNum = ByteUtils.intToBytes(serialNum, 1); + this.pathId = ByteUtils.intToBytes(pathId, 1); + this.angle = ByteUtils.floatToBytes(angle); + this.isSpecifyAngle = isSpecifyAngle; + this.drivePose = drivePose; + this.pathActionSize = pathActionSize; + this.pathRetain = (byte) 0x00; + this.maxSpeed = ByteUtils.floatToBytes(maxSpeed); + this.maxAngularSpeed = ByteUtils.floatToBytes(maxAngularSpeed); + this.pathRetain2 = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00}; + this.actions = actions; + } + + public byte[] toBytes() { + ByteBuf byteBuf = Unpooled.buffer(); + byteBuf.writeBytes(serialNum); + byteBuf.writeBytes(pathId); + byteBuf.writeBytes(angle); + byteBuf.writeByte(isSpecifyAngle); + byteBuf.writeByte(drivePose); + byteBuf.writeByte(pathActionSize); + byteBuf.writeByte(pathRetain); + byteBuf.writeBytes(maxSpeed); + byteBuf.writeBytes(maxAngularSpeed); + byteBuf.writeBytes(pathRetain2); + if (actions != null) { + for (Action action : actions) { + byteBuf.writeBytes(action.toBytes()); + } } + int i = byteBuf.writerIndex(); + byte[] bytes = new byte[i]; + byteBuf.readBytes(bytes); + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Point.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Point.java index 74a945a..e776733 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Point.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/navigation/Point.java @@ -4,51 +4,52 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/8 9:39 - */ public class Point { - //序列号,4个字节,Integer,用于定位点在整个任务中的位置,从 0 开始偶数递增(如 0、2、4、6......),以区分同一个点 ID 在任务中是否多次出现 - private byte[] serialNum; - //路径点 ID,4个字节,Integer - private byte[] pointId; - //指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效 - private byte[] angle; - //是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定 - private byte isSpecifyAngle; - //任务中点上动作信息个数,1个字节,byte - private byte pointActionSize; - //保留,6个字节 - private byte[] pointRetain; - //任务中点上动作结构体,这里数组的长度是 pointActionSize 长度 - private Action[] actions; + //序列号,4个字节,Integer,用于定位点在整个任务中的位置,从 0 开始偶数递增(如 0、2、4、6......),以区分同一个点 ID 在任务中是否多次出现 + private byte[] serialNum; + //路径点 ID,4个字节,Integer + private byte[] pointId; + //指定角度时路径点的车头角度,4个字节,float ,当 isSpecifyAngle==1 的时候这个字段才生效 + private byte[] angle; + //是否指定路径点角度,1个字节,byte,1 表示指定,0 表示不指定 + private byte isSpecifyAngle; + //任务中点上动作信息个数,1个字节,byte + private byte pointActionSize; + //保留,6个字节 + private byte[] pointRetain; + //任务中点上动作结构体,这里数组的长度是 pointActionSize 长度 + private Action[] actions; - public Point(Integer serialNum, Integer pointId, float angle, byte isSpecifyAngle, byte pointActionSize, Action[] actions) { - this.serialNum = ByteUtils.intToBytes(serialNum,1); - this.pointId = ByteUtils.intToBytes(pointId,1); - this.angle = ByteUtils.floatToBytes(angle); - 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 Point( + Integer serialNum, Integer pointId, float angle, byte isSpecifyAngle, byte pointActionSize, + Action[] actions + ) { + this.serialNum = ByteUtils.intToBytes(serialNum, 1); + this.pointId = ByteUtils.intToBytes(pointId, 1); + this.angle = ByteUtils.floatToBytes(angle); + 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() { - ByteBuf byteBuf = Unpooled.buffer(); - byteBuf.writeBytes(serialNum); - byteBuf.writeBytes(pointId); - byteBuf.writeBytes(angle); - byteBuf.writeByte(isSpecifyAngle); - byteBuf.writeByte(pointActionSize); - byteBuf.writeBytes(pointRetain); - for (Action action : actions) { - byteBuf.writeBytes(action.toBytes()); - } - int i = byteBuf.writerIndex(); - byte[] bytes = new byte[i]; - byteBuf.readBytes(bytes); - return bytes; + public byte[] toBytes() { + ByteBuf byteBuf = Unpooled.buffer(); + byteBuf.writeBytes(serialNum); + byteBuf.writeBytes(pointId); + byteBuf.writeBytes(angle); + byteBuf.writeByte(isSpecifyAngle); + byteBuf.writeByte(pointActionSize); + byteBuf.writeBytes(pointRetain); + if (actions != null) { + for (Action action : actions) { + byteBuf.writeBytes(action.toBytes()); + } } + int i = byteBuf.writerIndex(); + byte[] bytes = new byte[i]; + byteBuf.readBytes(bytes); + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadParam.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadParam.java index ed7ff78..f183054 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadParam.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadParam.java @@ -4,48 +4,44 @@ import java.util.ArrayList; import java.util.List; import org.opentcs.kc.common.byteutils.ByteUtil; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024/12/30 15:44 - */ public class ReadParam { - private byte valueNum; - private byte[] retain; - private byte[] valueId; - private byte[] readStrValues; - public ReadParam(byte[] valueId, List rvalues) { - // 这里的valueId 也是 header里面的 transationId - valueNum = ByteUtil.intTo1Byte(rvalues.size()); - retain = new byte[]{0x00,0x00,0x00}; + private byte valueNum; + private byte[] retain; + private byte[] valueId; + private byte[] readStrValues; - this.valueId = new byte[]{valueId[0],valueId[1],0x00,0x00}; - List bytes = new ArrayList<>(); - for (ReadStrValue b : rvalues) { - bytes.addAll(b.toBytes()); - } - readStrValues = new byte[bytes.size()]; - for (int i = 0; i < bytes.size(); i++) { - readStrValues[i] = bytes.get(i); - } - } + public ReadParam(byte[] valueId, List rvalues) { + // 这里的valueId 也是 header里面的 transationId + valueNum = ByteUtil.intTo1Byte(rvalues.size()); + retain = new byte[]{0x00, 0x00, 0x00}; - public byte[] toBytes() { - List 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; + this.valueId = new byte[]{valueId[0], valueId[1], 0x00, 0x00}; + List bytes = new ArrayList<>(); + for (ReadStrValue b : rvalues) { + bytes.addAll(b.toBytes()); } + readStrValues = new byte[bytes.size()]; + for (int i = 0; i < bytes.size(); i++) { + readStrValues[i] = bytes.get(i); + } + } + + public byte[] toBytes() { + List 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; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadRsp.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadRsp.java index 00c6034..98cfc1f 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadRsp.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadRsp.java @@ -2,36 +2,32 @@ package org.opentcs.kc.udp.agv.param.function.read; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/5 14:55 - */ public class ReadRsp { - //源数组 - private byte[] src; - //ValueID ,4个字节 - public byte[] valueId; - //应答数据总长度,2个字节 - public short valueByteLength; - //预留,2个字节 - public byte[] reserved; - //变量值,长度是 valueByteLength - public byte[] dataValue; + //源数组 + private byte[] src; + //ValueID ,4个字节 + public byte[] valueId; + //应答数据总长度,2个字节 + public short valueByteLength; + //预留,2个字节 + public byte[] reserved; + //变量值,长度是 valueByteLength + public byte[] dataValue; - public ReadRsp(byte[] src) { - this.src = src; - this.valueId = ByteUtils.copyBytes(src, 0, 4); - this.valueByteLength = ByteUtils.bytesToShort(ByteUtils.copyBytes(src, 4, 2),1); - this.reserved = ByteUtils.copyBytes(src, 6, 2); - this.dataValue = ByteUtils.copyBytes(src, 8, valueByteLength-8); - } + public ReadRsp(byte[] src) { + this.src = src; + this.valueId = ByteUtils.copyBytes(src, 0, 4); + this.valueByteLength = ByteUtils.bytesToShort(ByteUtils.copyBytes(src, 4, 2), 1); + this.reserved = ByteUtils.copyBytes(src, 6, 2); + this.dataValue = ByteUtils.copyBytes(src, 8, valueByteLength - 8); + } - public boolean isOk(){ - if(valueByteLength<=0){ - return false; - }else { - return true; - } + public boolean isOk() { + if (valueByteLength <= 0) { + return false; } + else { + return true; + } + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadStrValue.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadStrValue.java index a24ec96..fc7bb93 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadStrValue.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadStrValue.java @@ -4,46 +4,43 @@ import java.util.ArrayList; import java.util.List; import org.opentcs.kc.common.byteutils.ByteUtil; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024/12/30 15:46 - */ public class ReadStrValue { - //变量名,16个字节( 以这个变量名来定位变量的) - private byte[] varName; - //成员变量数量,4个字节 - private byte[] memberVarNum; - private byte[] memberList; - public ReadStrValue(String varName, Integer memberVarNum, List memberList) { - this.varName = ByteUtil.stringTo16Byte(varName); - this.memberVarNum = ByteUtil.intToBytes(memberVarNum); - List 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]; - } + //变量名,16个字节( 以这个变量名来定位变量的) + private byte[] varName; + //成员变量数量,4个字节 + private byte[] memberVarNum; + private byte[] memberList; - public List toBytes() { - List 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; + public ReadStrValue(String varName, Integer memberVarNum, List memberList) { + this.varName = ByteUtil.stringTo16Byte(varName); + this.memberVarNum = ByteUtil.intToBytes(memberVarNum); + List 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 toBytes() { + List 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; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadValueMember.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadValueMember.java index 6921279..9fc301f 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadValueMember.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/read/ReadValueMember.java @@ -4,31 +4,26 @@ import java.util.ArrayList; import java.util.List; import org.opentcs.kc.common.byteutils.ByteUtil; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2024/12/30 15:49 - */ public class ReadValueMember { - //偏移值,就是以这个变量的起始点为基准,偏移几个字节,来读取数组里的后面几个变量,基本上用于数组变量,单体变量用不着 2个字节 - private byte[] offsetValue; - //变量成员长度,就是你要读取的content长度,可以是1个变量的长度,也可以是n个变量的长度(就是数据类型 的字节长度) - private byte[] memberVarLength; + //偏移值,就是以这个变量的起始点为基准,偏移几个字节,来读取数组里的后面几个变量,基本上用于数组变量,单体变量用不着 2个字节 + private byte[] offsetValue; + //变量成员长度,就是你要读取的content长度,可以是1个变量的长度,也可以是n个变量的长度(就是数据类型 的字节长度) + private byte[] memberVarLength; - public ReadValueMember(Short offsetValue, Short memberVarLength) { - this.offsetValue = ByteUtil.shortToBytes(offsetValue); - this.memberVarLength = ByteUtil.shortToBytes(memberVarLength); - } + public ReadValueMember(Short offsetValue, Short memberVarLength) { + this.offsetValue = ByteUtil.shortToBytes(offsetValue); + this.memberVarLength = ByteUtil.shortToBytes(memberVarLength); + } - public List toBytes() { - List bytes = new ArrayList<>(); - for (byte b : offsetValue) { - bytes.add(b); - } - for (byte b : memberVarLength) { - bytes.add(b); - } - return bytes; + public List toBytes() { + List bytes = new ArrayList<>(); + for (byte b : offsetValue) { + bytes.add(b); } + for (byte b : memberVarLength) { + bytes.add(b); + } + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteParam.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteParam.java index 49e2873..a2a2b89 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteParam.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteParam.java @@ -5,35 +5,31 @@ import io.netty.buffer.Unpooled; import java.util.List; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/5 16:41 - */ public class WriteParam { - //变量数量 1个字节 ,最大只支持 15 个变量 - private byte valueNum; - //保留 3个字节 - private byte[] retain; - //这里的length 就是 valueNum - private List values; - public WriteParam(Integer valueNum, List values) { - this.valueNum = ByteUtils.usintTo1Byte(valueNum); - this.retain = new byte[]{(byte)0x00,(byte)0x00,(byte)0x00}; - this.values = values; - } + //变量数量 1个字节 ,最大只支持 15 个变量 + private byte valueNum; + //保留 3个字节 + private byte[] retain; + //这里的length 就是 valueNum + private List values; - public byte[] toBytes() { - ByteBuf byteBuf = Unpooled.buffer(); - byteBuf.writeByte(valueNum); - byteBuf.writeBytes(retain); - for (WriteStrValue value : values) { - byteBuf.writeBytes(value.toBytes()); - } - int i = byteBuf.writerIndex(); - byte[] bytes = new byte[i]; - byteBuf.readBytes(bytes); - return bytes; + public WriteParam(Integer valueNum, List values) { + this.valueNum = ByteUtils.usintTo1Byte(valueNum); + this.retain = new byte[]{(byte) 0x00, (byte) 0x00, (byte) 0x00}; + this.values = values; + } + + public byte[] toBytes() { + ByteBuf byteBuf = Unpooled.buffer(); + byteBuf.writeByte(valueNum); + byteBuf.writeBytes(retain); + for (WriteStrValue value : values) { + byteBuf.writeBytes(value.toBytes()); } + int i = byteBuf.writerIndex(); + byte[] bytes = new byte[i]; + byteBuf.readBytes(bytes); + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteStrValue.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteStrValue.java index 2c443fc..aa2977b 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteStrValue.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteStrValue.java @@ -5,37 +5,32 @@ import io.netty.buffer.Unpooled; import java.util.List; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/5 16:43 - */ public class WriteStrValue { - //变量名 16个字节 - private String valueName; - //变量成员数量 4个字节 - private Integer valueNum; - private List members; + //变量名 16个字节 + private String valueName; + //变量成员数量 4个字节 + private Integer valueNum; + private List members; - public WriteStrValue(String valueName, Integer valueNum, List members) { - this.valueName = valueName; - this.valueNum = valueNum; - this.members = members; + public WriteStrValue(String valueName, Integer valueNum, List members) { + this.valueName = valueName; + this.valueNum = valueNum; + 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() { - 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; - } + return bytes; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteValueMember.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteValueMember.java index b38e39f..417895d 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteValueMember.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/write/WriteValueMember.java @@ -4,29 +4,25 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/5 16:44 - */ public class WriteValueMember { - //变量成员偏移 2个字节 - private byte[] valueOffset; - //变量成员长度 2个字节 - private byte[] valueLength; - //变量成员值 4个字节 - private byte[] newValue; - public WriteValueMember(Short valueOffset, Short valueLength, byte[] newValue) { - this.valueOffset = ByteUtils.shortToBytes(valueOffset); - this.valueLength = ByteUtils.shortToBytes(valueLength); - this.newValue = newValue; - } + //变量成员偏移 2个字节 + private byte[] valueOffset; + //变量成员长度 2个字节 + private byte[] valueLength; + //变量成员值 4个字节 + private byte[] newValue; - public byte[] toBytes() { - ByteBuf byteBuf = Unpooled.buffer(8); - byteBuf.writeBytes(valueOffset); - byteBuf.writeBytes(valueLength); - byteBuf.writeBytes(newValue); - return byteBuf.array(); - } + public WriteValueMember(Short valueOffset, Short valueLength, byte[] newValue) { + this.valueOffset = ByteUtils.shortToBytes(valueOffset); + this.valueLength = ByteUtils.shortToBytes(valueLength); + this.newValue = newValue; + } + + public byte[] toBytes() { + ByteBuf byteBuf = Unpooled.buffer(8); + byteBuf.writeBytes(valueOffset); + byteBuf.writeBytes(valueLength); + byteBuf.writeBytes(newValue); + return byteBuf.array(); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x14/RobotSetPosition.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x14/RobotSetPosition.java index dc0ce35..867d1e2 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x14/RobotSetPosition.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x14/RobotSetPosition.java @@ -4,29 +4,25 @@ import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import org.opentcs.kc.common.byteutils.ByteUtil; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/7 9:21 - */ public class RobotSetPosition { - //机器人 x 坐标 ,8 个字节 - private byte[] robotX; - //机器人 y 坐标 ,8 个字节 - private byte[] robotY; - //机器人朝向角度 ,8 个字节 - private byte[] robotAngle; + //机器人 x 坐标 ,8 个字节 + private byte[] robotX; + //机器人 y 坐标 ,8 个字节 + private byte[] robotY; + //机器人朝向角度 ,8 个字节 + private byte[] robotAngle; - public RobotSetPosition(double robotX, double robotY, double robotAngle) { - this.robotX = ByteUtil.doubleToBytes(robotX); - this.robotY = ByteUtil.doubleToBytes(robotY); - this.robotAngle = ByteUtil.doubleToBytes(robotAngle); - } - public byte[] toBytes() { - ByteBuf byteBuf = Unpooled.buffer(24); - byteBuf.writeBytes(robotX); - byteBuf.writeBytes(robotY); - byteBuf.writeBytes(robotAngle); - return byteBuf.array(); - } + public RobotSetPosition(double robotX, double robotY, double robotAngle) { + this.robotX = ByteUtil.doubleToBytes(robotX); + this.robotY = ByteUtil.doubleToBytes(robotY); + this.robotAngle = ByteUtil.doubleToBytes(robotAngle); + } + + public byte[] toBytes() { + ByteBuf byteBuf = Unpooled.buffer(24); + byteBuf.writeBytes(robotX); + byteBuf.writeBytes(robotY); + byteBuf.writeBytes(robotAngle); + return byteBuf.array(); + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x17/QueryRobotRunStatusRsp.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x17/QueryRobotRunStatusRsp.java index 5262090..43876a4 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x17/QueryRobotRunStatusRsp.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/function/x17/QueryRobotRunStatusRsp.java @@ -3,128 +3,123 @@ package org.opentcs.kc.udp.agv.param.function.x17; import java.util.Arrays; import org.opentcs.kc.common.byteutils.ByteUtils; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2025/2/7 9:43 - */ public class QueryRobotRunStatusRsp { - //本体温度 ,8个字节 ,double - private double temp; - //位置的 X 坐标 , 8个字节 ,double - private double currentX; - //位置的 Y 坐标,8个字节 ,double - private double currentY; - //位置的 角度 ,8个字节 ,double - private double currentAngle; - //电池电量,,8个字节 ,double - private double battery; - //是否被阻挡,1个字节,byte - private byte isBlocked; - //是否在充电,1个字节,byte - private byte isCharging; - //运行模式,1个字节,byte - private byte runMode; - //地图载入状态,1个字节,byte - private byte mapLoadState; - //当前的目标点 id,U32 ,4个字节 - private Integer currentTargetId; + //本体温度 ,8个字节 ,double + private double temp; + //位置的 X 坐标 , 8个字节 ,double + private double currentX; + //位置的 Y 坐标,8个字节 ,double + private double currentY; + //位置的 角度 ,8个字节 ,double + private double currentAngle; + //电池电量,,8个字节 ,double + private double battery; + //是否被阻挡,1个字节,byte + private byte isBlocked; + //是否在充电,1个字节,byte + private byte isCharging; + //运行模式,1个字节,byte + private byte runMode; + //地图载入状态,1个字节,byte + private byte mapLoadState; + //当前的目标点 id,U32 ,4个字节 + private Integer currentTargetId; - //前进速度,8个字节,double - private double forwardSpeed; - //转弯速度,8个字节,double - private double turnSpeed; - //电池电压(充电为正,放电为负),8个字节,double - private double batteryVoltage; - //电流(充电为正,放电为负),double - private double electricCurrent; - //当前任务状态,1个字节,byte - private byte taskState; - //保留,1个字节 - private byte retain1; - //地图版本号,2个字节 - private short mapVersion; - //保留,4个字节 - private byte[] retain2; - //累计行驶里程(单位 m),8个字节 - private double cumulativeMileage; - //本次运行时间(单位 ms),8个字节 - private double currentRunTime; - //累计运行时间(单位 ms),8个字节 - private double cumulativeRunTime; - //机器人定位状态,1个字节 - public byte robotLocalizationState; - //保留,3个字节 - private byte[] retain3; - //地图数量,U32,4个字节 - private Integer mapNum; - //当前地图名称,64字节 - private String currentMapName; - //置信度,4个字节 - private float confidence; - //保留,4个字节 - private byte[] retain4; + //前进速度,8个字节,double + private double forwardSpeed; + //转弯速度,8个字节,double + private double turnSpeed; + //电池电压(充电为正,放电为负),8个字节,double + private double batteryVoltage; + //电流(充电为正,放电为负),double + private double electricCurrent; + //当前任务状态,1个字节,byte + private byte taskState; + //保留,1个字节 + private byte retain1; + //地图版本号,2个字节 + private short mapVersion; + //保留,4个字节 + private byte[] retain2; + //累计行驶里程(单位 m),8个字节 + private double cumulativeMileage; + //本次运行时间(单位 ms),8个字节 + private double currentRunTime; + //累计运行时间(单位 ms),8个字节 + private double cumulativeRunTime; + //机器人定位状态,1个字节 + public byte robotLocalizationState; + //保留,3个字节 + private byte[] retain3; + //地图数量,U32,4个字节 + private Integer mapNum; + //当前地图名称,64字节 + private String currentMapName; + //置信度,4个字节 + private float confidence; + //保留,4个字节 + private byte[] retain4; - public QueryRobotRunStatusRsp(byte[] src) { - this.temp = ByteUtils.bytesToDouble(src, 0); - this.currentX = ByteUtils.bytesToDouble(src, 8); - this.currentY = ByteUtils.bytesToDouble(src, 16); - this.currentAngle = ByteUtils.bytesToDouble(src, 24); - this.battery = ByteUtils.bytesToDouble(src, 32); - this.isBlocked = src[40]; - this.isCharging = src[41]; - this.runMode = src[42]; - this.mapLoadState = src[43]; - this.currentTargetId = ByteUtils.bytesToInt(src, 44); - this.forwardSpeed = ByteUtils.bytesToDouble(src, 48); - this.turnSpeed = ByteUtils.bytesToDouble(src, 56); - this.batteryVoltage = ByteUtils.bytesToDouble(src, 64); - this.electricCurrent = ByteUtils.bytesToDouble(src, 72); - this.taskState = src[80]; - this.retain1 = src[81]; - this.mapVersion = ByteUtils.bytesToShortLitt(src, 82); - this.retain2 = ByteUtils.copyBytes(src, 84, 4); - this.cumulativeMileage = ByteUtils.bytesToDouble(src, 88); - this.currentRunTime = ByteUtils.bytesToDouble(src, 96); - this.cumulativeRunTime = ByteUtils.bytesToDouble(src, 104); - this.robotLocalizationState = src[112]; - this.retain3 = ByteUtils.copyBytes(src, 113, 3); - this.mapNum = ByteUtils.bytesToInt(src, 116); - this.currentMapName = ByteUtils.bytesToString(src, 120, 64); - this.confidence = ByteUtils.bytesToFloat(src, 184); - this.retain4 = ByteUtils.copyBytes(src, 188, 4); - } + public QueryRobotRunStatusRsp(byte[] src) { + this.temp = ByteUtils.bytesToDouble(src, 0); + this.currentX = ByteUtils.bytesToDouble(src, 8); + this.currentY = ByteUtils.bytesToDouble(src, 16); + this.currentAngle = ByteUtils.bytesToDouble(src, 24); + this.battery = ByteUtils.bytesToDouble(src, 32); + this.isBlocked = src[40]; + this.isCharging = src[41]; + this.runMode = src[42]; + this.mapLoadState = src[43]; + this.currentTargetId = ByteUtils.bytesToInt(src, 44); + this.forwardSpeed = ByteUtils.bytesToDouble(src, 48); + this.turnSpeed = ByteUtils.bytesToDouble(src, 56); + this.batteryVoltage = ByteUtils.bytesToDouble(src, 64); + this.electricCurrent = ByteUtils.bytesToDouble(src, 72); + this.taskState = src[80]; + this.retain1 = src[81]; + this.mapVersion = ByteUtils.bytesToShortLitt(src, 82); + this.retain2 = ByteUtils.copyBytes(src, 84, 4); + this.cumulativeMileage = ByteUtils.bytesToDouble(src, 88); + this.currentRunTime = ByteUtils.bytesToDouble(src, 96); + this.cumulativeRunTime = ByteUtils.bytesToDouble(src, 104); + this.robotLocalizationState = src[112]; + this.retain3 = ByteUtils.copyBytes(src, 113, 3); + this.mapNum = ByteUtils.bytesToInt(src, 116); + this.currentMapName = ByteUtils.bytesToString(src, 120, 64); + this.confidence = ByteUtils.bytesToFloat(src, 184); + this.retain4 = ByteUtils.copyBytes(src, 188, 4); + } - @Override - public String toString() { - return "QueryRobotRunStatusRsp{" + - "temp=" + temp + - ", currentX=" + currentX + - ", currentY=" + currentY + - ", currentAngle=" + currentAngle + - ", battery=" + battery + - ", isBlocked=" + isBlocked + - ", isCharging=" + isCharging + - ", runMode=" + runMode + - ", mapLoadState=" + mapLoadState + - ", currentTargetId=" + currentTargetId + - ", forwardSpeed=" + forwardSpeed + - ", turnSpeed=" + turnSpeed + - ", batteryVoltage=" + batteryVoltage + - ", electricCurrent=" + electricCurrent + - ", taskState=" + taskState + - ", retain1=" + retain1 + - ", mapVersion=" + mapVersion + - ", retain2=" + Arrays.toString(retain2) + - ", cumulativeMileage=" + cumulativeMileage + - ", cuttentRunTime=" + currentRunTime + - ", cumulativeRunTime=" + cumulativeRunTime + - ", robotLocalizationState=" + robotLocalizationState + - ", retain3=" + Arrays.toString(retain3) + - ", mapNum=" + mapNum + - ", currentMapName='" + currentMapName + '\'' + - ", confidence=" + confidence + - ", retain4=" + Arrays.toString(retain4) + - '}'; - } + @Override + public String toString() { + return "QueryRobotRunStatusRsp{" + + "temp=" + temp + + ", currentX=" + currentX + + ", currentY=" + currentY + + ", currentAngle=" + currentAngle + + ", battery=" + battery + + ", isBlocked=" + isBlocked + + ", isCharging=" + isCharging + + ", runMode=" + runMode + + ", mapLoadState=" + mapLoadState + + ", currentTargetId=" + currentTargetId + + ", forwardSpeed=" + forwardSpeed + + ", turnSpeed=" + turnSpeed + + ", batteryVoltage=" + batteryVoltage + + ", electricCurrent=" + electricCurrent + + ", taskState=" + taskState + + ", retain1=" + retain1 + + ", mapVersion=" + mapVersion + + ", retain2=" + Arrays.toString(retain2) + + ", cumulativeMileage=" + cumulativeMileage + + ", cuttentRunTime=" + currentRunTime + + ", cumulativeRunTime=" + cumulativeRunTime + + ", robotLocalizationState=" + robotLocalizationState + + ", retain3=" + Arrays.toString(retain3) + + ", mapNum=" + mapNum + + ", currentMapName='" + currentMapName + '\'' + + ", confidence=" + confidence + + ", retain4=" + Arrays.toString(retain4) + + '}'; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/rsp/RcvEventPackage.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/rsp/RcvEventPackage.java index 38d2438..35d5351 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/rsp/RcvEventPackage.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/agv/param/rsp/RcvEventPackage.java @@ -4,86 +4,90 @@ package org.opentcs.kc.udp.agv.param.rsp; import org.opentcs.kc.common.byteutils.ByteUtils; import org.opentcs.kc.udp.agv.param.AgvEventHeader; -/** - * @Desc: "通用的数据传输底层类" - * @Author: caixiang - * @DATE: 2022/10/18 16:22 - */ public class RcvEventPackage { - private boolean isOk; - private byte[] value; - private String content; - // header size = 授权码16 + 报文头12(包括报文数据长度2个字节+保留2个字节) = 28 - private AgvEventHeader header; - private byte[] dataBytes; + private boolean isOk; + private byte[] value; + private String content; + // header size = 授权码16 + 报文头12(包括报文数据长度2个字节+保留2个字节) = 28 + private AgvEventHeader header; + private byte[] dataBytes; - private String getContent(byte i) { - if(i==0x00){ - return "成功执行"; - }else if(i==0x01){ - return "执行失败,原因未知"; - }else if(i==0x02){ - return "服务码错误"; - }else if(i==0x03){ - return "命令码错误"; - }else if(i==0x04){ - return "报文头部错误"; - }else if(i==0x80){ - return "无法执行命令,因为当前车辆导航状态与命令冲突"; - }else if(i==0xFF){ - return "协议授权码错误"; - }else { - return "未知错误"; - } - + private String getContent(byte i) { + if (i == 0x00) { + return "成功执行"; + } + else if (i == 0x01) { + return "执行失败,原因未知"; + } + else if (i == 0x02) { + return "服务码错误"; + } + else if (i == 0x03) { + return "命令码错误"; + } + else if (i == 0x04) { + 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() { - return isOk; + 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 void setValue(byte[] value) { - this.value = value; - } + public RcvEventPackage() { + } - public byte[] getValue() { - return value; - } + public boolean isOk() { + return isOk; + } - public String getContent() { - return content; - } + public void setValue(byte[] value) { + this.value = value; + } - public AgvEventHeader getHeader() { - return header; - } + public byte[] getValue() { + return value; + } - public byte[] getDataBytes() { - return dataBytes; - } + public String getContent() { + return content; + } - @Override - public String toString() { - return "RcvPackage{" + - "isOk=" + isOk + - ", value=" + value + - ", content='" + content + '\'' + - '}'; - } + public AgvEventHeader getHeader() { + return header; + } + + public byte[] getDataBytes() { + return dataBytes; + } + + @Override + public String toString() { + return "RcvPackage{" + + "isOk=" + isOk + + ", value=" + value + + ", content='" + content + '\'' + + '}'; + } } diff --git a/opentcs-common/src/main/java/org/opentcs/kc/udp/io/UDPClient.java b/opentcs-common/src/main/java/org/opentcs/kc/udp/io/UDPClient.java index 78ba303..59a6dbd 100644 --- a/opentcs-common/src/main/java/org/opentcs/kc/udp/io/UDPClient.java +++ b/opentcs-common/src/main/java/org/opentcs/kc/udp/io/UDPClient.java @@ -9,6 +9,7 @@ import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.DatagramPacket; import io.netty.channel.socket.nio.NioDatagramChannel; import java.net.InetSocketAddress; +import java.util.HashMap; import java.util.Set; import org.opentcs.access.KernelServicePortal; 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.LoggerFactory; -/** - * @Desc: "" - * @Author: caixiang - * @DATE: 2022/1/15 13:01 - */ public enum UDPClient { - //如果要配置多个链接, local1 local2 .... 这样排下去好了 + //如果要配置多个链接, local1 local2 .... 这样排下去好了 - localAGV("1","192.168.0.211",17804,55678), - //local("127.0.0.1",502,true), - ; + localAGV("50", "192.168.124.124", 17804, 55678), + ; - // 服务端地址+端口 - private String SERVICE_HOST = "192.168.0.123"; - private Integer SERVICE_PORT = 1099; + // 服务端用户名+密码+地址+端口 + private String SERVICE_USER = GuestUserCredentials.USER; + private String SERVICE_PWD = GuestUserCredentials.PASSWORD; + private String SERVICE_HOST = GuestUserCredentials.IP; + private Integer SERVICE_PORT = GuestUserCredentials.PORT; - private String name; - private String host; - //默认 0 port - private Integer port; - private Integer bindPort; - private Bootstrap bootstrap; - private NioEventLoopGroup group; + private String name; + private String host; + //默认 0 port + private Integer port; + private Integer bindPort; + private Bootstrap bootstrap; + private NioEventLoopGroup group; - private Channel conn; - private boolean isOnline; + private Channel conn; + 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 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 是线程池的数量 - 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 void subscribeKC(RcvEventPackage rcv, byte[] body) { + if (rcv.isOk()) { + KernelServicePortal servicePortal = new KernelServicePortalBuilder( + SERVICE_USER, SERVICE_PWD + ).build(); + servicePortal.login(SERVICE_HOST, SERVICE_PORT); + VehicleService vehicleService = servicePortal.getVehicleService(); + Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name); + vehicleService.sendCommAdapterMessage(vehicle.getReference(), body); + servicePortal.logout(); + } + else { + System.out.println(); + System.out.println("subscribe received transationId : " + "isok:" + rcv.isOk()); + } + } + + 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(){ - return this.host; + public void subscribe0xAF(RcvEventPackage rcv, byte[] body) { + + if (rcv.isOk()) { + this.achieveSub0xAF(body); } - public String getName(){ - return this.name; - } - 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 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()); - } + else { + System.out.println(); + System.out.println("subscribe0xAF received transationId : " + "isok:" + rcv.isOk()); } + } /** * 0xAF上报信息传入通讯适配器 - * @param vehicleName 车辆名称 - * @param rcv 响应数据 + * + * @param body 响应数据 */ - private void achieveSub0xAF(String vehicleName ,RcvEventPackage rcv){ - - QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes()); - - System.out.println(); - System.out.println("received subscribe 0xAF List : "+ "isok:"+rcv.isOk()); - for (byte b:rcv.getValue()){ - System.out.print(byteToHex(b)+" "); - } - - KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER, GuestUserCredentials.PASSWORD).build(); - servicePortal.login(SERVICE_HOST, SERVICE_PORT); - VehicleService vehicleService = servicePortal.getVehicleService(); - Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, vehicleName); - //将AGV控制器上报信息传入通讯适配器 - vehicleService.sendCommAdapterMessage(vehicle.getReference(), queryRobotStatusRsp); - - servicePortal.logout(); - } + private void achieveSub0xAF(byte[] body) { +// QueryRobotStatusRsp queryRobotStatusRsp = new QueryRobotStatusRsp(rcv.getDataBytes()); + KernelServicePortal servicePortal = new KernelServicePortalBuilder( + SERVICE_USER, SERVICE_PWD + ).build(); + servicePortal.login(SERVICE_HOST, SERVICE_PORT); + VehicleService vehicleService = servicePortal.getVehicleService(); + Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, name); + vehicleService.sendCommAdapterMessage(vehicle.getReference(), body); + } /** * 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()); - System.out.println(); - System.out.println("received subscribe 0xB0 List : "+ "isok:"+rcv.isOk()); - for (byte b:rcv.getValue()){ - System.out.print(byteToHex(b)+" "); - } +// QueryCargoStatusRsp queryCargoStatusRsp = new QueryCargoStatusRsp(rcv.getDataBytes()); +// System.out.println(); +// System.out.println("received subscribe 0xB0 List : " + "isok:" + rcv.isOk()); +// for (byte b : rcv.getValue()) { +// System.out.print(byteToHex(b) + " "); +// } - KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER, GuestUserCredentials.PASSWORD).build(); - servicePortal.login(SERVICE_HOST, SERVICE_PORT); - VehicleService vehicleService = servicePortal.getVehicleService(); - Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, vehicleName); - //将AGV控制器上报信息传入通讯适配器 - vehicleService.sendCommAdapterMessage(vehicle.getReference(), queryCargoStatusRsp); + KernelServicePortal servicePortal = new KernelServicePortalBuilder( + SERVICE_USER, SERVICE_PWD + ).build(); + servicePortal.login(SERVICE_HOST, SERVICE_PORT); + VehicleService vehicleService = servicePortal.getVehicleService(); + 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){ - System.out.println("sended transationId : "+agvEvent.getTransationIdString()); - 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() { - @Override - protected void initChannel(NioDatagramChannel ch) throws Exception { - ChannelPipeline pipeline = ch.pipeline(); - //0 代表禁用 readerIdleTime 事件的监听 - //这两个是固定的 - //pipeline.addLast(new IdleStateHandler(0,0,10, TimeUnit.SECONDS)); + //将AGV控制器上报信息传入通讯适配器 + vehicleService.sendCommAdapterMessage(vehicle.getReference(), body); - //协议层的handler 这里要做以区分 + servicePortal.logout(); + } - 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()); - } + public static void printInfo(AgvEvent agvEvent) { + System.out.println("sended transationId : " + agvEvent.getTransationIdString()); + 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() { + @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()); + } + } } diff --git a/opentcs-common/src/test/java/org/opentcs/common/SameThreadExecutorServiceTest.java b/opentcs-common/src/test/java/org/opentcs/common/SameThreadExecutorServiceTest.java index 36868c4..507b158 100644 --- a/opentcs-common/src/test/java/org/opentcs/common/SameThreadExecutorServiceTest.java +++ b/opentcs-common/src/test/java/org/opentcs/common/SameThreadExecutorServiceTest.java @@ -86,40 +86,46 @@ class SameThreadExecutorServiceTest { verify(task).call(); } - @Test - void testVehicle(){ - //获取车辆对象代码 - KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER,GuestUserCredentials.PASSWORD).build(); - servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT); -// servicePortal.getPlantModelService().up - PlantModelService plantModelService = servicePortal.getPlantModelService(); - VehicleService vehicleService = servicePortal.getVehicleService(); - Set vehicles = vehicleService.fetchObjects(Vehicle.class); - for (Vehicle vehicle : vehicles) { - System.out.println("vehicle:"+vehicle); - } - } + /* + * @Test + * void testVehicle() { + * //获取车辆对象代码 + * KernelServicePortal servicePortal = new KernelServicePortalBuilder( + * GuestUserCredentials.USER, GuestUserCredentials.PASSWORD + * ).build(); + * servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT); + * // servicePortal.getPlantModelService().up + * PlantModelService plantModelService = servicePortal.getPlantModelService(); + * VehicleService vehicleService = servicePortal.getVehicleService(); + * Set vehicles = vehicleService.fetchObjects(Vehicle.class); + * for (Vehicle vehicle : vehicles) { + * System.out.println("vehicle:" + vehicle); + * } + * } + */ - @Test - void testRemoveVehicle(){ + @Test + void testRemoveVehicle() { - HashMap map = new HashMap<>(); - int energy = 54; - map.put("energy", energy); - long positionX = -100; - map.put("positionX", positionX); - long positionY = 6510; - map.put("positionY", positionY); - double positionAngle = 0.0; - map.put("positionAngle", positionAngle); + HashMap map = new HashMap<>(); + int energy = 52; + map.put("energy", energy); + long positionX = 3040; + map.put("positionX", positionX); + long positionY = -40; + map.put("positionY", positionY); + double positionAngle = 0.0; + map.put("positionAngle", positionAngle); - //向车辆对应的通讯适配器发送消息 - KernelServicePortal servicePortal = new KernelServicePortalBuilder(GuestUserCredentials.USER,GuestUserCredentials.PASSWORD).build(); - servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT); - VehicleService vehicleService = servicePortal.getVehicleService(); - Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "2"); - vehicleService.sendCommAdapterMessage(vehicle.getReference(), map); + //向车辆对应的通讯适配器发送消息 + KernelServicePortal servicePortal = new KernelServicePortalBuilder( + GuestUserCredentials.USER, GuestUserCredentials.PASSWORD + ).build(); + servicePortal.login(GuestUserCredentials.IP, GuestUserCredentials.PORT); + VehicleService vehicleService = servicePortal.getVehicleService(); + Vehicle vehicle = vehicleService.fetchObject(Vehicle.class, "50"); + vehicleService.sendCommAdapterMessage(vehicle.getReference(), map); - } + } } diff --git a/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java b/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java index c74327b..ec05511 100644 --- a/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java +++ b/opentcs-modeleditor/src/guiceConfig/java/org/opentcs/modeleditor/DefaultPropertySuggestions.java @@ -42,6 +42,7 @@ public class DefaultPropertySuggestions keySuggestions.add(LoopbackAdapterConstants.AGV_AUTHORIZE_CODE); keySuggestions.add(LoopbackAdapterConstants.AGV_IP); keySuggestions.add(LoopbackAdapterConstants.AGV_PORT); + keySuggestions.add(LoopbackAdapterConstants.POINT_TYPE); } @Override