Closed jongunee closed 1 year ago
There are several issues with your example
assetConnection
and messageBus
config sections are mixedYour example (simplified) was
{
"core": {...},
"endpoints": [...],
"persistence": {...},
"messageBus": {
"@class": "de.fraunhofer.iosb.ilt.faaast.service.messagebus.internal.MessageBusInternal",
"host": "opc.tcp://<myip>:<myport>",
"valueProviders": {...}
}
}
but should be
{
"core": {...},
"endpoints": [...],
"persistence":{...},
"messageBus": {...},
"assetConnections": [
{
"@class": "de.fraunhofer.iosb.ilt.faaast.service.assetconnection.opcua.OpcUaAssetConnection",
"host": "opc.tcp://<myip>:<myport>",
"valueProviders": {...}
}
]
}
Using valueProviders
instead of operationProviders
, as you want to execute an operation rather than read/write a value (see documentation on different types of providers)
Invalid References used to link provider and AAS operation
(local)
elementGlobalReference
instead of Operation
(Submodel)(local)[IRI]0112/2///61360_4#AAA650#001,(GlobalReference)(local)[IRI]0112/2///61360_4#AUA420#001
should be (Submodel)[IRI]https://example.com/ids/sm/3585_1051_9022_0802,(Operation)[ID_SHORT]Start
(assuming you want to connect the Start
operation).
For details see AAS specification Section 7.2.3
Really thank you!!
It is working well, but i have one another question.
I changed the configuration file following your comments like below.
but problem is data type is not matched, because the data type of "AirConditioner_1.State" is customized with "ControllerState" type.
If i enter "int" or "boolean" in "valueType", the type is not mapped, so error occurs with StatusCode - BadWaitingForInitialData (0x80320000) in OPC UA client. Can I know how to solve this situation with customized data type?
As for now, FA³ST only supports a limited set of OPC UA data types out-of-the-box, namely the ones defined as built-in datatypes by the used OPC UA client library (Eclipse Milo) .
However, ValueConverter allows you to register custom type mappings from OPC UA to AAS and vice-versa. The right place to add custom converter functionality would be inside the OpcUaAssetConnection. This requires that you build FA³ST yourself.
Probably at some time in the future adding custom type mappings might become more convenient, e.g. without the need to compile FA³ST yourself. I'll put this down in our backlog but it may take some time as we are currently working on other features.
I also wonder how to check submodel property with http API.
If I check humidity property, how should I enter the API? What should be typed in {aasIdentifier} or {submodelIdentifier}?
It occurs error with below all cases
Please have a look at the API specification, especially Section 10.3 which states
To avoid problems with IRIs in URLs the identifiers shall be BASE64-URL-encoded before using them as parameters in the HTTP-APIs. IdshortPaths are URL-encoded to handle including square brackets. In the example above “aHR0cHM6Ly9hZG1pbi1zaGVsbC5pby9zYW1wbGVTTQ” is the BASE64-URLencoding of “https://admin-shell.io/sampleSM”, “sme1.sme2%5B0%5D.p1” is the URL-encoding of “sme1.sme2[0].p1” and “sme1.sme2%5B0%5D” is the URL-encoding of “sme1.sme2[0]”.
In your case this would be
https://example.com/ids/sm/3585_1051_9022_0802
, base64URL-encoded: aHR0cHM6Ly9leGFtcGxlLmNvbS9pZHMvc20vMzU4NV8xMDUxXzkwMjJfMDgwMg
Humidity
, url-encoded: Humidity
/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9pZHMvc20vMzU4NV8xMDUxXzkwMjJfMDgwMg/submodel/submodel-elements/Humidity
Is it possible to opetate method with http endpoints?
For example. I have "Start"/"Stop" operation model type. It is working as a method in OPC UA server, it means it is mapped with method in OPC UA server
However, GET request just shows a json output.
Should I use PUT/POST requests?
Yes, it is possible to map an AAS Operation to an HTTP server. For details how to do this, please have a look at the following documents
In short, you need to have an HTTP AssetConnection configured with an OperationProvider linked to your AAS operation which should something similar to this
{
"core": {...},
"endpoints": [...],
"persistence": {...},
"messageBus": {...},
"assetConnections": [{
"@class": "de.fraunhofer.iosb.ilt.faaast.service.assetconnection.http.HttpAssetConnection",
"baseUrl": "http://example.com",
"operationProviders":
{
"(Submodel)[IRI]https://example.com/ids/sm/3585_1051_9022_0802,(Operation)[ID_SHORT]Start":
{
"format": "JSON",
"path": "/foo/bar/start",
"method": "POST",
"template": "{\"input1\" : \"${in1}\", \"input2\" : \"${in2}\"}",
"queries": {
"out1": "$.output1",
"out2": "$.output2"
}
}
}
}]
}
Where template
specifies the payload to send from AAS to HTTP server and can contain the actual input and inoutput values defined in AAS via ${...}
and queries does the mapping from the JSON returned by HTTP server to AAS output and inoutput variables of the operation via JSONPath. In this example the HTTP operation is expected to return JSON in the form
{
"output1": ...,
"output2": ...,
...
}
As it seems that the operations that you want to map to HTTP do not have any input-/output parameters, you probably don't need to specify template
and queries
. However, the HTTP Asset Connection has not been tested without any parameters, so please let us know if any exceptions happen in this case.
I have checked following your answer, but it is not working. I want to check whether it is right.
{
...
"assetConnections": [
{
...
"operationProviders": {
"(Submodel)[IRI]https://example.com/ids/sm/3585_1051_9022_0802,(Operation)[ID_SHORT]Start": {
"nodeId": "ns=3;s=AirConditioner_1.Start",
"format": "JSON",
"path": "/submodels/submodelElements/Start/",
"method": "POST"
}
...
}
]
}
URL to operate the OPC UA method:
http://localhost:8080/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9pZHMvc20vMzU4NV8xMDUxXzkwMjJfMDgwMg==/submodel/submodel-elements/Start/invoke
Return:
{
"success": false,
"messages": [
{
"messageType": "Error",
"text": "error parsing body",
"code": "",
"timestamp": "2022-10-24T04:07:43.986+00:00"
}
]
}
path
in conf file correct? I am not sure that this error is because of not specified template
/queries
or my configuration file is wronghttps://faaast-service.readthedocs.io/en/latest/assetconnections/http_assetconnection/
Always thanks for your support!
You are mixing configuration properties from OPC UA (nodeId
) and HTTP (format
, path
, and method
). Are you trying to use OPC UA via HTTPS or just HTTP(S) and forgot to remove the nodeId
property?
What exactly are you trying to do? What kind of assets (i.e. legacy systems to FA³ST should access) do you have? Is it OPC UA, HTTP or both? Could you please elaborate in detail what your intention is?
Are you maybe mixing the protocol how to invoke an operation via FA³ST (i.e. what we call Endpoint
) and the protocol that FA³ST uses to forward that call to the underlying asset (what we call AssetConnection
)? If so, please be aware that those two are completely independant from each other, meaning you define an asset connection without any information on how this will be invoke via FA³ST. This only depends on which endpoints you choose to expose (HTTP, OPC UA or both). This works because FA³ST parses incoming external requests (e.g. to invoke an AAS operation) into a protocl-agnostic format that is then executed. For asset connections it is quite similar. As they all implement the same protocol-agnostic interface FA³ST checks if there is a provider defined for the requested property and if so calls it without knowing about the internals, e.g. which protocol that provider actually implements.
DT API // can be HTTP, OPC UA, or both
_____|_______
| |
| FA³ST |
|_____________|
|
Asset Connection // can be either HTTP, OPC UA, or MQTT (for each AAS SubmodelElement)
I'll try to explain in detail.
What I have now:
What I checked:
What I am wondering now is:
Is it possible to call method with HTTP endpoints using REST API call like below example?
REST API call with HTTP endpoints
-> Call method in my asset (OPC UA server)
-> Start/Stop air conditioner
ex) http://localhost:8080/submodels/aHR0cHM6Ly9leGFtcGxlLmNvbS9pZHMvc20vMzU4NV8xMDUxXzkwMjJfMDgwMg==/submodel/submodel-elements/Start/invoke
Or is it REST API call only for HTTP asset
POST
: /submodels/{submodelIdentifier}/submodel-elements/{idShortPath}/invoke
Thank you, now I understand what you are trying to do.
As stated in my last post, asset connections and endpoint are not related in any way. This means that operations connected via any asset connection (HTTP, MQTT or OPC UA) can be invoked via both OPC UA and HTTP (assuming the corresponding endpoints are configured) without any additional configuration.
In your scenario that means that you should specify an OPC UA asset connection for your operation as well as an HTTP endpoint and then invoking the AAS operation via HTTP should work. I just tested it locally with an OPC UA operations that has neither input or output and it works as expected.
When doing the POST
to .../invoke
try adding some payload in the body (according to the specification) like
{
"inputArguments": [],
"timeout": 10000
}
and adding the header content-type: application/json
.
If you don't provide any body FA³ST seems to fail parsing the HTTP request.
Describe the bug A clear and concise description of what the bug is.
To Reproduce Steps to reproduce the behavior:
I followed your below example in your document, but i don't know how to apply exactly
Reference below:
AirCoditionerAAS-simple-operation.json
```json { "assetAdministrationShells": [ { "assetInformation": { "assetKind": "Instance", "globalAssetId": { "keys": [ { "idType": "Iri", "type": "Asset", "value": "https://example.com/ids/asset/9294_1051_9022_4665" } ] } }, "submodels": { "keys": [ { "type": "Submodel", "value": "https://example.com/ids/sm/3585_1051_9022_0802", "idType": "Iri" } ] }, "identification": { "idType": "Iri", "id": "https://example.com/ids/aas/5245_1051_9022_2232" }, "idShort": "AirConditionerAAS", "modelType": { "name": "AssetAdministrationShell" } } ], "assets": [ { "identification": { "idType": "Iri", "id": "https://example.com/ids/asset/9294_1051_9022_4665" }, "idShort": "AirConditioner", "modelType": { "name": "Asset" }, "kind": "Instance" } ], "submodels": [ { "semanticId": { "keys": [ { "idType": "Iri", "type": "GlobalReference", "value": "0112/2///61360_4#AAA650#001" } ] }, "identification": { "idType": "Iri", "id": "https://example.com/ids/sm/3585_1051_9022_0802" }, "idShort": "ConditionMonitoring", "modelType": { "name": "Submodel" }, "kind": "Instance", "submodelElements": [ { "value": "", "semanticId": { "keys": [ { "idType": "Iri", "type": "GlobalReference", "value": "0112/2///61360_4#AAA622#001" } ] }, "idShort": "Humidity", "category": "Variable", "modelType": { "name": "Property" }, "valueType": "double", "kind": "Instance", "descriptions": [ { "language": "en", "text": "degree of wetness of the atmosphere measured in the KETI meeting room" } ] }, { "value": "", "semanticId": { "keys": [ { "idType": "Iri", "type": "GlobalReference", "value": "0112/2///61360_4#AUA420#001" } ] }, "idShort": "State", "category": "Variable", "modelType": { "name": "Property" }, "valueType": "int", "kind": "Instance", "descriptions": [ { "language": "en", "text": "state of an object active or running" } ] }, { "value": "", "semanticId": { "keys": [ { "idType": "Iri", "type": "GlobalReference", "value": "https://example.com/ids/cd/5110_8051_9022_2974" } ] }, "idShort": "Start", "modelType": { "name": "Operation" }, "kind": "Instance", "descriptions": [ { "language": "en", "text": "call the method to start an air conditioner" } ] }, { "value": "", "semanticId": { "keys": [ { "idType": "Iri", "type": "GlobalReference", "value": "https://example.com/ids/cd/9301_8051_9022_9990" } ] }, "idShort": "Stop", "modelType": { "name": "Operation" }, "kind": "Instance", "descriptions": [ { "language": "en", "text": "call the method to stop an air conditioner" } ] } ], "descriptions": [] } ], "conceptDescriptions": [ { "modelType": { "name": "ConceptDescription" }, "administration": { "revision": "0", "version": "0.9" }, "identification": { "idType": "Iri", "id": "https://example.com/ids/cd/0491_5022_9022_2061" }, "idShort": "TestConceptDescription", "isCaseOf": [ { "keys": [ { "idType": "Iri", "type": "GlobalReference", "value": "http://example.com/DataSpecifications/ConceptDescriptions/TestConceptDescription" } ] } ], "description": [ { "language": "en-us", "text": "An example concept description for the test application" }, { "language": "de", "text": "Ein Beispiel-ConceptDescription für eine Test-Anwendung" } ] } ] } ```AirConditionAASConf.json
```json { "core": { "requestHandlerThreadPoolSize": 2 }, "endpoints": [ { "@class": "de.fraunhofer.iosb.ilt.faaast.service.endpoint.http.HttpEndpoint", "port": 8080 }, { "@class": "de.fraunhofer.iosb.ilt.faaast.service.endpoint.opcua.OpcUaEndpoint", "tcpPort": 18123 } ], "persistence": { "@class": "de.fraunhofer.iosb.ilt.faaast.service.persistence.memory.PersistenceInMemory", "initialModel": "AASEnv.json", "decoupleEnvironment": true }, "messageBus": { "@class": "de.fraunhofer.iosb.ilt.faaast.service.messagebus.internal.MessageBusInternal" }, "assetConnections": { "@class": "de.fraunhofer.iosb.ilt.faaast.service.assetconnection.opcua.OpcUaAssetConnection", "host": "opc.tcp://Can i know how to apply with configuration json file? Is there any example or other detailed explanation?
Expected behavior AAS property and opc ua server data are mapped
Output It is built successfully without "assetConnections" part in configuration file. but, I cannot get opc ua server data on my aas model