use of org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField in project plc4x by apache.
the class S7ProtocolLogic method encodeEventSubcriptionRequest.
private void encodeEventSubcriptionRequest(DefaultPlcSubscriptionRequest request, List<S7ParameterUserDataItem> parameterItems, List<S7PayloadUserDataItem> payloadItems) {
byte subsevent = 0;
for (String fieldName : request.getFieldNames()) {
if (request.getField(fieldName) instanceof DefaultPlcSubscriptionField) {
PlcField event = ((DefaultPlcSubscriptionField) request.getField(fieldName)).getPlcField();
if (event instanceof S7SubscriptionField) {
subsevent = (byte) (subsevent | ((S7SubscriptionField) event).getEventType().getValue());
}
}
}
S7ParameterUserDataItemCPUFunctions parameter = new S7ParameterUserDataItemCPUFunctions(// Method
(short) 0x11, // FunctionType
(byte) 0x04, // FunctionGroup
(byte) 0x04, // SubFunction
(short) 0x02, // SequenceNumber
(short) 0x00, // DataUnitReferenceNumber
null, // LastDataUnit
null, // errorCode
null);
parameterItems.clear();
parameterItems.add(parameter);
S7PayloadUserDataItemCpuFunctionMsgSubscription payload = null;
if (subsevent > 0) {
payload = new S7PayloadUserDataItemCpuFunctionMsgSubscription(DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, subsevent, "HmiRtm ", null, null);
} else {
// TODO: Check for ALARM_S (S7300) and ALARM_8 (S7400), maybe we need verify the CPU
AlarmStateType alarmtype;
if (s7DriverContext.getControllerType() == S7ControllerType.S7_400) {
alarmtype = AlarmStateType.ALARM_INITIATE;
} else {
alarmtype = AlarmStateType.ALARM_S_INITIATE;
}
payload = new S7PayloadUserDataItemCpuFunctionMsgSubscription(DataTransportErrorCode.OK, DataTransportSize.OCTET_STRING, subsevent, "HmiRtm ", alarmtype, (short) 0x00);
}
payloadItems.clear();
payloadItems.add(payload);
}
use of org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField in project plc4x by apache.
the class S7ProtocolLogic method subscribe.
@Override
public CompletableFuture<PlcSubscriptionResponse> subscribe(PlcSubscriptionRequest subscriptionRequest) {
CompletableFuture<PlcSubscriptionResponse> future = new CompletableFuture<>();
DefaultPlcSubscriptionRequest request = (DefaultPlcSubscriptionRequest) subscriptionRequest;
List<S7ParameterUserDataItem> parameterItems = new ArrayList<>(request.getNumberOfFields());
List<S7PayloadUserDataItem> payloadItems = new ArrayList<>(request.getNumberOfFields());
for (String fieldName : request.getFieldNames()) {
final DefaultPlcSubscriptionField sf = (DefaultPlcSubscriptionField) request.getField(fieldName);
final S7SubscriptionField field = (S7SubscriptionField) sf.getPlcField();
switch(field.getFieldType()) {
case EVENT_SUBSCRIPTION:
;
encodeEventSubcriptionRequest(request, parameterItems, payloadItems);
break;
case EVENT_UNSUBSCRIPTION:
;
// encodeEventUnSubcriptionRequest(msg, out);
break;
case ALARM_ACK:
;
// encodeAlarmAckRequest(msg, out);
break;
case ALARM_QUERY:
;
// encodeAlarmQueryRequest(msg, out);
break;
case CYCLIC_SUBSCRIPTION:
;
// encodeCycledSubscriptionRequest(msg, out);
break;
case CYCLIC_UNSUBSCRIPTION:
;
// encodeCycledUnSubscriptionRequest(msg, out);
break;
default:
;
}
;
// final PlcValue plcValue = request.getPlcValue(fieldName);
// parameterItems.add(new S7VarRequestParameterItemAddress(encodeS7Address(field)));
// payloadItems.add(serializePlcValue(field, plcValue));
}
final int tpduId = tpduGenerator.getAndIncrement();
// If we've reached the max value for a 16 bit transaction identifier, reset back to 1
if (tpduGenerator.get() == 0xFFFF) {
tpduGenerator.set(1);
}
TPKTPacket tpktPacket = new TPKTPacket(new COTPPacketData(null, new S7MessageUserData(tpduId, new S7ParameterUserData(parameterItems), new S7PayloadUserData(payloadItems, null)), true, (short) tpduId, null));
// Start a new request-transaction (Is ended in the response-handler)
RequestTransactionManager.RequestTransaction transaction = tm.startRequest();
transaction.submit(() -> context.sendRequest(tpktPacket).onTimeout(new TransactionErrorCallback<>(future, transaction)).onError(new TransactionErrorCallback<>(future, transaction)).expectResponse(TPKTPacket.class, REQUEST_TIMEOUT).check(p -> p.getPayload() instanceof COTPPacketData).unwrap(p -> ((COTPPacketData) p.getPayload())).unwrap(COTPPacket::getPayload).check(p -> p.getTpduReference() == tpduId).handle(p -> {
try {
future.complete(((PlcSubscriptionResponse) decodeEventSubcriptionRequest(p, subscriptionRequest)));
} catch (PlcProtocolException e) {
logger.warn("Error sending 'write' message: '{}'", e.getMessage(), e);
}
// Finish the request-transaction.
transaction.endRequest();
}));
return future;
}
use of org.apache.plc4x.java.s7.readwrite.field.S7SubscriptionField in project plc4x by apache.
the class S7ProtocolLogic method decodeEventSubcriptionRequest.
private PlcSubscriptionResponse decodeEventSubcriptionRequest(S7Message responseMessage, PlcSubscriptionRequest plcSubscriptionRequest) throws PlcProtocolException {
Map<String, ResponseItem<PlcSubscriptionHandle>> values = new HashMap<>();
short errorClass = 0;
short errorCode = 0;
if (responseMessage instanceof S7MessageUserData) {
S7MessageUserData messageUserData = (S7MessageUserData) responseMessage;
S7PayloadUserData payload = (S7PayloadUserData) messageUserData.getPayload();
// errorClass = payload.getItems()[0].
// errorCode = messageUserData.getParameter().
} else if (responseMessage instanceof S7MessageResponse) {
S7MessageResponse messageResponse = (S7MessageResponse) responseMessage;
errorClass = messageResponse.getErrorClass();
errorCode = messageResponse.getErrorCode();
} else {
throw new PlcProtocolException("Unsupported message type " + responseMessage.getClass().getName());
}
// If the result contains any form of non-null error code, handle this instead.
if ((errorClass != 0) || (errorCode != 0)) {
// This is usually the case if PUT/GET wasn't enabled on the PLC
if ((errorClass == 129) && (errorCode == 4)) {
logger.warn("Got an error response from the PLC. This particular response code usually indicates " + "that PUT/GET is not enabled on the PLC.");
for (String fieldName : plcSubscriptionRequest.getFieldNames()) {
values.put(fieldName, null);
}
return new DefaultPlcSubscriptionResponse(plcSubscriptionRequest, values);
} else {
logger.warn("Got an unknown error response from the PLC. Error Class: {}, Error Code {}. " + "We probably need to implement explicit handling for this, so please file a bug-report " + "on https://issues.apache.org/jira/projects/PLC4X and ideally attach a WireShark dump " + "containing a capture of the communication.", errorClass, errorCode);
for (String fieldName : plcSubscriptionRequest.getFieldNames()) {
values.put(fieldName, null);
}
return new DefaultPlcSubscriptionResponse(plcSubscriptionRequest, values);
}
}
// In all other cases all went well.
S7PayloadUserData payload = (S7PayloadUserData) responseMessage.getPayload();
List<S7PayloadUserDataItem> payloadItems = payload.getItems();
// Only one item for any number of subscription (4)
if (payloadItems.size() == 0) {
throw new PlcProtocolException("The number of requested items doesn't match the number of returned items");
}
boolean responseOk = false;
if (payloadItems.get(0) instanceof S7PayloadUserDataItemCpuFunctionMsgSubscriptionResponse) {
S7PayloadUserDataItemCpuFunctionMsgSubscriptionResponse item = (S7PayloadUserDataItemCpuFunctionMsgSubscriptionResponse) payloadItems.get(0);
if ((item.getReturnCode() == DataTransportErrorCode.OK) && (item.getTransportSize() == DataTransportSize.OCTET_STRING)) {
responseOk = true;
}
} else if (payloadItems.get(0) instanceof S7PayloadUserDataItemCpuFunctionMsgSubscriptionSysResponse) {
S7PayloadUserDataItemCpuFunctionMsgSubscriptionSysResponse item = (S7PayloadUserDataItemCpuFunctionMsgSubscriptionSysResponse) payloadItems.get(0);
if ((item.getReturnCode() == DataTransportErrorCode.OK) && (item.getTransportSize() == DataTransportSize.OCTET_STRING)) {
responseOk = true;
}
} else if (payloadItems.get(0) instanceof S7PayloadUserDataItemCpuFunctionMsgSubscriptionAlarmResponse) {
S7PayloadUserDataItemCpuFunctionMsgSubscriptionAlarmResponse item = (S7PayloadUserDataItemCpuFunctionMsgSubscriptionAlarmResponse) payloadItems.get(0);
if ((item.getReturnCode() == DataTransportErrorCode.OK) && (item.getTransportSize() == DataTransportSize.OCTET_STRING)) {
responseOk = true;
}
}
if (responseOk) {
for (String fieldName : plcSubscriptionRequest.getFieldNames()) {
DefaultPlcSubscriptionField dfield = (DefaultPlcSubscriptionField) plcSubscriptionRequest.getField(fieldName);
S7SubscriptionField field = (S7SubscriptionField) dfield.getPlcField();
switch(field.getEventType()) {
case MODE:
values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, modeHandle));
break;
case SYS:
values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, sysHandle));
break;
case USR:
values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, usrHandle));
break;
case ALM:
values.put(fieldName, new ResponseItem<>(PlcResponseCode.OK, almHandle));
break;
}
}
return new DefaultPlcSubscriptionResponse(plcSubscriptionRequest, values);
}
return null;
}
Aggregations