eclipse-basyx / basyx-java-server-sdk

MIT License
58 stars 45 forks source link

Operation Delegation missing inoutputVariables #342

Closed wasn93 closed 1 month ago

wasn93 commented 3 months ago

I have done some testing with the Operation Delegation feature and its example folder. I figuered out how it works and could integrate a http server into my project waiting for and handling delegated operations.

But it seems like the feature only forwards the inputVariables, not inoutputVariables. I have modified the AAS in the example JSON, so that my operation has two inputs, one inoutput and one output. Then I tracked the execution with Wireshark. There is one package, which seems to be internal inbetween the BaSyx components, containing the correct body:

{
  "inputArguments": [
    {
      "value": {
        "modelType": "Property",
        "valueType": "xs:int",
        "idShort": "input",
        "value": "1"
      }
    },
    {
      "value": {
        "modelType": "Property",
        "valueType": "xs:int",
        "idShort": "input2",
        "value": "2"
      }
    }
  ],
  "inoutputArguments": [
    {
      "value": {
        "modelType": "Property",
        "valueType": "xs:int",
        "idShort": "inAndOut",
        "value": "3"
      }
    }
  ],
  "clientTimeoutDuration": "PT60S"
}

However, the body sent to my server looks like this:

[
  {
    "value": {
      "modelType": "Property",
      "value": "1",
      "valueType": "xs:int",
      "idShort": "input"
    }
  },
  {
    "value": {
      "modelType": "Property",
      "value": "2",
      "valueType": "xs:int",
      "idShort": "input2"
    }
  }
]

This matches the feature documentation, but is it on purpose, that the inoutput is left behind?

mateusmolina-iese commented 3 months ago

Thank you for raising this issue.

Are you invoking the operations using AAS-GUI? I think this could be more of an issue of how the client is generating the request; I quickly looked at the server code and I see no restriction based on the internal Operation SubmodelElement attribute (in/inout/out).

Also, could you please provide a minimal example?

wasn93 commented 3 months ago

Thank you for looking into it.

Yes, I am using the GUI. Further I am using the Operation Delegation Example. The only modification is, that I added a second operation in the operationDelegationAAS.json. It is a copy of the original one where I set the qualifier value to my endpoint and added a second inputVariable and one inoutputVariable. The model itself is displayed correctly in the GUI.

I've attached my JSON File. The server I set up for testing looks like this. It just prints the received content and gives a static response. To run it, the localhost has to replaced by the own IP in the server and in the qualifier in the JSON file.

import json
from http.server import BaseHTTPRequestHandler, HTTPServer

serverPort = 8290
hostName = "localhost"

class OperationHttpServer(BaseHTTPRequestHandler):
    protocol_version = "HTTP/1.1"

    def do_POST(self):
        content_length = int(self.headers["Content-Length"])
        content_type = self.headers["Content-Type"]
        if content_type == "application/json":
            post_data = self.rfile.read(content_length) 
            print(post_data)
            self._send_response(200, "I am the return value")

    def _send_response(self, response_code: int, value):
        response = [{"value": {"modelType": "Property", "value": value, "valueType": "xs:string", "idShort": "result"}}]
        content = bytes(json.dumps(response), "utf-8")

        self.send_response(response_code)
        self.send_header("Content-type", "application/json")
        self.send_header("Content-length", str(len(content)))
        self.end_headers()
        self.wfile.write(content)

if __name__ == "__main__":
    webServer = HTTPServer((hostName, serverPort), OperationHttpServer)
    print("Server started http://%s:%s" % (hostName, serverPort))

    try:
        webServer.serve_forever()
    except KeyboardInterrupt:
        pass

    webServer.server_close()
    print("Server stopped.")

operationDelegationAAS.json

aaronzi commented 3 months ago

I checked the request that is being send by the UI. This is the payload for the example @wasn93 provided:

{
    "inputArguments": [
        {
            "value": {
                "modelType": "Property",
                "valueType": "xs:int",
                "idShort": "input",
                "value": "2"
            }
        },
        {
            "value": {
                "modelType": "Property",
                "valueType": "xs:int",
                "idShort": "input2",
                "value": "2"
            }
        }
    ],
    "inoutputArguments": [
        {
            "value": {
                "modelType": "Property",
                "valueType": "xs:int",
                "idShort": "inAndOut",
                "value": "2"
            }
        }
    ],
    "clientTimeoutDuration": "PT60S"
}

The request looks good to me. It seems like this is an internal bug in the basyx-java-serversdk's code.

mateusmolina-iese commented 3 months ago

Hi @aaronzi, thanks for checking the AAS GUI output.

@wasn93, thanks for providing additional info. We will take a look at the example and get back to you as soon we have an update on the issue.