private S7VarPayloadDataItem serializePlcValue(S7Tag tag, PlcValue plcValue) {
        try {
            DataTransportSize transportSize = tag.getDataType().getDataTransportSize();
            int stringLength = (tag instanceof S7StringFixedLengthTag) ? ((S7StringFixedLengthTag) tag).getStringLength() : 254;
            ByteBuffer byteBuffer = null;
            if((tag.getDataType() == TransportSize.BYTE) && (tag.getNumberOfElements() > 1)) {
                byteBuffer = ByteBuffer.allocate(tag.getNumberOfElements());
                byteBuffer.put(plcValue.getRaw());
            } else {
                for (int i = 0; i < tag.getNumberOfElements(); i++) {
                    int lengthInBits = DataItem.getLengthInBits(plcValue.getIndex(i), tag.getDataType().getDataProtocolId(), s7DriverContext.getControllerType(), stringLength);
                    // Cap the length of the string with the maximum allowed size.
                    if (tag.getDataType() == TransportSize.STRING) {
                        lengthInBits = Math.min(lengthInBits, (stringLength * 8) + 16);
                    } else if (tag.getDataType() == TransportSize.WSTRING) {
                        lengthInBits = Math.min(lengthInBits, (stringLength * 16) + 32);
                    } else if (tag.getDataType() == TransportSize.S5TIME) {
                        lengthInBits = lengthInBits * 8;
                    }
                    final WriteBufferByteBased writeBuffer = new WriteBufferByteBased((int) Math.ceil(((float) lengthInBits) / 8.0f));
                    DataItem.staticSerialize(writeBuffer, plcValue.getIndex(i), tag.getDataType().getDataProtocolId(), s7DriverContext.getControllerType(), stringLength);
                    // Allocate enough space for all items.
                    if (byteBuffer == null) {
                        // TODO: This logic will cause problems when reading arrays of strings.
                        byteBuffer = ByteBuffer.allocate(writeBuffer.getBytes().length * tag.getNumberOfElements());
                    }
                    byteBuffer.put(writeBuffer.getBytes());
                }
            }
            if (byteBuffer != null) {
                byte[] data = byteBuffer.array();
                return new S7VarPayloadDataItem(DataTransportErrorCode.OK, transportSize, data);
            }
        } catch (SerializationException e) {
            logger.warn("Error serializing tag item of type: '{}'", tag.getDataType().name(), e);
        }
        return null;
    }
DECODE:
This method is called when there is no handler for the message. 
By default it must correspond to asynchronous events, which if so, 
must be transferred to the event queue.
The event's own information is encapsulated in the parameters and payload
field. From this it is abstracted to the corresponding event model.
01. S7ModeEvent:
02. S7UserEvent:
03. S7SysEvent:
04. S7AlarmEvent
05. S7CyclicEvent:
06. S7CyclicEvent:
TODO: Use mspec to generate types that allow better interpretation of
the code using "instanceof".
plc4j/drivers/s7/src/main/java/org/apache/plc4x/java/s7/readwrite/protocol/S7ProtocolLogic.java