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 root@192.168.1.10
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 admin@192.168.1.10 "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 admin@192.168.1.10
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 admin@192.168.1.10:/opt/plcnext/projects/PCWE/Libs/PxcdBsa.DataAccess/libPxcdBsa.DataAccess.so && ssh root@192.168.1.10 \"/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.
Leave a Reply
You must be logged in to post a comment.