You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@plc4x.apache.org by sr...@apache.org on 2022/08/01 15:00:56 UTC

[plc4x] 03/04: feat(plc-simulator/cbus): implement proper option support

This is an automated email from the ASF dual-hosted git repository.

sruehl pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/plc4x.git

commit 8ddb301752193e2c4de6bcdce260eacaa7a101fc
Author: Sebastian Rühl <sr...@apache.org>
AuthorDate: Mon Aug 1 16:50:52 2022 +0200

    feat(plc-simulator/cbus): implement proper option support
---
 .../org/apache/plc4x/simulator/PlcSimulator.java   |   2 +-
 .../server/cbus/protocol/CBusServerAdapter.java    | 201 ++++++++++++++++-----
 2 files changed, 161 insertions(+), 42 deletions(-)

diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
index 43dc0ae27..579a3e209 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/PlcSimulator.java
@@ -153,7 +153,7 @@ public class PlcSimulator {
         CommandLine cmd = parser.parse(options, args);
 
         // Map options
-        config.host = cmd.getOptionValue("--host", "localhost");
+        config.host = cmd.getOptionValue("host", "localhost");
 
         return config;
     }
diff --git a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/protocol/CBusServerAdapter.java b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/protocol/CBusServerAdapter.java
index 2f33c7f56..593678061 100644
--- a/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/protocol/CBusServerAdapter.java
+++ b/sandbox/plc-simulator/src/main/java/org/apache/plc4x/simulator/server/cbus/protocol/CBusServerAdapter.java
@@ -38,56 +38,37 @@ public class CBusServerAdapter extends ChannelInboundHandlerAdapter {
     private Context context;
 
     private static final RequestContext requestContext = new RequestContext(false, false, false);
-    private static final CBusOptions cBusOptions = new CBusOptions(false, false, false, false, false, false, false, false, true);
 
-    private Lock writeLock = new ReentrantLock();
+    private static boolean connect;
+    private static boolean smart;
+    private static boolean idmon;
+    private static boolean exstat;
+    private static boolean monitor;
+    private static boolean monall;
+    private static boolean pun;
+    private static boolean pcn;
+    private static boolean srchk;
+    private static CBusOptions cBusOptions;
+
+    private final Lock writeLock = new ReentrantLock();
 
     private ScheduledFuture<?> sf;
 
     public CBusServerAdapter(Context context) {
         this.context = context;
+        cBusOptions = new CBusOptions(connect, smart, idmon, exstat, monitor, monall, pun, pcn, srchk);
     }
 
-    @Override
-    public void channelActive(ChannelHandlerContext ctx) throws Exception {
-        super.channelActive(ctx);
-        sf = ctx.executor().scheduleAtFixedRate(() -> {
-            try {
-                writeLock.lock();
-                MonitoredSAL monitoredSAL;
-                if (cBusOptions.getExstat()) {
-                    // TODO implement long from
-                    throw new IllegalStateException("Not implemented");
-                } else {
-                    LightingData lightingData;
-                    double random = Math.random();
-                    if (random < 0.25) {
-                        lightingData = new LightingDataOn(LightingCommandTypeContainer.LightingCommandOn, (byte) 0xAF);
-                    } else if (random > 0.25 && random < 0.5) {
-                        lightingData = new LightingDataOff(LightingCommandTypeContainer.LightingCommandOff, (byte) 0xAF);
-                    } else if (random > 0.5 && random < 0.75) {
-                        lightingData = new LightingDataRampToLevel(LightingCommandTypeContainer.LightingCommandRampToLevel_20Second, (byte) 0xAF, (byte) 0xE0);
-                    } else {
-                        lightingData = new LightingDataTerminateRamp(LightingCommandTypeContainer.LightingCommandTerminateRamp, (byte) 0xAF);
-                    }
-                    SALData salData = new SALDataLighting(null, lightingData);
-                    monitoredSAL = new MonitoredSALShortFormBasicMode((byte) 0x0, (byte) 0x0, (short) 0x0, (short) 0x0, (byte) 0x0, ApplicationIdContainer.LIGHTING_38, salData, cBusOptions);
-                }
-                EncodedReply encodedReply = new MonitoredSALReply((byte) 0x0, monitoredSAL, cBusOptions, requestContext);
-                Reply reply = new ReplyEncodedReply((byte) 0x0, encodedReply, null, cBusOptions, requestContext);
-                ReplyOrConfirmation replyOrConfirmation = new ReplyOrConfirmationReply((byte) 0x00, reply, new ResponseTermination(), cBusOptions, requestContext);
-                CBusMessage message = new CBusMessageToClient(replyOrConfirmation, requestContext, cBusOptions);
-                LOGGER.info("[Monitor] Sending out\n{}\n{}", message, encodedReply);
-                ctx.writeAndFlush(message);
-            } finally {
-                writeLock.unlock();
-            }
-        }, 5, 5, TimeUnit.SECONDS);
+    private static void buildCBusOptions() {
+        LOGGER.info("Updating options {}", cBusOptions);
+        cBusOptions = new CBusOptions(connect, smart, idmon, exstat, monitor, monall, pun, pcn, srchk);
+        LOGGER.info("Updated options {}", cBusOptions);
     }
 
     @Override
     public void channelInactive(ChannelHandlerContext ctx) throws Exception {
-        sf.cancel(false);
+        if (sf != null)
+            sf.cancel(false);
         super.channelInactive(ctx);
     }
 
@@ -111,8 +92,81 @@ public class CBusServerAdapter extends ChannelInboundHandlerAdapter {
             }
             if (request instanceof RequestDirectCommandAccess) {
                 RequestDirectCommandAccess requestDirectCommandAccess = (RequestDirectCommandAccess) request;
-                LOGGER.info("Handling RequestDirectCommandAccess\n{}", requestDirectCommandAccess);
-                // TODO: handle this
+                CALData calData = requestDirectCommandAccess.getCalData();
+                LOGGER.info("Handling RequestDirectCommandAccess\n{}\n{}", requestDirectCommandAccess, calData);
+
+                // TODO: handle other cal data type
+                if (calData instanceof CALDataWrite) {
+                    CALDataWrite calDataWrite = (CALDataWrite) calData;
+                    switch (calDataWrite.getParamNo().getParameterType()) {
+                        case APPLICATION_ADDRESS_1:
+                            // TODO: check settings for subscription etc.
+                            return;
+                        case APPLICATION_ADDRESS_2:
+                            // TODO: check settings for subscription etc.
+                            return;
+                        case INTERFACE_OPTIONS_1:
+                            InterfaceOptions1 interfaceOptions1 = ((ParameterValueInterfaceOptions1) calDataWrite.getParameterValue()).getValue();
+                            idmon = interfaceOptions1.getIdmon();
+                            monitor = interfaceOptions1.getMonitor();
+                            if (monitor) startMonitor(ctx);
+                            else stopMonitor();
+                            smart = interfaceOptions1.getSmart();
+                            srchk = interfaceOptions1.getSrchk();
+                            // TODO: add support for xonxoff
+                            // xonxoff = interfaceOptions1.getXonXoff();
+                            connect = interfaceOptions1.getConnect();
+                            buildCBusOptions();
+                            return;
+                        case INTERFACE_OPTIONS_2:
+                            InterfaceOptions2 interfaceOptions2 = ((ParameterValueInterfaceOptions2) calDataWrite.getParameterValue()).getValue();
+                            // TODO: add support for burden
+                            // burden =  interfaceOptions2.getBurden();
+                            // TODO: add support for clockgen
+                            // clockgen = interfaceOptions2.getClockGen();
+                            buildCBusOptions();
+                            return;
+                        case INTERFACE_OPTIONS_3:
+                            InterfaceOptions3 interfaceOptions3Value = ((ParameterValueInterfaceOptions3) calDataWrite.getParameterValue()).getValue();
+                            exstat = interfaceOptions3Value.getExstat();
+                            pun = interfaceOptions3Value.getPun();
+                            // TODO: add support for localsal
+                            // localsal = interfaceOptions3Value.getLocalSal();
+                            pcn = interfaceOptions3Value.getPcn();
+                            buildCBusOptions();
+                            return;
+                        case BAUD_RATE_SELECTOR:
+                            BaudRateSelector baudRateSelector = ((ParameterValueBaudRateSelector) calDataWrite.getParameterValue()).getValue();
+                            // TODO: add support for baudrate
+                            // baudrate = baudRateSelector.getValue();
+                            buildCBusOptions();
+                            return;
+                        case INTERFACE_OPTIONS_1_POWER_UP_SETTINGS:
+                            InterfaceOptions1 interfaceOptions1PowerUpSettings = ((ParameterValueInterfaceOptions1PowerUpSettings) calDataWrite.getParameterValue()).getValue().getInterfaceOptions1();
+                            idmon = interfaceOptions1PowerUpSettings.getIdmon();
+                            monitor = interfaceOptions1PowerUpSettings.getMonitor();
+                            if (monitor) startMonitor(ctx);
+                            else stopMonitor();
+                            smart = interfaceOptions1PowerUpSettings.getSmart();
+                            srchk = interfaceOptions1PowerUpSettings.getSrchk();
+                            // TODO: add support for xonxoff
+                            // xonxoff = interfaceOptions1PowerUpSettings.getXonXoff();
+                            connect = interfaceOptions1PowerUpSettings.getConnect();
+                            buildCBusOptions();
+                            return;
+                        case CUSTOM_MANUFACTURER:
+                            // TODO: handle other parm typed
+                            return;
+                        case SERIAL_NUMBER:
+                            // TODO: handle other parm typed
+                            return;
+                        case CUSTOM_TYPE:
+                            // TODO: handle other parm typed
+                            return;
+                        default:
+                            throw new IllegalStateException("Unmapped type");
+                    }
+                }
                 return;
             }
             if (request instanceof RequestCommand) {
@@ -223,7 +277,15 @@ public class CBusServerAdapter extends ChannelInboundHandlerAdapter {
             if (request instanceof RequestReset) {
                 RequestReset requestReset = (RequestReset) request;
                 LOGGER.info("Handling RequestReset\n{}", requestReset);
-                // TODO: handle this
+                connect = false;
+                smart = false;
+                idmon = false;
+                exstat = false;
+                monitor = false;
+                monall = false;
+                pun = false;
+                pcn = false;
+                srchk = false;
                 return;
             }
             if (request instanceof RequestSmartConnectShortcut) {
@@ -237,4 +299,61 @@ public class CBusServerAdapter extends ChannelInboundHandlerAdapter {
         }
     }
 
+    private void startMonitor(ChannelHandlerContext ctx) {
+        if (sf != null) {
+            LOGGER.debug("Monitor already running");
+            return;
+        }
+        LOGGER.info("Starting monitor");
+        sf = ctx.executor().scheduleAtFixedRate(() -> {
+            try {
+                writeLock.lock();
+                MonitoredSAL monitoredSAL;
+                if (cBusOptions.getExstat()) {
+                    LightingData lightingData;
+                    double random = Math.random();
+                    if (random < 0.25) {
+                        lightingData = new LightingDataOn(LightingCommandTypeContainer.LightingCommandOn, (byte) 0xAF);
+                    } else if (random > 0.25 && random < 0.5) {
+                        lightingData = new LightingDataOff(LightingCommandTypeContainer.LightingCommandOff, (byte) 0xAF);
+                    } else if (random > 0.5 && random < 0.75) {
+                        lightingData = new LightingDataRampToLevel(LightingCommandTypeContainer.LightingCommandRampToLevel_20Second, (byte) 0xAF, (byte) 0xE0);
+                    } else {
+                        lightingData = new LightingDataTerminateRamp(LightingCommandTypeContainer.LightingCommandTerminateRamp, (byte) 0xAF);
+                    }
+                    SALData salData = new SALDataLighting(null, lightingData);
+                    monitoredSAL = new MonitoredSALLongFormSmartMode((byte) 0x05, (byte) 0x00, new UnitAddress((byte) 0x0), null, ApplicationIdContainer.LIGHTING_38, (byte) 0x00, null, salData, cBusOptions);
+                } else {
+                    LightingData lightingData;
+                    double random = Math.random();
+                    if (random < 0.25) {
+                        lightingData = new LightingDataOn(LightingCommandTypeContainer.LightingCommandOn, (byte) 0xAF);
+                    } else if (random > 0.25 && random < 0.5) {
+                        lightingData = new LightingDataOff(LightingCommandTypeContainer.LightingCommandOff, (byte) 0xAF);
+                    } else if (random > 0.5 && random < 0.75) {
+                        lightingData = new LightingDataRampToLevel(LightingCommandTypeContainer.LightingCommandRampToLevel_20Second, (byte) 0xAF, (byte) 0xE0);
+                    } else {
+                        lightingData = new LightingDataTerminateRamp(LightingCommandTypeContainer.LightingCommandTerminateRamp, (byte) 0xAF);
+                    }
+                    SALData salData = new SALDataLighting(null, lightingData);
+                    monitoredSAL = new MonitoredSALShortFormBasicMode((byte) 0x0, (byte) 0x0, (short) 0x0, (short) 0x0, (byte) 0x0, ApplicationIdContainer.LIGHTING_38, salData, cBusOptions);
+                }
+                EncodedReply encodedReply = new MonitoredSALReply((byte) 0x0, monitoredSAL, cBusOptions, requestContext);
+                Reply reply = new ReplyEncodedReply((byte) 0x0, encodedReply, null, cBusOptions, requestContext);
+                ReplyOrConfirmation replyOrConfirmation = new ReplyOrConfirmationReply((byte) 0x00, reply, new ResponseTermination(), cBusOptions, requestContext);
+                CBusMessage message = new CBusMessageToClient(replyOrConfirmation, requestContext, cBusOptions);
+                LOGGER.info("[Monitor] Sending out\n{}\n{}", message, encodedReply);
+                ctx.writeAndFlush(message);
+            } finally {
+                writeLock.unlock();
+            }
+        }, 5, 5, TimeUnit.SECONDS);
+    }
+
+    private void stopMonitor() {
+        LOGGER.info("Stopping monitor");
+        sf.cancel(false);
+        sf = null;
+    }
+
 }