Esempio n. 1
0
    def _on_response(self, responsePayload, responseContext, timestamp):
        """
        Receives an OpcUa_*Response, creates a Response, associates it to a Request both-ways.
        It is called for every response received through the LibSub callback_generic_event.
        The dictionary _dResponseClasses contains classes that will be instantiated with the OpcUa_*Response as parameter.
        It is possible to add new elements to this dict to support more response decoders, or override existing decoders.

        Warning: responsePayload is freed by the caller, so the structure or its content must be copied before returning.

        The timestamp parameters is computed on the first line of the event callback,
        hence it is the most accurate instant when the response was received by the Python layer.
        """
        assert responseContext in self._dRequestContexts, 'Unknown requestContext {}.'.format(
            responseContext)
        request = self._dRequestContexts.pop(responseContext)
        try:
            if responsePayload is None:
                return
            # Build typed response
            encType = ffi.cast('SOPC_EncodeableType**', responsePayload)
            response = self._dResponseClasses.get(encType[0],
                                                  Response)(responsePayload)
            response.timestampReceived = timestamp  # Passing the timestamp instead of acquiring it here reduces it by ~10µs
            request.response = response
            response.request = request
            if responseContext not in self._sSkipResponse:
                self.on_generic_response(request, response)
            else:
                self._sSkipResponse.remove(responseContext)
        finally:
            # Hopefully the Toolkit always notifies the application, and it is caught here.
            # Also, if the processing of the response fails, it is caught here.
            request.eventResponseReceived.set()
        return response
Esempio n. 2
0
 def __init__(self, payload):
     super().__init__(None)
     payload = ffi.cast('OpcUa_BrowseResponse*', payload)
     assert payload.encodeableType == EncodeableType.BrowseResponse
     self.results = [
         BrowseResult(payload.Results[i])
         for i in range(payload.NoOfResults)
     ]
Esempio n. 3
0
 def __init__(self, payload):
     super().__init__(None)
     payload = ffi.cast('OpcUa_ReadResponse*', payload)
     assert payload.encodeableType == EncodeableType.ReadResponse
     self.results = [
         DataValue.from_sopc_datavalue(payload.Results[i])
         for i in range(payload.NoOfResults)
     ]
Esempio n. 4
0
 def __init__(self, payload):
     self.timestampSent = None  # The sender of the request sets the timestamp
     self.response = None
     self.eventResponseReceived = threading.Event()
     # Does not use the ffi.new_handle and from_handle capabilities because from_handle is subject to "undefined behavior"
     #  when it is given an unknown pointer...
     self._requestContextVoid = ffi.new_handle(
         self)  # Keep the void* to avoid garbage collection, ...
     self._requestContext = ffi.cast(
         'uintptr_t',
         self._requestContextVoid)  # ... but only use the casted value.
     self.payload = payload