4343import org .slf4j .Logger ;
4444import org .slf4j .LoggerFactory ;
4545
46+ import java .net .InetSocketAddress ;
4647import java .util .*;
4748import java .util .concurrent .CompletableFuture ;
4849
@@ -402,14 +403,14 @@ public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionReque
402403 // Create one PnIoCm_Block_ExpectedSubmoduleReq for every slot being referenced.
403404 // Create one PnIoCm_Block_AlarmCrReq
404405
405-
406406 // Go through the sorted slots and subslots and fill the datastructures.
407407 int inputFrameOffset = 0 ;
408408 int outputFrameOffset = 0 ;
409- /* List<PnIoCm_IoDataObject> inputMessageDataObjects = new ArrayList<>();
409+ List <PnIoCm_IoDataObject > inputMessageDataObjects = new ArrayList <>();
410410 List <PnIoCm_IoCs > inputMessageCs = new ArrayList <>();
411- //List<PnIoCm_IoDataObject> outputMessageDataObjects = new ArrayList<>();
412- //List<PnIoCm_IoCs> outputMessageCs = new ArrayList<>();
411+ List <PnIoCm_IoDataObject > outputMessageDataObjects = new ArrayList <>();
412+ List <PnIoCm_IoCs > outputMessageCs = new ArrayList <>();
413+ // TODO: Create and fill the expectedSubmodules list.
413414 List <PnIoCm_Block_ExpectedSubmoduleReq > expectedSubmodules = new ArrayList <>();
414415 for (Map .Entry <Integer , Map <Integer , Map <ProfinetTag .Direction , Map <Integer , ProfinetTag >>>> slotEntry : slots .entrySet ()) {
415416 int slotNumber = slotEntry .getKey ();
@@ -418,53 +419,178 @@ public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionReque
418419 int subslotNumber = subslotEntry .getKey ();
419420 Map <ProfinetTag .Direction , Map <Integer , ProfinetTag >> direction = subslotEntry .getValue ();
420421
422+ int iocsLength = driverContext .getSubmoduleIndex ().get (slotNumber ).get (subslotNumber ).getIoData ().getIocsLength ();
423+ // The default is 1
424+ if (iocsLength == 0 ) {
425+ iocsLength = 1 ;
426+ }
427+ int iopsLength = driverContext .getSubmoduleIndex ().get (slotNumber ).get (subslotNumber ).getIoData ().getIopsLength ();
428+ // The default is 1
429+ if (iopsLength == 0 ) {
430+ iopsLength = 1 ;
431+ }
421432
422433 if (direction .containsKey (ProfinetTag .Direction .INPUT )) {
423434 Map <Integer , ProfinetTag > inputTags = direction .get (ProfinetTag .Direction .INPUT );
424435 for (Map .Entry <Integer , ProfinetTag > inputTag : inputTags .entrySet ()) {
436+ ProfinetTag tag = inputTag .getValue ();
437+ int dataLength = (getDataTypeLengthInBytes (tag .getPlcValueType ()) * tag .getNumElements ());
438+
425439 PnIoCm_IoDataObject input = new PnIoCm_IoDataObject (slotNumber , subslotNumber , inputFrameOffset );
426440 inputMessageDataObjects .add (input );
427- // TODO: Get the iops-length from the IoData element
428- inputFrameOffset += 1;
429- // TODO: Get the data-length + iops-length
430- outputFrameOffset += 1;
441+ PnIoCm_IoCs output = new PnIoCm_IoCs (slotNumber , subslotNumber , outputFrameOffset );
442+ outputMessageCs .add (output );
443+
444+ // Get the iops-length from the IoData element and the binary length of the input
445+ inputFrameOffset += dataLength + iocsLength ;
446+ // Get the data-length + iops-length
447+ outputFrameOffset += iocsLength ;
431448 }
432449 }
450+
433451 if (direction .containsKey (ProfinetTag .Direction .OUTPUT )) {
434452 Map <Integer , ProfinetTag > outputTags = direction .get (ProfinetTag .Direction .OUTPUT );
435453 for (Map .Entry <Integer , ProfinetTag > outputTag : outputTags .entrySet ()) {
454+ ProfinetTag tag = outputTag .getValue ();
455+ int dataLength = (getDataTypeLengthInBytes (tag .getPlcValueType ()) * tag .getNumElements ());
456+
436457 PnIoCm_IoDataObject output = new PnIoCm_IoDataObject (slotNumber , subslotNumber , inputFrameOffset );
437458 outputMessageDataObjects .add (output );
438- // TODO: Get the data-length + iocs-length from the IoData element
439- inputFrameOffset += 1;
440- // TODO: Get the iops-length
441- outputFrameOffset += 1;
459+ PnIoCm_IoCs input = new PnIoCm_IoCs (slotNumber , subslotNumber , outputFrameOffset );
460+ inputMessageCs .add (input );
461+
462+ // Get the data-length + iocs-length from the IoData element
463+ inputFrameOffset += iopsLength ;
464+ // Get the iops-length and the binary length of the output
465+ outputFrameOffset += dataLength + iopsLength ;
442466 }
443467 }
444468 }
445469 }
446470
447- for (String tagName : subscriptionRequest.getTagNames()) {
448- ProfinetTag profinetTag = (ProfinetTag) subscriptionRequest.getTag(tagName);
449-
450-
451-
452-
453- PlcValueType plcValueType = profinetTag.getPlcValueType();
454- int numElements = profinetTag.getNumElements();
455- int iopsLength = driverContext.getSubmoduleIndex().get(slot).get(subSlot).getIoData().getIopsLength();
456- // The default is 1
457- if(iopsLength == 0) {
458- iopsLength = 1;
459- }
460-
461- PnIoCm_IoDataObject input = new PnIoCm_IoDataObject(slot, subSlot, inputFrameOffset);
462- inputDataObjects.add(input);
463-
464- // Increment the frame offset.
465- inputFrameOffset += (getDataTypeLengthInBytes(plcValueType) * numElements) + iopsLength;
466- }*/
467-
471+ RawSocketChannel rawSocketChannel = (RawSocketChannel ) context .getChannel ();
472+ MacAddress remoteMacAddress = new MacAddress (rawSocketChannel .getRemoteMacAddress ().getAddress ());
473+ InetSocketAddress remoteAddress = (InetSocketAddress ) rawSocketChannel .getRemoteAddress ();
474+ MacAddress localMacAddress = new MacAddress (rawSocketChannel .getLocalMacAddress ().getAddress ());
475+ InetSocketAddress localAddress = (InetSocketAddress ) rawSocketChannel .getLocalAddress ();
476+ List <PnIoCm_Block > blocks = new ArrayList <>();
477+ blocks .add (new PnIoCm_Block_ArReq (
478+ ProfinetDriverContext .BLOCK_VERSION_HIGH , ProfinetDriverContext .BLOCK_VERSION_LOW ,
479+ PnIoCm_ArType .IO_CONTROLLER ,
480+ driverContext .generateUuid (),
481+ driverContext .getSessionKey (),
482+ localMacAddress ,
483+ driverContext .getCmInitiatorObjectUuid (),
484+ false ,
485+ driverContext .isNonLegacyStartupMode (),
486+ false ,
487+ false ,
488+ PnIoCm_CompanionArType .SINGLE_AR ,
489+ false ,
490+ true ,
491+ false ,
492+ PnIoCm_State .ACTIVE ,
493+ ProfinetDriverContext .DEFAULT_ACTIVITY_TIMEOUT ,
494+ ProfinetDriverContext .UDP_RT_PORT ,
495+ "plc4x" ));
496+ if (!inputMessageDataObjects .isEmpty () || !inputMessageCs .isEmpty ()) {
497+ blocks .add (new PnIoCm_Block_IoCrReq (
498+ ProfinetDriverContext .BLOCK_VERSION_HIGH , ProfinetDriverContext .BLOCK_VERSION_LOW ,
499+ PnIoCm_IoCrType .INPUT_CR ,
500+ 0x0001 ,
501+ ProfinetDriverContext .UDP_RT_PORT ,
502+ false ,
503+ false ,
504+ false ,
505+ false ,
506+ PnIoCm_RtClass .RT_CLASS_2 ,
507+ ProfinetDriverContext .DEFAULT_IO_DATA_SIZE ,
508+ driverContext .getAndIncrementIdentification (),
509+ driverContext .getSendClockFactor (),
510+ driverContext .getReductionRatio (),
511+ 1 ,
512+ 0 ,
513+ 0xffffffffL ,
514+ driverContext .getWatchdogFactor (),
515+ driverContext .getDataHoldFactor (),
516+ 0xC000 ,
517+ ProfinetDriverContext .DEFAULT_EMPTY_MAC_ADDRESS ,
518+ Collections .singletonList (
519+ new PnIoCm_IoCrBlockReqApi (inputMessageDataObjects , inputMessageCs )
520+ )
521+ ));
522+ }
523+ if (!outputMessageDataObjects .isEmpty () || !outputMessageCs .isEmpty ()) {
524+ blocks .add (new PnIoCm_Block_IoCrReq (
525+ ProfinetDriverContext .BLOCK_VERSION_HIGH , ProfinetDriverContext .BLOCK_VERSION_LOW ,
526+ PnIoCm_IoCrType .OUTPUT_CR ,
527+ 0x0002 ,
528+ ProfinetDriverContext .UDP_RT_PORT ,
529+ false ,
530+ false ,
531+ false ,
532+ false ,
533+ PnIoCm_RtClass .RT_CLASS_2 ,
534+ ProfinetDriverContext .DEFAULT_IO_DATA_SIZE ,
535+ driverContext .getAndIncrementIdentification (),
536+ driverContext .getSendClockFactor (),
537+ driverContext .getReductionRatio (),
538+ 1 ,
539+ 0 ,
540+ 0xffffffffL ,
541+ driverContext .getWatchdogFactor (),
542+ driverContext .getDataHoldFactor (),
543+ 0xC000 ,
544+ ProfinetDriverContext .DEFAULT_EMPTY_MAC_ADDRESS ,
545+ Collections .singletonList (
546+ new PnIoCm_IoCrBlockReqApi (outputMessageDataObjects , outputMessageCs )
547+ )
548+ ));
549+ }
550+ blocks .addAll (expectedSubmodules );
551+ blocks .add (new PnIoCm_Block_AlarmCrReq (
552+ ProfinetDriverContext .BLOCK_VERSION_HIGH , ProfinetDriverContext .BLOCK_VERSION_LOW ,
553+ PnIoCm_AlarmCrType .ALARM_CR ,
554+ ProfinetDriverContext .UDP_RT_PORT ,
555+ false ,
556+ false ,
557+ 1 ,
558+ 3 ,
559+ 0x0000 ,
560+ 200 ,
561+ 0xC000 ,
562+ 0xA000 ));
563+ PnIoCm_Packet_Req request = new PnIoCm_Packet_Req (
564+ 16696L , 16696L , 0L , blocks );
565+ DceRpc_Packet packet = new DceRpc_Packet (
566+ DceRpc_PacketType .WORKING ,
567+ false , false , false ,
568+ IntegerEncoding .BIG_ENDIAN , CharacterEncoding .ASCII , FloatingPointEncoding .IEEE ,
569+ new DceRpc_ObjectUuid ((byte ) 0x00 , 0x0001 , Integer .decode ("0x" + driverContext .getDeviceId ()), Integer .decode ("0x" + driverContext .getVendorId ())),
570+ new DceRpc_InterfaceUuid_DeviceInterface (),
571+ driverContext .getActivityUuid (),
572+ 0L , 0L ,
573+ DceRpc_Operation .CONNECT ,
574+ (short ) 0 ,
575+ request
576+ );
577+ Random rand = new Random ();
578+ // Serialize it to a byte-payload
579+ Ethernet_FramePayload_IPv4 udpFrame = new Ethernet_FramePayload_IPv4 (
580+ rand .nextInt (65536 ),
581+ true ,
582+ false ,
583+ (short ) 64 ,
584+ new IpAddress (localAddress .getAddress ().getAddress ()),
585+ new IpAddress (remoteAddress .getAddress ().getAddress ()),
586+ driverContext .getLocalPort (),
587+ driverContext .getRemotePortImplicitCommunication (),
588+ packet
589+ );
590+ Ethernet_Frame ethernetFrame = new Ethernet_Frame (
591+ remoteMacAddress ,
592+ localMacAddress ,
593+ udpFrame );
468594
469595 return null ;
470596 }
0 commit comments