FreeOpcUa / python-opcua

LGPL Pure Python OPC-UA Client and Server
http://freeopcua.github.io/
GNU Lesser General Public License v3.0
1.36k stars 658 forks source link

WARNING:opcua.server.uaprocessor:Unknown message received FourByteNodeId(i=769) #594

Open FluxReality opened 6 years ago

FluxReality commented 6 years ago

Hi

I developed a prototype server using this great library, to try out the IoT-Edge OPC Publisher for Azure. This publisher is based on the OPCFoundation UA-.NETStandard. The publisher works by enabling monitoring mode to "Reporting", but when the client request this to my python server i get this warning

WARNING:opcua.server.uaprocessor:Unknown message received FourByteNodeId(i=769)

Resulting in an BadNotImplemented on the client side.

I suppose this means that the

SetMonitoringModeRequest_Encoding_DefaultBinary = 769

case has not yet been implemented by the FreeOpcUa library. Is this assumption correct or am I missing something here (given that I'm still new to the OPCua architecture)?

oroulet commented 6 years ago

yes looks like this call has not be implemented. it need to be added to uaprocessor and InternalServer/Session I suppose. It is probably not complicated, just copy from other calls. It should be possible to autogenerate most of this uaprocessor file....

jcharlytown commented 6 years ago

Hi,

the same seems to be the case for SetPublishingModeRequest_Encoding_DefaultBinary = 799. I get

07/02/2018 12:46:53: Start monitoring items on endpoint 'opc.tcp://localhost:4840/'. Currently monitoring 0 items.
07/02/2018 12:46:53: Unhandled OPC UA ServiceResultException 'BadNotImplemented' when monitoring node 'S7.DB1.Station_StatusId' on endpoint 'opc.tcp://localhost:4840/'. Continue.
07/02/2018 12:46:53: Done processing unmonitored items on endpoint 'opc.tcp://localhost:4840/'. Now monitoring 0 items in subscription with id '78'.

When running microsoft/iot-edge-opc-publisher:2.1.4 against opcua==0.98.1.

Is this correct?

bullvai commented 6 years ago

Flux, did you end up implementing this? I'm looking into it now, but I'm uncertain how to respond to the SetMonitoringModeRequest.

Here's what I've got so far: In uaprocessor.py I've added:

elif typeid == ua.NodeId(ua.ObjectIds.SetMonitoringModeRequest_Encoding_DefaultBinary: self.logger.info("Monitoring Mode Request")

params = struct_from_binary(ua.SetMonitoringModeParameters, body)

results = self.session.??? <-- not sure what goes here or even if this is the right way to proceed

response = ua.SetMonitoringModeResponse()
response.Results = results

self.send_response(requesthdr.Requesthandle, algohdr, seqhdr, response)

Am I walking down the right path here, or am I way off track? What am I missing?

Also, I get one (and only one) of these right when the client first connects: Unknown message received FourByteNodeId(i=841), which seems to be this binary: TransferSubscriptionsRequest_Encoding_DefaultBinary = 841

Since I only receive this message once, I don't perceive it to be a big deal.

I'm using Inductive Automation's Ignition platform.

ghost commented 6 years ago

Hi everyone,

This is the first thing I'm doing with OPC-UA, so I don't know where to start helping, just letting you know you're not alone. I also encounter Unknown message received FourByteNodeId(i=799) from the server-minimal example and Unhandled OPC UA ServiceResultException 'BadNotImplemented' when monitoring node 'MyVariable' on endpoint [...] on the iot-edge-opc-publisher side.

Also I don't see the 841, so that seems to be unrelated.

oroulet commented 6 years ago

@bullvai your work looks ok. Next step is to add a method in Session

FluxReality commented 6 years ago

@bullvai sorry for slow reply.

No I did not get around to implement it, due to time limitations. I just ended up doing it all in .net instead.

Surinamer1997 commented 6 years ago

Hi all,

Im also having this problem with "SetPublishingModeRequest_Encoding_DefaultBinary = 799".

i added the following code to uaprocessor.py

elif typeid == ua.NodeId(ua.ObjectIds.SetPublishingModeRequest_Encoding_DefaultBinary): self.logger.info("Publishing Mode Request")

        params = struct_from_binary(ua.SetPublishingModeParameters, body)

        results = 

        response = ua.SetPublishingModeResponse()
        response.Results = results

        self.send_response(requesthdr.Requesthandle, algohdr, seqhdr, response)`

@oroulet do you know what i need to add to internal_server.py to fill in the results line and get this working?

ODugas commented 6 years ago

I'm also interested in the sub-question issued by @Surinamer1997 .

oroulet commented 6 years ago

Well. Now you are at the hard part ;-) you need to find the corresponding subscribtion and modify it with the parameters from the request. I think there is already a modify_subscribtion request InternalServer, try to find the code for it as a starting point

Naurislv commented 5 years ago

We are having the same issue as @SmilingWorlock and @jcharlytown. Maybe someone has found the workaround for this either at OPCPublisher or python-opcua side?

zerox1212 commented 5 years ago

No one has taken the time to implement the UA calls and make a pull request. I do not think there is a workaround that will let OPCPublisher work without these.

asinitson commented 5 years ago

There is a crude workaround we used to get OPC Publisher play nicely with this library: just send happy dummy responses for unimplemented calls. To do this you need to modify opcua/server/uaprocessor.py:

# ---- snip ----
class UaProcessor(object):
# ---- snip ----
    def _process_message(self, typeid, requesthdr, algohdr, seqhdr, body):
# ---- snip ----
        elif typeid == ua.NodeId(ua.ObjectIds.SetMonitoringModeRequest_Encoding_DefaultBinary):
            self.logger.info("set monitoring mode request")

            params = struct_from_binary(ua.SetMonitoringModeParameters, body)

            # Send dummy results to keep clients happy
            response = ua.SetMonitoringModeResponse()
            results = ua.SetMonitoringModeResult()
            ids = params.MonitoredItemIds
            statuses = [ua.StatusCode(ua.StatusCodes.Good) for node_id in ids]
            results.Results = statuses
            response.Parameters = results

            self.logger.info("sending set monitoring mode response")
            self.send_response(requesthdr.RequestHandle, algohdr, seqhdr, response)

        elif typeid == ua.NodeId(ua.ObjectIds.SetPublishingModeRequest_Encoding_DefaultBinary):
            self.logger.info("set publishing mode request")

            params = struct_from_binary(ua.SetPublishingModeParameters, body)

            # Send dummy results to keep clients happy
            response = ua.SetPublishingModeResponse()
            results = ua.SetPublishingModeResult()
            ids = params.SubscriptionIds
            statuses = [ua.StatusCode(ua.StatusCodes.Good) for node_id in ids]
            results.Results = statuses
            response.Parameters = results

            self.logger.info("sending set publishing mode response")
            self.send_response(requesthdr.RequestHandle, algohdr, seqhdr, response)
# ---- snip ----

Thanks for the hints from the comments above!

asinitson commented 5 years ago

I forked python-opcua repository and applied the change from the comment above:

https://github.com/FreeOpcUa/python-opcua/compare/master...asinitson:opc-publisher-support

To try it out with your project do something like this:

# Fetch modified version of the library
git clone https://github.com/asinitson/python-opcua
cd python-opcua
git checkout  opc-publisher-support

# NOTE: Path to the library has to be absolute
export PYTHONPATH="$PWD:$PYTHONPATH"

# Change to your project working directory and run your python code
cd <some_fancy_project_directory>

# Start your program
# It should pick up OPC UA library from `PYTHONPATH`
# To make sure you are not using unmodified version do this first
pip uninstall opcua
oroulet commented 5 years ago

@asinitson can you make a pull request? . You have already done 99% of the work

asinitson commented 5 years ago

@oroulet: Done!

Just to make sure we are on the same page: we effectively ignore the requests and return "fake" ua.StatusCodes.Good.