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);
}
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);
}
}
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;
}
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());
}
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);
}
}
Aggregations