aws-samples / aws-iot-greengrass-opcua-adapter

MIT No Attribution
15 stars 5 forks source link

Use Greengrass OPC-UA to Communicate with Multiple Industrial Equipment

Greengrass supports OPC-UA, an information exchange standard for industrial communication. OPC-UA allows you to ingest and process messages from industrial equipment and deliver them to devices in your Greengrass group or to the cloud based on rules you define.

The Greengrass implementation of OPC-UA supports certificate-based authentication. It is based on an open source implementation, and is fully customizable. You can also bring your own implementation of OPC-UA, and implement your own support for other custom, legacy, and proprietary messaging protocols.

In this section we will cover the following steps:

Architectural Overview

Greengrass implements OPC-UA as a Lambda function in NodeJS. Since Lambda functions running on Greengrass cores have access to network resources, you can create Lambda functions that proxy information from your existing OPC-UA servers over TCP to other functions or services in your Greengrass group.

Under this architecture, we provide the following additional features for customer to use:

\[Greengrass OPCUA Architecture.\]

You can configure Greengrass to have a long-lived connection to your OPC-UA server(s), and, using OPC-UA Subscriptions, you can have your OPCUA_Adapter Lambda function monitor changes to pre-defined nodes. Any change to those nodes triggers a Publish event from the OPC-UA server, which will be received by your Lambda function, and republished into predefined topic names.

Set Up a Test OPC-UA Server

Use the following commands to set up a test OPC-UA server. Or, if you already have an OPC-UA server you'd like to use instead, you may skip this step.

git clone git://github.com/node-opcua/node-opcua.git
cd node-opcua
git checkout v0.0.65
npm install
node bin/simple_server

The server produces the following output:

[ec2-user@<your_instance_id> node-opcua]$ node bin/simple_server
  server PID          : 28585

registering server to :opc.tcp://<your_instance_id>4840/UADiscovery
err Cannot find module 'usage'
skipping installation of cpu_usage and memory_usage nodes
  server on port      : 26543
  endpointUrl         : opc.tcp://<your_instance_id>us-west-2.compute.internal:26543
  serverInfo          :
      applicationUri                  : urn:54f7890cca4c49a1:NodeOPCUA-Server
      productUri                      : NodeOPCUA-Server
      applicationName                 : locale=en text=NodeOPCUA
      applicationType                 : SERVER
      gatewayServerUri                : null
      discoveryProfileUri             : null
      discoveryUrls                   : 
      productName                     : NODEOPCUA-SERVER
      buildInfo                       :
      productUri                      : NodeOPCUA-Server
      manufacturerName                : Node-OPCUA : MIT Licence ( see http://node-opcua.github.io/)
      productName                     : NODEOPCUA-SERVER
      softwareVersion                 : 0.0.65
      buildNumber                     : 1234
      buildDate                       : Thu Aug 03 2017 00:13:50 GMT+0000 (UTC)

  server now waiting for connections. CTRL+C to stop

You could setup many OPC-UA servers concurrently.

Make sure your Greengrass Group is ready

Use Greengrass OPC-UA to Interact with your OPC-UA Server

  1. Prepare your Lambda function and relocate the config foler.

    • Get the code for an OPC-UA adapter Lambda function from GitHub:

      git clone https://github.com/aws-samples/aws-iot-greengrass-opcua-adapter.git
      cd greengrass-opcua-adapter-nodejs
      npm install
    • Fix the issue happened due to openssl while npm install.

      • The error log would looks like the following:
        
        reading configuration
        =====================

      Creating default g_config file /Your-Path/aws-iot-greengrass-opcua-adapter/greengrass-opcua-adapter-nodejs/node_modules/node-opcua/certificates/config.js configuration = subject : /C=FR/ST=IDF/L=Paris/O=NodeOPCUA/CN=NodeOPCUA-TEST validity : 5475 keySize : 2048 certificateDir : /Your-Path/aws-iot-greengrass-opcua-adapter/greengrass-opcua-adapter-nodejs/node_modules/node-opcua/certificates CAFolder : /Your-Path/aws-iot-greengrass-opcua-adapter/greengrass-opcua-adapter-nodejs/node_modules/node-opcua/certificates/CA PKIFolder : /Your-Path/aws-iot-greengrass-opcua-adapter/greengrass-opcua-adapter-nodejs/node_modules/node-opcua/certificates/PKI altNames : dns : f8ffc267b5de.ant.amazon.com ip : OpenSSL version : OpenSSL 1.1.1g 21 Apr 2020 ERROR Command failed: "openssl" genrsa -out private/cakey.pem -rand random.rnd 2048 Can't load random.rnd into RNG 4406738368:error:2406F079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:98:Filename=random.rnd

      Command failed: "openssl" genrsa -out private/cakey.pem -rand random.rnd 2048 Can't load random.rnd into RNG 4406738368:error:2406F079:random number generator:RAND_load_file:Cannot open file:crypto/rand/randfile.c:98:Filename=random.rnd

      done ... (0)

      + Fix the error by the patch and then npm rebuild.

      git apply patch/Fix-the-npm-install-issue-due-to-openssl.patch

      npm rebuild

    • Patch the factories.js

      git apply patch/factories.patch
    • Relocate the folder greengrass-opcua-adapter-nodejs/config to environment variable AWS_LAMBDA_OPCUA_ADAPTER_CONFIG_FILE_PATH defined in Configure Lambda section or default external path /etc/greengrass/opcua-adapter/config.

    Note:

    • The relocated path must also defined in Lambda configuration in IoT Core console, or the Lambda function wouldn't find the path or have no access right to this path!
    • There's a future work here which would make this path adjustable!
  2. Configure the server and monitored nodes

    Modify the field endpointUrl in the file published_nodes.json in config folder which contain the server IP and Port that you want to connect to, as well as the node Ids you would like to monitor. Here's the example:

    {
      "serInfo": [
         {
            "endpointName": "UNO-1372G",
            "endpointUrl": "opc.tcp://localhost:26543",
            "certExist": false,
            "userIdentity": {
               "userName": "",
               "password": ""
            },
            "OpcNodes": [
               {
                  "Id": "ns=1;s=Temperature",
                  "DisplayName": "M140001"
               },
               {
                  "Id": "ns=1;s=FanSpeed",
                  "DisplayName": "M140002"
               },
               {
                  "Id": "ns=1;s=PumpSpeed",
                  "DisplayName": "M140003"
               }
            ]
         }
      ]
    }

    In this case, we are connecting to an OPC-UA server running on the same host as our Greengrass Core, on port 26543, and monitoring multiple nodes that has an OPC-UA Id 'ns=1;s=Temperature', 'ns=1;s=FanSpeed', and 'ns=1;s=PumpSpeed'.

    Besides, There are two additional configuration for OPC-UA Server:

    • certExist: This is a configuration that support certificate validation or not. The OPC-UA adapter will not validtate the OPC-UA server's certificate if this flag set to false, otherwise it will go to check the certificate from the OPC-UA server.
    • userIdentity: This is a configuration to support user identity mechanism from the OPC-UA server. Please fill in the userName and password recognized between the OPC-UA adapter and the OPC-UA server.
      "userIdentity":
      {
      "userName": "user1",
      "password": "password1"
      }

      Note:

    • For the node information output from Advantech Edgelink, we provide an node converter tool to convert it to published_nodes.json, and the following is the example:
      • sample.csv : The node information file generated by Advantech Edgelink.
      • nodeFileParser.py : The tool to convert the node information file into published_nodes.json.
      • Commands:
        python3 nodeFileParser.py --inputFile ./sample.csv --serverName UNO-1372G --endpointURL opc.tcp://localhost:26543 --userName testName --password testPassword --userIdentity --certExist
      • Please take use of help command python3 nodeFileParser.py -h for more detail.
  3. Configure to authenticate trusted server

    Modify the field certPath in cert_config.json, which is used to tell OPC-UA client the received OPC-UA server certificate in Certificate List is matched or not:

     {
        "certPath": "Directory"
     }

    Once there's no any certificate matched in the certPath, then the OPC-UA client wouldn't go on the communication with the OPC-UA server.

  4. Configure client_config.json file:

    • checkServerConfigInterval : polling time of Lambda.
      • Modify the field checkServerConfigInterval to adjust the polling interval in mini second of Lambda reading json file.
    • reportStatus: Report system status.
      • Used to write counter into a file to let any other cooperative process aware this lambda still works.
    • reportTolerance: Counters to access file to report status.
      • The access right to the file to report status might not correct, use this configuration to prevent system warnings.
    • customUploadDataStrategy: The mechanism to keep the received data locally, then it will send them to AWS IoT Core in designated period defined in field pollingInSecond.
      • enableStrategy: The field used to decide to enable the mechanism or not.
      • pollingInSecond: The designated period to send the retained data out to AWS IoT Core.
      • sendAllDataToCloud: Set to true in this field used to send all latest received data to AWS IoT Core, otherwise only the received data in the designated time will be sent.
    {
      "keepSessionAlive": true,
      "connectionStrategy": {
         "maxRetry": 100000,
         "initialDelay": 2000,
         "maxDelay": 10000
      },
      "checkServerConfigInterval": 1000,
      "reportStatus": false,
      "reportTolerance": 5,
      "customUploadDataStrategy": {
         "enableStrategy": true,
         "pollingInSecond": 10,
         "sendAllDataToCloud": true
      }
    }
  5. Upload your Lambda

    Create a Greengrass Lambda function. You can find more details on how to do that in Configure the Lambda Function for AWS IoT Greengrass. In a nutshell, create a Lambda function code archive by doing the following:

    # Archive the whole directory as a zip file under 
    # the folder aws-iot-greengrass-opcua-adapter/greengrass-opcua-adapter-nodejs
    # ├── Directory
    # ├── config
    # ├── config_agent.js
    # ├── index.js
    # ├── node_modules
    # ├── package.json
    # ├── patch
    # ├── pics
    # ├── subscriber.js
    # └── tool
    zip -r opcuaLambda.zip * -x \*.git\*

    Add this Lambda to your Greengrass Group. Details are, again, in: Configure the Lambda Function for AWS IoT Greengrass.

  6. Configure and Deploy the Lambda function to your Greengrass Group

    After creating your AWS Lambda function, you add it to your Greengrass Group. Follow the instructions in same section as above.

    • Make sure to specify the Lambda function as Long-Running. \[Greengrass OPCUA Lambda Long-Run.\]
    • Give it at least 64MB of memory size. \[Greengrass OPCUA Lambda Memory.\]
    • Configure the environment variable AWS_LAMBDA_OPCUA_ADAPTER_CONFIG_FILE_PATH for configurable json file in Group-specific Lambda configuration. \[Greengrass OPCUA configure environment variable for configuration file path.\]
    • Configure the environment variable
      • Set AWS_LAMBDA_OPCUA_ADAPTER_SEND_ALL_DATA_TO_CLOUD to true to send all latest received data to AWS IoT Core.
      • This variable is an optional setting, setting it to false or being not to set it will only send the received data in designated period to AWS IoT Core. \[Greengrass OPCUA configure environment variable for sending all received data to AWS IoT Cloud.\]
      • Set AWS_LAMBDA_OPCUA_ADAPTER_POLL_IN_SECOND to the number used to overwrite the default setting pollingInSecond in client_config.json.
      • Set AWS_LAMBDA_OPCUA_ADAPTER_ACCUMULATIVE_WHITE_LIST to configure the candidates to be sent to the cloud after accumulating their data. The candidates in the white list should be separated by a comma such as the following format:
        export AWS_LAMBDA_OPCUA_ADAPTER_ACCUMULATIVE_WHITE_LIST=HXC1:40020,HXC1:40021,HXC1:40022

    You can now create a deployment with your latest configuration. You can find details in Deploy Cloud Configurations to an AWS IoT Greengrass Core Device.

Verify that your Lambda function is receiving OPC-UA Publishes and posting them onto Greengrass

As described in the Architecture section, your Lambda function should start receiving messages from your OPC-UA server. If you are using your own custom OPC-UA server, make sure you trigger a change in the OPC-UA node Id you specified, so that you see the change received by your Lambda function. If you are using the example server above, the PumpSpeed node is configured to simulate a series of consecutive updates, so you should expect your Lambda function to receive multiple messages a second.

You can see messages received by your Lambda function in one of two ways:

Note:

License

This solution is licensed under the MIT-0 License. See the LICENSE file.