Engineering-Research-and-Development / iotagent-opcua

IoT Agent for OPC UA protocol
https://iotagent-opcua.rtfd.io/
GNU Affero General Public License v3.0
41 stars 21 forks source link

Use of commands status PENDING #64

Closed manolait closed 1 year ago

manolait commented 2 years ago

Hello,

I am trying to use the commands to send information to my OPC server. I have a number of doubts.

Doubt 1: When I send my update (why is it necessary to put it between [])

curl -X PUT \ 'http://localhost:1026/v2/entities/React/attrs/Imput?type=3:React' \ -H 'content-type: application/json' \ -H 'fiware-service: sabana' \ -H 'fiware-servicepath: /team' \ -d '{ "value": [44], "type": "command" }’

Doubt 2: When I query my OCB I get the response from that entity and the command attribute to update is PENDING. How do I solve this problem.

"Imput_info": {
            "type": "commandResult",
            "value": " ",
            "metadata": {}
        },
        "Imput_status": {
            "type": "commandStatus",
            "value": "PENDING",
            "metadata": {}
        }

Thank you.

MattiaMarzano-Eng commented 2 years ago

Are you using the same set up of the issue #63?

manolait commented 2 years ago

Hello,

this is my system configuration

Config.properties

## SOUTHBOUND CONFIGURATION (OPC UA)
namespace-ignore=2,7
endpoint=opc.tcp://MacBook-Pro.local:5001/UA/CarServer

## NORTHBOUND CONFIGURATION (ORION CONTEXT BROKER)
context-broker-host=orion
context-broker-port=1026
fiware-service=sabana
fiware-service-path=/team

## AGENT CONFIGURATION
server-base-root=/
server-port=4001
provider-url=http://iotage:4001

device-registration-duration=P1M
device-registry-type=memory

log-level=DEBUG

namespaceIndex=3
namespaceNumericIdentifier=1000

# MONGO-DB CONFIGURATION (required if device-registry-type=mongodb)
mongodb-host=iotmongo
mongodb-port=27017
mongodb-db=iotagent
mongodb-retries=5
mongodb-retry-time=5

## DATATYPE MAPPING OPCUA --> NGSI
OPC-datatype-Number=Number
OPC-datatype-Decimal128=Number
OPC-datatype-Double=Number
OPC-datatype-Float=Number
OPC-datatype-Integer=Integer
OPC-datatype-UInteger=Integer
OPC-datatype-String=Text
OPC-datatype-ByteString=Text
#END DATATYPE MAPPING OPCUA --> NGSI

## SESSION PARAMETERS
requestedPublishingInterval=10
requestedLifetimeCount=1000
requestedMaxKeepAliveCount=10
maxNotificationsPerPublish=100
publishingEnabled=true
priority=10

#SubscriptionsStrategy
uniqueSubscription=true

## MONITORING PARAMETERS
samplingInterval=1
queueSize=10000
discardOldest=false

## SERVER CERT E AUTH
securityMode=None
securityPolicy=None
userName=
password=

#securityMode=SIGNANDENCRYPT
#securityPolicy=1Basic256
#password=password1
#userName=user1

#api-ip=192.168.13.153

## ADMINISTRATION SERVICES
api-port=8080

## POLL COMMANDS SETTINGS
polling=false
polling-commands-timer=30000
pollingDaemonFrequency=20000
pollingExpiration=200000

## AGENT ID
# agent-id=age01_
# entity-id=age01_Car # used only during tests

## CONFIGURATION
# configuration=api

## CHECK TIMER POLLING DEVICES
checkTimer=2000

config.json

{
  "logLevel" : "DEBUG",
  "contextBroker" : {
    "host" : "orion",
    "port" : 1026
  },
  "server" : {
    "port" : 4001,
    "baseRoot" : "/"
  },
  "deviceRegistry" : {
    "type" : "memory"
  },
  "mongodb" : {
    "host" : "iotmongo",
    "port" : "27017",
    "db" : "iotagent",
    "retries" : 5,
    "retryTime" : 5
  },
  "types" : {
    "3:React" : {
      "service" : "sabana",
      "subservice" : "/team",
      "active" : [ {
        "name" : "Temperature",
        "type" : "Number"
      }, {
        "name" : "Co2",
        "type" : "Number"
      }, {
        "name" : "Radiation",
        "type" : "Number"
      } ],
      "lazy" : [ ],
      "commands" : [ {
                "name": "Speed",
                "type": "command"
            },{
                "name": "Imput",
                "type": "command"
            }]
    }
  },
  "browseServerOptions" : null,
  "service" : "sabana",
  "subservice" : "/team",
  "providerUrl" : "http://iotage:4001",
  "pollingExpiration" : "200000",
  "pollingDaemonFrequency" : "20000",
  "deviceRegistrationDuration" : "P1M",
  "defaultType" : null,
  "contexts" : [ {
    "id" : "React",
    "type" : "3:React",
    "service" : "sabana",
    "subservice" : "/team",
    "polling" : false,
    "mappings" : [ {
      "ocb_id" : "Temperature",
      "opcua_id" : "ns=3;i=1008",
      "object_id" : null,
      "inputArguments" : [ ]
    }, {
      "ocb_id" : "Co2",
      "opcua_id" : "ns=3;i=1009",
      "object_id" : null,
      "inputArguments" : [ ]
    }, {
      "ocb_id" : "Radiation",
      "opcua_id" : "ns=3;i=1010",
      "object_id" : null,
      "inputArguments" : [ ]
    } ]
  }],
  "contextSubscriptions" : [
    {
      "id": "React",
      "type": "3:React",
      "mappings": [{
        "ocb_id": "Speed",
        "opcua_id": "ns=3;s=Speed",
        "object_id": "ns=3;i=1011",
        "inputArguments": [{
          "dataType": 6,
          "type": "Intensity"
        }]
      },{
        "ocb_id": "Imput",
        "opcua_id": "ns=3;s=Imput",
        "object_id": "ns=3;i=1012",
        "inputArguments": [{
          "dataType": 6,
          "type": "Intensity"
        }]
      }]
    }
   ]
}

Reviewing the co-configured agents in http://localhost:4001/iot/devices/ I have noticed that it does not create the command part, but in OCB it does. Is it possible that it is because of some configuration problem with the OPC server? when I send an update of the command from OCB if it appears in Pending and in the /iot/devices/

MattiaMarzano-Eng commented 2 years ago

It could be, please share also your server setting and object folder

manolait commented 2 years ago

Hello,

I am modifying all my configuration attached the information to be OPC server, config.jon, config.properties

Opc where my command would be the variable2


const { OPCUAServer, Variant, DataType, StatusCodes } = require("node-opcua");

(async () => {

    // Let's create an instance of OPCUAServer
    const server = new OPCUAServer({
        port: 5001, // the port of the listening socket of the server
        resourcePath: "/UA/CarServer", // this path will be added to the endpoint resource name
        buildInfo: {
            productName: "CarServer",
            buildNumber: "7658",
            buildDate: new Date(2014, 5, 2)
        }
    });
    await server.initialize();
    console.log("initialized");

    const addressSpace = server.engine.addressSpace;
    const namespace = addressSpace.getOwnNamespace();

    // declare a new object
    const device = namespace.addObject({
        organizedBy: addressSpace.rootFolder.objects,
        browseName: "MyDevice"
    });

    // add some variables
    // add a variable named MyVariable1 to the newly created folder "MyDevice"
    let variable1 = 1;

    // emulate variable1 changing every 500 ms
    setInterval(() => { variable1 += 1; }, 500);

    namespace.addVariable({
        componentOf: device,
        nodeId: "ns=1;s=Variable1", // some opaque NodeId in namespace 4
        browseName: "Variable1",
        dataType: "Double",
        value: {
            get: () => new Variant({ dataType: DataType.Double, value: variable1 })
        }
    });

    // add a variable named MyVariable2 to the newly created folder "MyDevice"
    let variable2 = 10.0;

    namespace.addVariable({

        componentOf: device,

        nodeId: "ns=1;s=Variable2", // some opaque NodeId in namespace 4

        browseName: "Variable2",

        dataType: "Double",

        value: {
            get: () => new Variant({ dataType: DataType.Double, value: variable2 }),
            set: (variant) => {
                variable2 = parseFloat(variant.value);
                return StatusCodes.Good;
            }
        }
    });
    const os = require("os");
    /**
     * returns the percentage of free memory on the running machine
     * @return {double}
     */
    function available_memory() {
        // var value = process.memoryUsage().heapUsed / 1000000;
        const percentageMemUsed = os.freemem() / os.totalmem() * 100.0;
        return percentageMemUsed;
    }
    namespace.addVariable({

        componentOf: device,

        //Si no especificamos el NS automaticamente te lo pone en el node 1 en este caso seria ns=1 y la b seria esa

        nodeId: "s=free_memory", // a string nodeID
        browseName: "FreeMemory",
        dataType: "Double",
        value: {
            get: () => new Variant({ dataType: DataType.Double, value: available_memory() })
        }
    });

    server.start(function() {
        console.log("Server is now listening ... ( press CTRL+C to stop)");
        console.log("port ", server.endpoints[0].port);
        const endpointUrl = server.endpoints[0].endpointDescriptions()[0].endpointUrl;
        console.log(" the primary server endpoint url is ", endpointUrl);
    });

})();

config.json


{
  "logLevel" : "DEBUG",
  "contextBroker" : {
    "host" : "orion",
    "port" : 1026
  },
  "server" : {
    "port" : 4001,
    "baseRoot" : "/"
  },
  "deviceRegistry" : {
    "type" : "memory"
  },
  "mongodb" : {
    "host" : "iotmongo",
    "port" : "27017",
    "db" : "iotagent",
    "retries" : 5,
    "retryTime" : 5
  },
  "types" : {
    "MyDevice" : {
      "service" : "sabana",
      "subservice" : "/team",
      "active" : [ {
        "name" : "Variable1",
        "type" : "Number"
      } ],
      "lazy" : [ ],
      "commands" : [ {
        "name" : "Variable2",
        "type" : "command"
      }]
    }
  },
  "browseServerOptions" : null,
  "service" : "sabana",
  "subservice" : "/team",
  "providerUrl" : "http://iotage:4001",
  "pollingExpiration" : "200000",
  "pollingDaemonFrequency" : "20000",
  "deviceRegistrationDuration" : "P1M",
  "defaultType" : null,
  "contexts" : [ {
    "id" : "MyDevice",
    "type" : "MyDevice",
    "service" : "sabana",
    "subservice" : "/team",
    "polling" : false,
    "mappings" : [ {
      "ocb_id" : "Variable1",
      "opcua_id" : "ns=1;s=Variable1",
      "object_id" : null,
      "inputArguments" : [ ]
    }]
  }],
  "contextSubscriptions" : [
    {
            "ocb_id": "Variable2",
            "opcua_id": "ns=1;s=Variable2",
            "object_id": "ns=1;i=2",
            "inputArguments": []
        }
   ]
}

config.propierties


## SOUTHBOUND CONFIGURATION (OPC UA)
namespace-ignore=2,7
endpoint=xxxxxxxx

## NORTHBOUND CONFIGURATION (ORION CONTEXT BROKER)
context-broker-host=orion
context-broker-port=1026
fiware-service=sabana
fiware-service-path=/team

## AGENT CONFIGURATION
server-base-root=/
server-port=4001
provider-url=http://iotage:4001

device-registration-duration=P1M
device-registry-type=memory

log-level=DEBUG

namespaceIndex=3
namespaceNumericIdentifier=1000

# MONGO-DB CONFIGURATION (required if device-registry-type=mongodb)
mongodb-host=iotmongo
mongodb-port=27017
mongodb-db=iotagent
mongodb-retries=5
mongodb-retry-time=5

## DATATYPE MAPPING OPCUA --> NGSI
OPC-datatype-Number=Number
OPC-datatype-Decimal128=Number
OPC-datatype-Double=Number
OPC-datatype-Float=Number
OPC-datatype-Integer=Integer
OPC-datatype-UInteger=Integer
OPC-datatype-String=Text
OPC-datatype-ByteString=Text
#END DATATYPE MAPPING OPCUA --> NGSI

## SESSION PARAMETERS
requestedPublishingInterval=10
requestedLifetimeCount=1000
requestedMaxKeepAliveCount=10
maxNotificationsPerPublish=100
publishingEnabled=true
priority=10

#SubscriptionsStrategy
uniqueSubscription=true

## MONITORING PARAMETERS
samplingInterval=1
queueSize=10000
discardOldest=false

## SERVER CERT E AUTH
securityMode=None
securityPolicy=None
userName=
password=

#securityMode=SIGNANDENCRYPT
#securityPolicy=1Basic256
#password=password1
#userName=user1

#api-ip=192.168.13.153

## ADMINISTRATION SERVICES
api-port=8080

## POLL COMMANDS SETTINGS
polling=false
polling-commands-timer=30000
pollingDaemonFrequency=20000
pollingExpiration=200000

## AGENT ID
# agent-id=age01_
# entity-id=age01_Car # used only during tests

## CONFIGURATION
# configuration=api

## CHECK TIMER POLLING DEVICES
checkTimer=2000

Fiware devices: (I do not understand why variable 2 does not appear in the devices as a command.)


{
    "count": 1,
    "devices": [
        {
            "device_id": "MyDevice",
            "service": "sabana",
            "service_path": "/team",
            "entity_name": "MyDevice",
            "entity_type": "MyDevice",
            "endpoint": "opc.tcp://arm.ual.es:5001/UA/CarServer",
            "attributes": [
                {
                    "object_id": "Variable1",
                    "name": "Variable1",
                    "type": "Number"
                }
            ]
        }
    ]
}

If I try to change the value it gives error: ({"error":"NotFound","description":"The requested entity has not been found. Check type and id"}% )

curl -X PUT \
  'http://localhost:1026/v2/entities/MyDevice/attrs/Variable2?type=MyDevice' \ 
  -H 'content-type: application/json' \
  -H 'fiware-service: sabana' \
  -H 'fiware-servicepath: /team' \
  -d '{
  "value": [2],
  "type": "command"
}'

Fiware entities


[
    {
        "id": "MyDevice",
        "type": "MyDevice",
        "Variable1": {
            "type": "Number",
            "value": 254,
            "metadata": {}
        },
        "Variable2_info": {
            "type": "commandResult",
            "value": " ",
            "metadata": {}
        },
        "Variable2_status": {
            "type": "commandStatus",
            "value": "UNKNOWN",
            "metadata": {}
        }
    }
]
manolait commented 2 years ago

Hello,

could you help me with the problem?

Best regards.

MattiaMarzano-Eng commented 2 years ago

Please try to use the latest version of the docker image now. Leave a comment if the issue persist.

manfredipist commented 1 year ago

Hi @manolait , command execution flow has been totally revised on v2 of the agent thus i suggest you to try the latest version to check if the issue still persists.