PLCnext on LinkedInPLCnext on Instagram  PLCnext on YouTube Github PLCnext CommunityStore PLCnext Community

 

 How to create a Blog Entry

Automate your development workflow with Visual Studio Code

In my last post I wrote about our development setup to write C++ for PLCnext here in IMA Engineering at Phoenix Contact Deutschland GmbH. So you maybe already know that we are using Visual Studio Code to write C++ for PLCnext. In this post I want to show you how you can automate and therefore shorten your deploy and development cycle with Visual Studio Code tasks.

 

Prerequisites

For this example you need following:

  • Visual Studio Code with following extension installed
    • CMake (twxs.cmake)
    • CMake Tools (vector-of-bool.cmake-tools)
    • C/C++ (ms-vscode.cpptools)
  • Ninja build
  • AXC F 2152 Firmware 2019.0 LTS or higher
  • PLCnext Engineer 2019.0 LTS or higher
  • PLCnext Command Line Interface (CLI) 2019.0 LTS or higher
  • PLCnext Software Development Kit (SDK), installed using the CLI
  • Linux based build system

Setup the project

Setup the PLCnext C++ project like described in the PLCnext blog entry How to use Visual Studio Code to write C++ for PLCnext.

You should now be able to build the project by calling CMake Install from the Command Palette. You can open the Visual Studio Code Command Palette by pressing the keys F1 or Ctrl+Shift+P.

To deploy the Library to the target build the PLCnext Engineer library include the library in the PLCnext Engineer Project and download the project.

This workflow becomes time consuming if you only want to deploy an update made to the C++ part of your project. If this is the case it is sufficient to only deploy the updateed shared object library on the target and restart the PLCnext runtime.

SSH key based authentication

To automate the download of the shared object library and restart of the PLCnext runtime we need to setup key based authentication for the ssh server on the controller. This is needed because we don’t want to type in our password on each action.

Edit the ssh server configuration /etc/ssh/sshd_config on the target controller and modify the AuthorizedKeysFile and PermitRootLogin options.

Remember to deactivate the PermitRootLogin option on production systems. It is not recommended to leave this option activated in production systems.

PermitRootLogin yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
AuthorizedKeysFile .ssh/authorized_keys /home/%u/.ssh/authorized_keys

The PermitRootLogin allows to connect to the ssh server with the root user. The AuthorizedKeysFile option specifies files to look for authorized keys. We need to add the /home/%u/.ssh/authorized_key file here. The %u parameter will expand to the user name that tries to log in to the ssh server.

So why is the additional file needed? This is because the home directory of the admin user is set to /opt/plcnext and this directory is the working directory of the PLCnext runtime. The ssh server needs restricted file permissions to the directory in which the .ssh folder is located. The directory must not be writable by the group. So if we would use the home directory of the admin user, the group plcnext would not have write permissions to the plcnext runtime working directory anymore. This is why we add the explicit location to the AuthorizedKeysFile option. So we can place the file authorized_keys in a directory in /home/admin/.ssh even if the actual home directory of the user is set to another location.

Create a ssh key for your user on the build machine if not already done. Do not specify a password for your key otherwise we have to setup a key agent to provide the encrypted keys and this is not part of this example.

ssh-keygen -t ed25519

the option ed25519 uses a elliptic curve cryptography based algorithm for the key.

Copy the key to the target controller for the root user. This requires that a password for the root user was set with sudo passwd root on the controller.

ssh-copy-id -i ~/.ssh/id_ed25519.pub This email address is being protected from spambots. You need JavaScript enabled to view it.

This will add the public key into the authorized_keys file in the home directory of the root user /home/.root/ssh/authorized_keys. The ssh-copy-id tool can not be used to copy the key for the admin user because the tool would add the key to the home directory of the user. For the admin user the home directory is set to /opt/plcnext so we need to manually copy the public key. Login with the admin user to the target controller and run the following commands.

su -
mkdir -p /home/admin/.ssh
chown -R admin:plcnext /home/admin
exit
chmod 755 /home/admin
chmod 700 /home/admin/.ssh
touch /home/admin/.ssh/authorized_keys
chmod 600 /home/admin/.ssh/authorized_keys

Now from your build machine run

cat ~/.ssh/id_ed25519.pub | ssh This email address is being protected from spambots. You need JavaScript enabled to view it. "cat >> /home/admin/.ssh/authorized_keys"

This will append the public key to the authorize_keys file on the target controller.

Finally restart the ssh server on the controller.

su -
/etc/init.d/sshd restart
exit
exit

We should now be able to login to the controller with our ssh key and without password. Try to connect again to the controller.

ssh This email address is being protected from spambots. You need JavaScript enabled to view it.
admin@axcf2152:~$

It should directly connect without prompting for a password.

Visual Studio Code tasks

Now lets create a task to deploy the shared object library and restart the PLCnext runtime. First log in to the controller with the admin user and check the directory layout and library name of the project.

admin@axcf2152:~$ ls -al projects/PCWE/Libs
total 12
drwxrwxr-x 3 plcnext_firmware plcnext 4096 Apr 17 09:50 .
drwxrwxr-x 1 admin            plcnext 4096 Apr 17 09:50 ..
drwxrwxr-x 3 plcnext_firmware plcnext 4096 Apr 17 09:50 PxcdBsa.DataAccess

Here you can see the folder PxcdBsa.DataAccess. The C++ library is deployed to this folder. It consists of the library name and, if used, also the root namespace of the library.

admin@axcf2152:~$ ls -al projects/PCWE/Libs/PxcdBsa.DataAccess/
total 244
drwxrwxr-x 3 plcnext_firmware plcnext   4096 Apr 17 09:50 .
drwxrwxr-x 3 plcnext_firmware plcnext   4096 Apr 17 09:50 ..
-rw-rw-r-- 1 plcnext_firmware plcnext      8 Apr 17 09:50 CRC32.crc
drwxrwxr-x 3 plcnext_firmware plcnext   4096 Apr 17 09:50 DataAccessComponent
-rw-rw-r-- 1 plcnext_firmware plcnext    625 Apr 17 09:50 PxcdBsa.DataAccess.libmeta
-rw-rw-r-- 1 plcnext_firmware plcnext    298 Apr 17 09:50 PxcdBsa.DataAccess.typemeta
-rw-rw-r-- 1 plcnext_firmware plcnext 225168 Apr 17 10:14 libPxcdBsa.DataAccess.so

Here you can see the name of the shared object file that was deployed to the controller. Notice that it was renamed to libPxcdBsa.DataAccess.so to match the library name of the PLCnext Engineer library.

So remember the directory and library name we will need this later in our task.

Create a Deploy task in the Visual Studio Code task file .vscode/tasks.json.

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Deploy",
            "type": "shell",
            "command": "scp build/axcf2152_2019.3/out/lib/libDataAccess.so This email address is being protected from spambots. You need JavaScript enabled to view it.:/opt/plcnext/projects/PCWE/Libs/PxcdBsa.DataAccess/libPxcdBsa.DataAccess.so && ssh This email address is being protected from spambots. You need JavaScript enabled to view it. \"/etc/init.d/plcnext restart\"",
            "options": {
                "cwd": "${workspaceFolder}"
            },
            "problemMatcher": []
        }
    ]
}

There are two parts in this command. First we copy the library from our CMAKE_STAGING_PREFIX install directory build/axcf2152_2019.3/out to the directory on our target. Notice the renaming in this command. The second command is appendend with and && and will run after the first command has finished. The second command logs in with the root user and restarts the PLCnext runtime on the target.

Thats it. You can now open the Command Palette in Visual Studio Code. Enter CMake Install and then Tasks: Run Task and choose the Deploy task. This will download the library and restart the runtime. No need to genrate the PLCnext Engineer library and update the PLCnext Engineer project anymore.

But don't forget to include the final C++ library into your PLCnext Engineer project. Otherwise the old library will be downloaded from PLCnext Engineer again.