Search in sources :

Example 1 with PlcException

use of org.apache.plc4x.java.api.exceptions.PlcException in project plc4x by apache.

the class ProfinetProtocolLogic method onConnect.

@Override
public void onConnect(ConversationContext<Ethernet_Frame> context) {
    final Channel channel = context.getChannel();
    if (!(channel instanceof RawSocketChannel)) {
        logger.warn("Expected a 'raw' transport, closing channel...");
        context.getChannel().close();
        return;
    }
    RawSocketChannel rawSocketChannel = (RawSocketChannel) channel;
    // Create an udp socket
    DatagramSocket udpSocket;
    try {
        udpSocket = new DatagramSocket();
    } catch (SocketException e) {
        logger.warn("Unable to create udp socket " + e.getMessage());
        context.getChannel().close();
        return;
    }
    // //////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Initialize some important datastructures, that will be used a lot.
    // Generate a new Activity Id, which will be used throughout the connection.
    profinetDriverContext.setDceRpcActivityUuid(generateActivityUuid());
    // TODO: Possibly we can remove the ARP lookup and simply use the mac address in the connection-response.
    // Local connectivity attributes
    profinetDriverContext.setLocalMacAddress(new MacAddress(rawSocketChannel.getLocalMacAddress().getAddress()));
    final InetSocketAddress localAddress = (InetSocketAddress) rawSocketChannel.getLocalAddress();
    Inet4Address localIpAddress = (Inet4Address) localAddress.getAddress();
    profinetDriverContext.setLocalIpAddress(new IpAddress(localIpAddress.getAddress()));
    // Use the port of the udp socket
    profinetDriverContext.setLocalUdpPort(udpSocket.getPort());
    // Remote connectivity attributes
    byte[] macAddress = null;
    try {
        macAddress = Hex.decodeHex("000000000000");
    } catch (DecoderException e) {
    // Ignore this.
    }
    profinetDriverContext.setRemoteMacAddress(new MacAddress(macAddress));
    final InetSocketAddress remoteAddress = (InetSocketAddress) rawSocketChannel.getRemoteAddress();
    Inet4Address remoteIpAddress = (Inet4Address) remoteAddress.getAddress();
    profinetDriverContext.setRemoteIpAddress(new IpAddress(remoteIpAddress.getAddress()));
    profinetDriverContext.setRemoteUdpPort(remoteAddress.getPort());
    // Generate a new session key.
    profinetDriverContext.setSessionKey(sessionKeyGenerator.getAndIncrement());
    // Reset the session key as soon as it reaches the max for a 16 bit uint
    if (sessionKeyGenerator.get() == 0xFFFF) {
        sessionKeyGenerator.set(1);
    }
    // Create the connection request.
    try {
        // Create the packet
        final DceRpc_Packet profinetConnectionRequest = createProfinetConnectionRequest();
        // Serialize it to a byte-payload
        WriteBufferByteBased writeBuffer = new WriteBufferByteBased(profinetConnectionRequest.getLengthInBytes());
        profinetConnectionRequest.serialize(writeBuffer);
        // Create a udp packet.
        DatagramPacket connectRequestPacket = new DatagramPacket(writeBuffer.getData(), writeBuffer.getData().length);
        connectRequestPacket.setAddress(remoteAddress.getAddress());
        connectRequestPacket.setPort(remoteAddress.getPort());
        // Send it.
        udpSocket.send(connectRequestPacket);
        // Receive the response.
        byte[] resultBuffer = new byte[profinetConnectionRequest.getLengthInBytes()];
        DatagramPacket connectResponsePacket = new DatagramPacket(resultBuffer, resultBuffer.length);
        udpSocket.receive(connectResponsePacket);
        ReadBufferByteBased readBuffer = new ReadBufferByteBased(resultBuffer);
        final DceRpc_Packet dceRpc_packet = DceRpc_Packet.staticParse(readBuffer);
        if ((dceRpc_packet.getOperation() == DceRpc_Operation.CONNECT) && (dceRpc_packet.getPacketType() == DceRpc_PacketType.RESPONSE)) {
            if (dceRpc_packet.getPayload().getPacketType() == DceRpc_PacketType.RESPONSE) {
                // Get the remote MAC address and store it in the context.
                final PnIoCm_Packet_Res connectResponse = (PnIoCm_Packet_Res) dceRpc_packet.getPayload();
                if ((connectResponse.getBlocks().size() > 0) && (connectResponse.getBlocks().get(0) instanceof PnIoCm_Block_ArRes)) {
                    final PnIoCm_Block_ArRes pnIoCm_block_arRes = (PnIoCm_Block_ArRes) connectResponse.getBlocks().get(0);
                    profinetDriverContext.setRemoteMacAddress(pnIoCm_block_arRes.getCmResponderMacAddr());
                    // Update the raw-socket transports filter expression.
                    ((RawSocketChannel) channel).setRemoteMacAddress(org.pcap4j.util.MacAddress.getByAddress(profinetDriverContext.getRemoteMacAddress().getAddress()));
                } else {
                    throw new PlcException("Unexpected type of frist block.");
                }
            } else {
                throw new PlcException("Unexpected response");
            }
        } else {
            throw new PlcException("Unexpected response");
        }
    } catch (SerializationException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (PlcException e) {
        e.printStackTrace();
    } catch (ParseException e) {
        e.printStackTrace();
    }
    System.out.println(rawSocketChannel);
}
Also used : RawSocketChannel(org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel) Channel(io.netty.channel.Channel) IOException(java.io.IOException) RawSocketChannel(org.apache.plc4x.java.utils.rawsockets.netty.RawSocketChannel) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) DecoderException(org.apache.commons.codec.DecoderException)

Example 2 with PlcException

use of org.apache.plc4x.java.api.exceptions.PlcException in project plc4x by apache.

the class HelloInflux method run.

public void run() {
    InfluxDBClient dbConnection = connectToDb();
    WriteApi writeApi = dbConnection.getWriteApi();
    try {
        PlcConnection plcConnection = connectToPlc();
        final PlcSubscriptionRequest subscriptionRequest = plcConnection.subscriptionRequestBuilder().addChangeOfStateField("query", configuration.getString("plc.query")).build();
        final PlcSubscriptionResponse subscriptionResponse = subscriptionRequest.execute().get(10, TimeUnit.SECONDS);
        subscriptionResponse.getSubscriptionHandle("query").register(plcSubscriptionEvent -> {
            DefaultPlcSubscriptionEvent internalEvent = (DefaultPlcSubscriptionEvent) plcSubscriptionEvent;
            final Point point = Point.measurement(configuration.getString("influx.measurement")).time(plcSubscriptionEvent.getTimestamp().toEpochMilli(), WritePrecision.MS);
            final Map<String, ResponseItem<PlcValue>> values = internalEvent.getValues();
            values.forEach((fieldName, fieldResponsePair) -> {
                final PlcResponseCode responseCode = fieldResponsePair.getCode();
                final PlcValue plcValue = fieldResponsePair.getValue();
                if (responseCode == PlcResponseCode.OK) {
                    PlcStruct structValue = (PlcStruct) plcValue;
                    for (String key : structValue.getKeys()) {
                        PlcValue subValue = structValue.getValue(key);
                        registerFields(point, key, subValue);
                    }
                }
            });
            writeApi.writePoint(configuration.getString("influx.bucket"), configuration.getString("influx.org"), point);
        });
    } catch (PlcException e) {
        logger.error("PLC Error", e);
    } catch (Exception e) {
        logger.error("General Error", e);
    }
}
Also used : InfluxDBClient(com.influxdb.client.InfluxDBClient) PlcSubscriptionRequest(org.apache.plc4x.java.api.messages.PlcSubscriptionRequest) DefaultPlcSubscriptionEvent(org.apache.plc4x.java.spi.messages.DefaultPlcSubscriptionEvent) Point(com.influxdb.client.write.Point) PlcConnection(org.apache.plc4x.java.api.PlcConnection) ConfigurationException(org.apache.commons.configuration2.ex.ConfigurationException) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) WriteApi(com.influxdb.client.WriteApi) PlcSubscriptionResponse(org.apache.plc4x.java.api.messages.PlcSubscriptionResponse) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem)

Example 3 with PlcException

use of org.apache.plc4x.java.api.exceptions.PlcException in project plc4x by apache.

the class AdsProtocolLogic method multiWrite.

protected CompletableFuture<PlcWriteResponse> multiWrite(PlcWriteRequest writeRequest, List<DirectAdsField> directAdsFields) {
    CompletableFuture<PlcWriteResponse> future = new CompletableFuture<>();
    // Calculate the size of all fields together.
    // Calculate the expected size of the response data.
    int expectedRequestDataSize = directAdsFields.stream().mapToInt(field -> field.getAdsDataType().getNumBytes() * field.getNumberOfElements()).sum();
    byte[] writeBuffer = new byte[expectedRequestDataSize];
    int pos = 0;
    for (String fieldName : writeRequest.getFieldNames()) {
        final AdsField field = (AdsField) writeRequest.getField(fieldName);
        final PlcValue plcValue = writeRequest.getPlcValue(fieldName);
        final int stringLength;
        if (field.getAdsDataType() == AdsDataType.STRING) {
            stringLength = plcValue.getString().length() + 1;
        } else {
            if (field.getAdsDataType() == AdsDataType.WSTRING) {
                stringLength = (plcValue.getString().length() + 1) * 2;
            } else {
                stringLength = 0;
            }
        }
        try {
            WriteBufferByteBased itemWriteBuffer = new WriteBufferByteBased(DataItem.getLengthInBytes(plcValue, field.getAdsDataType().getDataFormatName(), stringLength));
            DataItem.staticSerialize(itemWriteBuffer, plcValue, field.getAdsDataType().getDataFormatName(), stringLength, ByteOrder.LITTLE_ENDIAN);
            int numBytes = itemWriteBuffer.getPos();
            System.arraycopy(itemWriteBuffer.getData(), 0, writeBuffer, pos, numBytes);
            pos += numBytes;
        } catch (Exception e) {
            throw new PlcRuntimeException("Error serializing data", e);
        }
    }
    // With multi-requests, the index-group is fixed and the index offset indicates the number of elements.
    AdsData adsData = new AdsReadWriteRequest(ReservedIndexGroups.ADSIGRP_MULTIPLE_WRITE.getValue(), directAdsFields.size(), (long) directAdsFields.size() * 4, directAdsFields.stream().map(directAdsField -> new AdsMultiRequestItemWrite(directAdsField.getIndexGroup(), directAdsField.getIndexOffset(), ((long) directAdsField.getAdsDataType().getNumBytes() * directAdsField.getNumberOfElements()))).collect(Collectors.toList()), writeBuffer);
    AmsPacket amsPacket = new AmsPacket(configuration.getTargetAmsNetId(), configuration.getTargetAmsPort(), configuration.getSourceAmsNetId(), configuration.getSourceAmsPort(), CommandId.ADS_READ_WRITE, DEFAULT_COMMAND_STATE, 0, getInvokeId(), adsData);
    AmsTCPPacket amsTCPPacket = new AmsTCPPacket(amsPacket);
    // Start a new request-transaction (Is ended in the response-handler)
    RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
    transaction.submit(() -> context.sendRequest(amsTCPPacket).expectResponse(AmsTCPPacket.class, Duration.ofMillis(configuration.getTimeoutRequest())).onTimeout(future::completeExceptionally).onError((p, e) -> future.completeExceptionally(e)).check(responseAmsPacket -> responseAmsPacket.getUserdata().getInvokeId() == amsPacket.getInvokeId()).unwrap(response -> (AdsReadWriteResponse) response.getUserdata().getData()).handle(responseAdsData -> {
        if (responseAdsData.getResult() == ReturnCode.OK) {
            final PlcWriteResponse plcWriteResponse = convertToPlc4xWriteResponse(writeRequest, responseAdsData);
            // Convert the response from the PLC into a PLC4X Response ...
            future.complete(plcWriteResponse);
        } else {
            // TODO: Implement this correctly.
            future.completeExceptionally(new PlcException("Error"));
        }
        // Finish the request-transaction.
        transaction.endRequest();
    }));
    return future;
}
Also used : IntStream(java.util.stream.IntStream) PlcSubscriptionType(org.apache.plc4x.java.api.types.PlcSubscriptionType) java.util(java.util) LoggerFactory(org.slf4j.LoggerFactory) PlcValue(org.apache.plc4x.java.api.value.PlcValue) DefaultPlcConsumerRegistration(org.apache.plc4x.java.spi.model.DefaultPlcConsumerRegistration) CompletableFuture(java.util.concurrent.CompletableFuture) PlcConsumerRegistration(org.apache.plc4x.java.api.model.PlcConsumerRegistration) AdsSubscriptionHandle(org.apache.plc4x.java.ads.model.AdsSubscriptionHandle) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) ConversationContext(org.apache.plc4x.java.spi.ConversationContext) DefaultPlcSubscriptionField(org.apache.plc4x.java.spi.model.DefaultPlcSubscriptionField) Duration(java.time.Duration) PlcResponseCode(org.apache.plc4x.java.api.types.PlcResponseCode) DataItem(org.apache.plc4x.java.ads.readwrite.DataItem) Plc4xProtocolBase(org.apache.plc4x.java.spi.Plc4xProtocolBase) BigInteger(java.math.BigInteger) Logger(org.slf4j.Logger) PlcSubscriptionHandle(org.apache.plc4x.java.api.model.PlcSubscriptionHandle) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) org.apache.plc4x.java.spi.messages(org.apache.plc4x.java.spi.messages) Instant(java.time.Instant) Collectors(java.util.stream.Collectors) org.apache.plc4x.java.ads.readwrite(org.apache.plc4x.java.ads.readwrite) PlcField(org.apache.plc4x.java.api.model.PlcField) IEC61131ValueHandler(org.apache.plc4x.java.spi.values.IEC61131ValueHandler) HasConfiguration(org.apache.plc4x.java.spi.configuration.HasConfiguration) org.apache.plc4x.java.spi.generation(org.apache.plc4x.java.spi.generation) Consumer(java.util.function.Consumer) AtomicLong(java.util.concurrent.atomic.AtomicLong) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) org.apache.plc4x.java.ads.field(org.apache.plc4x.java.ads.field) AdsConfiguration(org.apache.plc4x.java.ads.configuration.AdsConfiguration) ResponseItem(org.apache.plc4x.java.spi.messages.utils.ResponseItem) org.apache.plc4x.java.api.messages(org.apache.plc4x.java.api.messages) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) RequestTransactionManager(org.apache.plc4x.java.spi.transaction.RequestTransactionManager) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) PlcRuntimeException(org.apache.plc4x.java.api.exceptions.PlcRuntimeException) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) CompletableFuture(java.util.concurrent.CompletableFuture) PlcValue(org.apache.plc4x.java.api.value.PlcValue)

Example 4 with PlcException

use of org.apache.plc4x.java.api.exceptions.PlcException in project plc4x by apache.

the class CachedDriverManagerIT method connectWithMultipleThreads.

@Test
void connectWithMultipleThreads() throws InterruptedException, PlcException {
    ExecutorService executorService = Executors.newFixedThreadPool(4);
    PlcConnectionFactory mock = Mockito.mock(PlcConnectionFactory.class);
    MockConnection plcMockConnection = mock(MockConnection.class);
    when(mock.create()).thenReturn(plcMockConnection);
    CachedDriverManager driverManager = new CachedDriverManager("", mock, 10_000);
    AtomicInteger errorCounter = new AtomicInteger(0);
    AtomicInteger successCounter = new AtomicInteger(0);
    for (int i = 1; i <= 100; i++) {
        executorService.submit(() -> {
            try {
                driverManager.getConnection("").close();
                successCounter.incrementAndGet();
            } catch (Exception e) {
                LOGGER.warn("error", e);
                errorCounter.incrementAndGet();
            }
        });
    }
    executorService.shutdown();
    boolean forced = executorService.awaitTermination(50, TimeUnit.SECONDS);
    // If this is false, a thread was still hanging => something failed
    assertTrue(forced);
    assertEquals(100, successCounter.get());
    assertEquals(0, errorCounter.get());
}
Also used : AtomicInteger(java.util.concurrent.atomic.AtomicInteger) ExecutorService(java.util.concurrent.ExecutorService) MockConnection(org.apache.plc4x.java.mock.connection.MockConnection) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) Test(org.junit.jupiter.api.Test)

Example 5 with PlcException

use of org.apache.plc4x.java.api.exceptions.PlcException in project plc4x by apache.

the class MqttConnector method run.

private void run() throws PlcException {
    // Create a new MQTT client.
    final Mqtt3RxClient client = MqttClient.builder().identifier(UUID.randomUUID().toString()).serverHost(config.getMqttConfig().getServerHost()).serverPort(config.getMqttConfig().getServerPort()).useMqttVersion3().buildRx();
    // Connect to the MQTT broker.
    final Single<Mqtt3ConnAck> connAckSingle = client.connect().timeout(10, TimeUnit.SECONDS);
    // Connect to the PLC.
    try (PlcConnection plcConnection = new PlcDriverManager().getConnection(config.getPlcConfig().getConnection())) {
        // Check if this connection support reading of data.
        if (!plcConnection.getMetadata().canRead()) {
            System.err.println("This connection doesn't support reading.");
            return;
        }
        // Create a new read request.
        PlcReadRequest.Builder builder = plcConnection.readRequestBuilder();
        for (PlcFieldConfig fieldConfig : config.getPlcConfig().getPlcFields()) {
            builder = builder.addItem(fieldConfig.getName(), fieldConfig.getAddress());
        }
        PlcReadRequest readRequest = builder.build();
        // Send a message containing the PLC read response.
        Flowable<Mqtt3Publish> messagesToPublish = Flowable.generate(emitter -> {
            PlcReadResponse response = readRequest.execute().get();
            String jsonPayload = getPayload(response);
            final Mqtt3Publish publishMessage = Mqtt3Publish.builder().topic(config.getMqttConfig().getTopicName()).qos(MqttQos.AT_LEAST_ONCE).payload(jsonPayload.getBytes()).build();
            emitter.onNext(publishMessage);
        });
        // Emit 1 message only every 100 milliseconds.
        messagesToPublish = messagesToPublish.zipWith(Flowable.interval(config.getPollingInterval(), TimeUnit.MILLISECONDS), (publish, aLong) -> publish);
        final Single<Mqtt3ConnAck> connectScenario = connAckSingle.doOnSuccess(connAck -> System.out.println("Connected with return code " + connAck.getReturnCode())).doOnError(throwable -> System.out.println("Connection failed, " + throwable.getMessage()));
        final Flowable<Mqtt3PublishResult> publishScenario = client.publish(messagesToPublish).doOnNext(publishResult -> System.out.println("Publish acknowledged: " + new String(publishResult.getPublish().getPayloadAsBytes())));
        connectScenario.toCompletable().andThen(publishScenario).blockingSubscribe();
    } catch (Exception e) {
        throw new PlcException("Error creating connection to " + config.getPlcConfig().getConnection(), e);
    }
}
Also used : PlcDriverManager(org.apache.plc4x.java.PlcDriverManager) JsonObject(com.google.gson.JsonObject) PlcConnection(org.apache.plc4x.java.api.PlcConnection) LoggerFactory(org.slf4j.LoggerFactory) MqttQos(com.hivemq.client.mqtt.datatypes.MqttQos) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) Single(io.reactivex.Single) StringUtils(org.apache.commons.lang3.StringUtils) Mqtt3PublishResult(com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult) MqttClient(com.hivemq.client.mqtt.MqttClient) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) Flowable(io.reactivex.Flowable) YAMLFactory(com.fasterxml.jackson.dataformat.yaml.YAMLFactory) Mqtt3RxClient(com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient) PlcFieldConfig(org.apache.plc4x.java.examples.connectivity.mqtt.model.PlcFieldConfig) Logger(org.slf4j.Logger) Configuration(org.apache.plc4x.java.examples.connectivity.mqtt.model.Configuration) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Mqtt3ConnAck(com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck) IOException(java.io.IOException) UUID(java.util.UUID) File(java.io.File) TimeUnit(java.util.concurrent.TimeUnit) JsonArray(com.google.gson.JsonArray) Mqtt3Publish(com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish) Mqtt3RxClient(com.hivemq.client.mqtt.mqtt3.Mqtt3RxClient) PlcConnection(org.apache.plc4x.java.api.PlcConnection) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) IOException(java.io.IOException) PlcException(org.apache.plc4x.java.api.exceptions.PlcException) PlcReadResponse(org.apache.plc4x.java.api.messages.PlcReadResponse) Mqtt3PublishResult(com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3PublishResult) PlcFieldConfig(org.apache.plc4x.java.examples.connectivity.mqtt.model.PlcFieldConfig) Mqtt3Publish(com.hivemq.client.mqtt.mqtt3.message.publish.Mqtt3Publish) PlcReadRequest(org.apache.plc4x.java.api.messages.PlcReadRequest) Mqtt3ConnAck(com.hivemq.client.mqtt.mqtt3.message.connect.connack.Mqtt3ConnAck) PlcDriverManager(org.apache.plc4x.java.PlcDriverManager)

Aggregations

PlcException (org.apache.plc4x.java.api.exceptions.PlcException)12 CompletableFuture (java.util.concurrent.CompletableFuture)6 PlcResponseCode (org.apache.plc4x.java.api.types.PlcResponseCode)4 java.util (java.util)3 Logger (org.slf4j.Logger)3 LoggerFactory (org.slf4j.LoggerFactory)3 IOException (java.io.IOException)2 BigInteger (java.math.BigInteger)2 Duration (java.time.Duration)2 Instant (java.time.Instant)2 ConcurrentHashMap (java.util.concurrent.ConcurrentHashMap)2 ExecutorService (java.util.concurrent.ExecutorService)2 AtomicLong (java.util.concurrent.atomic.AtomicLong)2 Consumer (java.util.function.Consumer)2 Collectors (java.util.stream.Collectors)2 IntStream (java.util.stream.IntStream)2 PlcRuntimeException (org.apache.plc4x.java.api.exceptions.PlcRuntimeException)2 org.apache.plc4x.java.spi.generation (org.apache.plc4x.java.spi.generation)2 ResponseItem (org.apache.plc4x.java.spi.messages.utils.ResponseItem)2 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1