#!/bin/sh # File/Project has to be the last argument FILE=${@:$#} PROJECT_NAME=$(echo "${FILE##*/}" | sed 's/\.[^.]*$//') SCRIPT=$(readlink -f "$0") SILECS_VERSION=2.2.0 SILECS_BASE=/common/usr/cscofe/silecs FESA_VERSION=7.3.0 FESA_BASE=/opt/fesa/fesa-fwk/$FESA_VERSION N_ARGUMENTS=$# function help { echo -e "" echo -e "Usage: silecs [OPTION] [FILE]" echo -e "" echo -e "Script in order to model PLC devices in FESA by using the Silecs framework." echo -e "" echo -e "\t -c \t create new .silecsdesign/.silecsdeploy file for the specified FESA .design/.deploy file" echo -e "\t -v \t validate silecs xml file" echo -e "\t -g \t generate source code for silecs xml file" echo -e "\t -d \t start diagnostic tool for silecs xml file" echo -e "\t -r \t release parameter file to FEC (TODO)" echo -e "\t -m \t migrate silecs design/deploy file to new silecs version (TODO)" echo -e "\t -h \t show this help" echo -e "" echo -e "Examples:" echo -e "" echo -e "\t To create a new file 'MyClass.silecsdesign' for the FESA class." echo -e "\t\t silces -c ~/workspace/MyClass/src/MyClass.design" echo -e "" echo -e "\t To validate 'MyClass.silecsdesign'." echo -e "\t\t silces -v ~/workspace/MyClass/src/MyClass.silecsdesign" echo -e "" echo -e "\t To add missing properties and value-items specified in 'MyClass.silecsdesign' into the FESA document 'MyClass.design'." echo -e "\t This will as well ate C++ code." echo -e "\t\t silces -g ~/workspace/MyClass/src/MyClass.silecsdesign" echo -e "" echo -e "Check the Silecs Wiki for more info: https://www-acc.gsi.de/wiki/Frontend/SILECS" echo -e "" exit 1; } if [ $N_ARGUMENTS -lt 1 ] then echo "Error: Wrong number of arguments supplied." help fi function assert_n_arguments { if [ $N_ARGUMENTS -lt $1 ] then echo "Error: Wrong number of arguments supplied." help fi } function silecs_validate { assert_n_arguments 2 EXTENSION=$(echo "$FILE" | sed 's/^.*\.//') # Resolve possible relative path FILE=$(realpath "$FILE" ) case $EXTENSION in silecsdesign) SCHEMA=$SILECS_BASE/silecs-model/$SILECS_VERSION/xml/DesignSchema.xsd ;; silecsdeploy) SCHEMA=$SILECS_BASE/silecs-model/$SILECS_VERSION/xml/DeploySchema.xsd ;; *) echo "Error: Passed file for validation needs to have the extension '.silecsdesign' or '.silecsdeploy'" exit 1 ;; esac echo "validating $FILE" echo "" xmllint --schema $SCHEMA $FILE --noout RESULT=$? echo "" if [ $RESULT -eq 0 ] then echo "File is valid" else echo "File is not valid. Check errors above." fi return $RESULT # TODO: Implement jave-rules - See here for details: https://gitlab.com/al.schwinn/silecs-cli/-/issues/3 } function execute_python { PYTHON_FILE=$1 PYTHON_METHOD=$2 SILECS_CODEGEN_BASE=$SILECS_BASE/silecs-codegen/$SILECS_VERSION/xml/ SILECS_CODEGEN_MIGRATION=$SILECS_BASE/silecs-codegen/$SILECS_VERSION/xml/migration # TODO: Check for concrete fesa version - See here for details: https://gitlab.com/al.schwinn/silecs-cli/-/issues/4 SILECS_CODEGEN_FESA=$SILECS_BASE/silecs-codegen/$SILECS_VERSION/xml/fesa/fesa_7_3_0/ ARGUMENTS="" for ((i=3; i<=$#; i++)) do ARGUMENTS+="'" ARGUMENTS+=${!i} ARGUMENTS+="'" if [ $i -ne $# ] then ARGUMENTS+="," fi done #echo $ARGUMENTS python3 -c "import sys;\ sys.path.append('$SILECS_CODEGEN_BASE');\ sys.path.append('$SILECS_CODEGEN_MIGRATION');\ sys.path.append('$SILECS_CODEGEN_FESA');\ import $PYTHON_FILE;\ $PYTHON_FILE.$PYTHON_METHOD($ARGUMENTS);" return $? } function silecs_generate { assert_n_arguments 2 silecs_validate if [ $? -ne 0 ]; then echo "" echo "Error: $FILE is not valid. Please fix all xml errors before generating code !" exit 1 fi # Resolve possible relative path FILE=$(realpath "$FILE" ) EXTENSION=$(echo "$FILE" | sed 's/^.*\.//') case $EXTENSION in silecsdesign) silecs_generate_silecsdesign ;; silecsdeploy) silecs_generate_silecsdeploy ;; *) echo "Error: Passed file for code generation needs to have the exctension '.silecsdesign' or '.silecsdeploy'" exit 1 ;; esac } function silecs_generate_silecsdesign { SILECS_DESIGN_FILE=$FILE PROJECT_PATH=$(dirname "$(dirname "$FILE")") WORKSPACE_PATH=$(dirname "$PROJECT_PATH") SILECS_LIBRARY_BASE=$SILECS_BASE/silecs-communication-cpp/$SILECS_VERSION FESA_DESIGN_FILE=$PROJECT_PATH/src/$PROJECT_NAME.design FESA_XSD=$FESA_BASE/fesa-model-gsi/xml/design/design-gsi.xsd echo "generating code for $PROJECT_NAME ..." echo "" if [ -f $FESA_DESIGN_FILE ]; then echo "Please note that old, obsolete xml-elements are not deleted automatically! Sometimes this can lead to an invalid FESA Design document!" echo "If this is the case, please remove the obsolete elements by hand." echo "Creating a backup of the existing FESA file at: $FESA_DESIGN_FILE.backup" echo "" cp $FESA_DESIGN_FILE $FESA_DESIGN_FILE.backup fi execute_python generateFesaDesign fillDesignFile $FESA_VERSION $PROJECT_NAME $WORKSPACE_PATH $FESA_XSD execute_python generateSourceCode genCppFiles $PROJECT_NAME $WORKSPACE_PATH $SILECS_DESIGN_FILE echo "" echo "Please not that you need to add the dependency to the silecs library to your Makefile." echo "Here an example: https://www-acc.gsi.de/wiki/Frontend/Silecs_1_0_0_CodeSnippets#Dependency_in_Makefile.specific !" echo "" echo "Code generation finished" } function silecs_generate_silecsdeploy { SILECS_DEPLOY_FILE=$FILE PROJECT_PATH=$(dirname "$(dirname "$FILE")") WORKSPACE_PATH=$(dirname "$PROJECT_PATH") SILECS_LIBRARY_BASE=$SILECS_BASE/silecs-communication-cpp/$SILECS_VERSION FESA_DEPLOY_FILE=$PROJECT_PATH/src/$PROJECT_NAME.deploy FESA_XSD=$FESA_BASE/fesa-model-gsi/xml/deployment/deployment-gsi.xsd FESA_GSI_TEMPLATE=$FESA_BASE/fesa-model-gsi/xml/design/templates/GSIClassTemplate.xml SILECS_DEPLOY_VERSION="unused_parameter" echo "generating code for $PROJECT_NAME ..." echo "" if [ -f $FESA_DESIGN_FILE ]; then echo "Please note that old, obsolete xml-elements are not deleted automatically! Sometimes this can lead to an invalid FESA document!" echo "If this is the case, please remove the obsolete elements by hand." echo "Creating a backup of the existing FESA file at: $FESA_DEPLOY_FILE.backup" echo "" cp $FESA_DEPLOY_FILE $FESA_DEPLOY_FILE.backup fi execute_python genparam genParam $WORKSPACE_PATH $PROJECT_NAME $SILECS_DEPLOY_VERSION $SILECS_VERSION execute_python genplcsrc genPlcSrc $WORKSPACE_PATH $PROJECT_NAME $SILECS_VERSION execute_python genduwrapper genDuWrapper $WORKSPACE_PATH $PROJECT_NAME $SILECS_DEPLOY_VERSION execute_python fillFESADeployUnit fillDeployUnit $WORKSPACE_PATH $PROJECT_NAME $FESA_XSD $FESA_VERSION echo "" echo "Please not that you need to add the dependency to the silecs library to your Makefile." echo "Here an example: https://www-acc.gsi.de/wiki/Frontend/Silecs_1_0_0_CodeSnippets#Dependency_in_Makefile.specific !" echo "" echo "Code generation finished" } function silecs_create_design { NEWFILEPATH=$1 DATE=$(date +%x) SCHEMA_PATH=$SILECS_BASE/silecs-model/$SILECS_VERSION/xml/DesignSchema.xsd DESIGN_TEMPLATE='<?xml version="1.0" encoding="UTF-8"?> <SILECS-Design silecs-version="'$SILECS_VERSION'" created="'$DATE'" updated="'$DATE'" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="'$SCHEMA_PATH'"> <Information> <Owner user-login="'$USER'"/> <Editor user-login="'$USER'"/> </Information> <SILECS-Class name="'$PROJECT_NAME'" version="0.1.0" domain="OPERATIONAL" > <Acquisition-Block name="MyBlock" generateFesaProperty="true"> <Acquisition-Register name="myRegister" generateFesaValueItem="true"> <scalar format="int32"/> </Acquisition-Register> </Acquisition-Block> </SILECS-Class> </SILECS-Design>' if [ -f $NEWFILEPATH ]; then echo "Error: There is already a .silecsdesign file available: $NEWFILEPATH" exit 1 fi echo $DESIGN_TEMPLATE | xmllint --format - > $NEWFILEPATH echo "" echo "created new silecsdesign: $NEW_FILE" } function silecs_create_deploy { NEWFILEPATH=$1 DATE=$(date +%x) SCHEMA_PATH=$SILECS_BASE/silecs-model/$SILECS_VERSION/xml/DeploySchema.xsd DEPLOY_TEMPLATE='<?xml version="1.0" encoding="UTF-8"?> <SILECS-Deploy silecs-version="'$SILECS_VERSION'" created="'$DATE'" updated="'$DATE'" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="'$SCHEMA_PATH'"> <Information> <Owner user-login="'$USER'"/> <Editor user-login="'$USER'"/> </Information> <Deploy-Unit name="'$PROJECT_NAME'" version="0.1.0"/> <SilecsDesign silecs-design-name="" silecs-design-version=""/> <Controller host-name=""> <Siemens-PLC system="TIA-PORTAL" model="SIMATIC_S7-300" protocol="DEVICE_MODE" base-DB-number="1"> <Device silecs-device-label="dev0" silecs-design-ref="" fesa-device-name="" fesa-fec-name=""/> </Siemens-PLC> </Controller> </SILECS-Deploy>' if [ -f $NEWFILEPATH ]; then echo "Error: There is already a .silecsdeploy file available: $NEWFILEPATH" exit 1 fi echo $DEPLOY_TEMPLATE | xmllint --format - > $NEWFILEPATH echo "" echo "created new silecsdeploy: $NEW_FILE" } function silecs_create { assert_n_arguments 2 # Resolve possible relative path FILE=$(realpath "$FILE" ) EXTENSION=$(echo "$FILE" | sed 's/^.*\.//') FILE_PATH=$(dirname "$FILE") case $EXTENSION in design) NEW_FILE=$FILE_PATH/$PROJECT_NAME.silecsdesign silecs_create_design $NEW_FILE ;; deploy) NEW_FILE=$FILE_PATH/$PROJECT_NAME.silecsdeploy silecs_create_deploy $NEW_FILE ;; *) echo "Error: Passed FESA file needs to have the extension '.design' or '.deploy'" exit 1 ;; esac } function silecs_open_diag { assert_n_arguments 2 # Resolve possible relative path FILE=$(realpath "$FILE" ) EXTENSION=$(echo "$FILE" | sed 's/^.*\.//') if [ $EXTENSION -ne "silecsdeploy"]; then echo "Error: diag tool only can be opened for a -silecsdeploy file" fi SILECS_DIAG_TOOL=$SILECS_BASE/silecs-diagnostic-cpp/$SILECS_VERSION/bin/x86_64/silecs-diagnostic SNAP7_LIB_FOLDER=$SILECS_BASE/snap7/$SILECS_VERSION/bin/x86_64-linux LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SNAP7_LIB_FOLDER $SILECS_DIAG_TOOL -d $FILE } function silecs_release_param { # TODO - See here for details: https://gitlab.com/al.schwinn/silecs-cli/-/issues/5 echo "Not implemented yet .. please copy the param file by hand for now" } function silecs_migrate { # TODO - See here for details: https://gitlab.com/al.schwinn/silecs-cli/-/issues/7 echo "Not implemented yet .. please update/migrate by hand for now" } while getopts c:v:g:d:r:m:h flag do case "${flag}" in c ) silecs_create;; v ) silecs_validate;; g ) silecs_generate;; d ) silecs_open_diag;; r ) silecs_release_param;; m ) silecs_migrate;; h ) help;; esac done