Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • silecs/opensilecs
  • k.fugiel/opensilecs
  • s.kupiecki/opensilecs
3 results
Show changes
Commits on Source (94)
Showing
with 458 additions and 335 deletions
......@@ -9,3 +9,6 @@ venv
builds
builds/*
.data
build
build-yocto
test/build-test
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>snap7</name>
<name>silecs</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>org.python.pydev.PyDevBuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.python.pydev.pythonNature</nature>
</natures>
</projectDescription>
cmake_minimum_required(VERSION 3.20.2)
project(opensilecs VERSION 3.0.0)
include(CTest)
enable_testing()
option(BUILD_COMMUNICATION_LIB_ONLY "Setup only the Silecs communication library." OFF)
option(ADD_LATEST_LINK "Link this install release as latest." ON)
set(GSI_SILECS_PATH "/common/usr/cscofe/silecs" CACHE STRING "GSI_SILECS_PATH")
set(BUILD_TARGET "x86_64" CACHE STRING "BUILD_TARGET")
# Use, i.e. don't skip the full RPATH for the build tree.
set(CMAKE_SKIP_BUILD_RPATH FALSE)
# When building, don't use the install RPATH already (but later on when installing).
set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
# Add the automatically determined parts of the RPATH which point to directories outside the build
# tree to the install RPATH.
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if (BUILD_COMMUNICATION_LIB_ONLY)
add_subdirectory(silecs-communication-cpp)
else()
add_subdirectory(silecs_cli)
add_subdirectory(silecs-codegen)
add_subdirectory(silecs-model)
add_subdirectory(silecs-communication-cpp)
add_subdirectory(silecs-cli-client)
add_subdirectory(silecs-diagnostic-cpp)
# Create a silecs_environment file which can be sourced to use the silecs command line tools.
FILE(WRITE ${CMAKE_BINARY_DIR}/silecs_environment
"SILECS_VERSION=${CMAKE_PROJECT_VERSION}\n"
"export PATH=${CMAKE_INSTALL_PREFIX}/\$SILECS_VERSION/silecs-cli:\${PATH}\n"
"export PATH=${CMAKE_INSTALL_PREFIX}/\$SILECS_VERSION/silecs-cli-client/bin/x86_64:\${PATH}\n"
"export PATH=${CMAKE_INSTALL_PREFIX}/\$SILECS_VERSION/silecs-diagnostic-cpp/bin/x86_64:\${PATH}\n"
)
# The silecs_environment file is released/installed together with the other sub-projects.
install(
FILES ${CMAKE_BINARY_DIR}/silecs_environment
DESTINATION ${CMAKE_INSTALL_PREFIX}/${CMAKE_PROJECT_VERSION}/
)
endif()
if(ADD_LATEST_LINK)
# Symlink this release as latest.
install(CODE "execute_process( \
COMMAND ${CMAKE_COMMAND} -E create_symlink \
${CMAKE_INSTALL_PREFIX}/${CMAKE_PROJECT_VERSION} \
${CMAKE_INSTALL_PREFIX}/latest )"
)
endif()
......@@ -8,13 +8,20 @@ Supported PLC vendors: Siemens, Beckhoff(untested), Schneider(untested)
## Getting Started
If you plan to just use the silecs framework, please check the [Opensilecs Wiki](https://www-acc.gsi.de/wiki/Frontend/SILECS) for handson courses and all required documentation.
If you plan to just use the silecs framework, please check the [Opensilecs Wiki](https://www-acc.gsi.de/wiki/Frontend/SILECS) for hands-on courses and all required documentation.
## Build & Install
If you want to touch the code of silecs itself, you can build it like this:
If you want to touch the code of silecs itself, you can build it using CMake.
There are three scripts available `configure.sh`, `build.sh` and `install.sh`. To setup the CMake build environment use `configure.sh`. The script accepts a few options (use `configure.sh -h` to see available options)
with which the release path, target and the build type can be configured. Once the build is configured
use `build.sh` to compile all the projects and `install.sh` to install them to the release path you
provided to `configure.sh`. In case no release path is provided the project will be released/installed
to the build directory. You can optionally specify the build target to `build.sh` and `install.sh`
scripts which can be used to build with yocto SDK.
`./build_and_install.sh v1.2.3 /home/user/MyCustomDir`
Note: when using the option `--target yocto` a different build directory is used `build-yocto`.
This means that for a full yocto build you need to provide the `--target yocto` option to all three scripts (`configure.sh`, `build.sh` and `install.sh`).
Please open issues / merge requests in order to upstream your changes. ([GSI account required](https://www-oracle.gsi.de/pls/gsi/a_admin.acc_antrag))
......
#!/bin/bash
TARGET=x86_64
usage(){
echo "Usage: $0 [--target yocto]"
echo "-t | --target"
echo " $TARGET when not specified"
echo "-h | --help"
exit 1
}
USER_TARGET=$TARGET
# Loop through all the arguments and determine provided options.
while [ "${1:-}" != "" ]; do
case $1 in
-t | --target ) shift
USER_TARGET=$1
;;
-h | --help ) usage
exit
;;
* ) usage
exit 1
esac
shift
done
# Based on the build target select the build directory (build by default & build-yocto for yocto SDK).
# Using a different build directory for yocto builds since mixing between the two cmake versions doesn't work to well.
BUILD_DIR_NAME=build
if [[ $USER_TARGET == yocto ]]; then
TARGET=yocto
BUILD_DIR_NAME=build-yocto
elif [[ $USER_TARGET != x86_64 ]]; then
echo "Unsupported target" $USER_TARGET
usage
exit 1
fi
SCRIPT_PATH=$(dirname $(readlink -f "$0"))
BUILD_DIR=$SCRIPT_PATH/$BUILD_DIR_NAME
echo "------------------------------------------------------------------------"
echo "Build target: " $TARGET
echo "Build directory: " $BUILD_DIR
echo "------------------------------------------------------------------------"
cmake --build $BUILD_DIR -j 8
\ No newline at end of file
#!/bin/bash
# release locations
GLOBAL_RELEASE_DIR=/common/usr/cscofe/silecs
function help {
echo -e ""
echo -e "Script in order to build and install the complete silecs framework"
echo -e ""
echo -e "Usage:"
echo -e ""
echo -e "\t Install version 1.2.3 to default directory ($GLOBAL_RELEASE_DIR):"
echo -e "\t\t ./build_and_install.sh 1.2.3"
echo -e ""
echo -e "\t Install version 1.2.3 to custom directory:"
echo -e "\t\t ./build_and_install.sh 1.2.3 /home/user/MyCustomDir"
echo -e ""
exit 1;
}
if [ $# -lt 1 ]
then
echo "Error: Wrong number of arguments supplied."
help
fi
if [[ "$1" == "-h" || "$1" == "--help" ]];
then
help
fi
# Build and install instructions for modbus library:
# ./configure --prefix=/common/usr/cscofe/silecs/modbus/3.1.7 --enable-static
# make -j4
# make install
# List of silecs packages which can be released
PACKAGES="silecs-codegen silecs-model snap7 silecs-communication-cpp silecs-diagnostic-cpp silecs_cli silecs-cli-client"
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
SILECS_VERSION=$1
if [ -z "$2" ]
then
RELEASE_DIR_BASE=$GLOBAL_RELEASE_DIR
else
RELEASE_DIR_BASE=$2
fi
for PACKAGE in $PACKAGES; do
echo "installing package ${PACKAGE} into ${RELEASE_DIR_BASE}"
mkdir -p ${RELEASE_DIR_BASE}
${PACKAGE}/install.sh ${RELEASE_DIR_BASE} ${SILECS_VERSION}
if [ "$?" -eq "1" ]; then
echo "Error: Package ${PACKAGE} skipped"
fi
done
# Create silecs environment file to be easily sourced for users
echo -e "Create silecs environment file"
SILECS_ENV_FILE=${RELEASE_DIR_BASE}/${SILECS_VERSION}/silecs_environment
echo $SILECS_ENV_FILE
touch $SILECS_ENV_FILE
echo -e "SILECS_VERSION=${SILECS_VERSION}" >> $SILECS_ENV_FILE;
echo -e "export PATH=${RELEASE_DIR_BASE}/\$SILECS_VERSION/silecs-cli:\${PATH}" >> $SILECS_ENV_FILE;
echo -e "export PATH=${RELEASE_DIR_BASE}/\$SILECS_VERSION/silecs-cli-client/bin/x86_64:\${PATH}" >> $SILECS_ENV_FILE;
echo -e "export PATH=${RELEASE_DIR_BASE}/\$SILECS_VERSION/silecs-diagnostic-cpp/bin/x86_64:\${PATH}" >> $SILECS_ENV_FILE;
# Update links to latest versions
echo -e "Update links to silecs versions"
python3 setup_silecs_env.py ${RELEASE_DIR_BASE}
exit 0
#!/bin/bash
YOCTO_SDK_ENV=/common/usr/embedded/yocto/fesa/current/sdk/environment-setup-core2-64-ffos-linux
GLOBAL_RELEASE_DIR=/common/usr/cscofe/silecs/
TARGET=x86_64
usage(){
echo "Usage: $0 [--release [path]] [--target yocto]"
echo "-r | --release"
echo " Install path prefix. If only option is provided without any paths $GLOBAL_RELEASE_DIR is used."
echo "-t | --target"
echo " $TARGET when not specified"
echo "-h | --help"
exit 1
}
DEBUG=y
USER_RELEASE_DIR=""
USER_TARGET=$TARGET
# Loop through all the arguments and determine provided options.
while [ "${1:-}" != "" ]; do
case $1 in
# In case the next argument is empty or it starts with a dash,
# it means we only got --release, otherwise we expect an argument
# after --release and we need to shift.
-r | --release ) if [[ $2 == -* ]] || [[ $2 == "" ]]; then
USER_RELEASE_DIR=$GLOBAL_RELEASE_DIR
else
shift
USER_RELEASE_DIR=$1
fi
DEBUG=""
;;
-t | --target ) shift
USER_TARGET=$1
;;
-h | --help ) usage
exit
;;
* ) usage
exit 1
esac
shift
done
# Based on the build target select the build directory (build by default & build-yocto for yocto SDK).
# Using a different build directory for yocto builds since mixing between the two cmake versions doesn't work to well.
BUILD_DIR_NAME=build
if [[ $USER_TARGET == yocto ]]; then
TARGET=yocto
BUILD_DIR_NAME=build-yocto
elif [[ $USER_TARGET != x86_64 ]]; then
echo "Unsupported target" $USER_TARGET
usage
exit 1
fi
SCRIPT_PATH=$(dirname $(readlink -f "$0"))
BUILD_DIR=$SCRIPT_PATH/$BUILD_DIR_NAME
# If user didn't provide a release directory use the build directory. Otherwise use whatever the user provided.
if [[ $USER_RELEASE_DIR == "" ]]; then
RELEASE_DIR=$BUILD_DIR
else
RELEASE_DIR=$USER_RELEASE_DIR
fi
BUILD_TYPE=Release
# Enable debug compilation when not releasing.
if [[ $DEBUG == y ]]; then
BUILD_TYPE=Debug
fi
echo "------------------------------------------------------------------------"
echo "Build type: " $BUILD_TYPE
echo "Build target: " $TARGET
echo "Build directory: " $BUILD_DIR
echo "Install directory:" $RELEASE_DIR
echo "------------------------------------------------------------------------"
if [[ $TARGET == yocto ]]; then
if [ ! -f "$YOCTO_SDK_ENV" ]; then
echo "Error: Build environment for target '$TARGET' not found at '$YOCTO_SDK_ENV'."
echo "configure aborted"
exit 1
fi
# Configure yocto environment.
unset LD_LIBRARY_PATH; source $YOCTO_SDK_ENV
cmake -S . -B $BUILD_DIR -DBUILD_TARGET=$TARGET -DCMAKE_INSTALL_PREFIX=$RELEASE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DBUILD_COMMUNICATION_LIB_ONLY=ON -DADD_LATEST_LINK=OFF
else
cmake -S . -B $BUILD_DIR -DBUILD_TARGET=$TARGET -DCMAKE_INSTALL_PREFIX=$RELEASE_DIR -DCMAKE_BUILD_TYPE=$BUILD_TYPE
fi
#!/bin/sh
# startup for silecs yocto FECs
#! workaround until new image:
sed -i 's/graylog/logging/g' /etc/fesa/log.cfg
NFSHOST=fsl00c
FESA_BASE=/opt/fesa
FESA_MOUNT="$FESA_BASE/nfs"
# CH: TFTP is never set. need to parse /proc/cmdline
# CH: would add this as hardoced variable at the beginning of the script
FESA_SERVER=${TFTP:-fsl00c}
FESA_EXPORT=/export/fesa
FESA_DATAMOUNT="$FESA_BASE/data"
# determine name of fec (name or nomenclature)
# CH:comlete nomen logic
# CH: FEC_NAME=$(hostnomen || hostname -s)
FEC_NAME=$(hostname)
FEC_NOMEN=$(hostnomen 2> /dev/null)
if [ $? -eq 0 ]; then
# log "Found nomenclature '$FEC_NOMEN' for frontend '$FEC_NAME'."
echo "Found nomenclature '$FEC_NOMEN' for frontend '$FEC_NAME'."
FEC_NAME=$FEC_NOMEN
else
echo "No nomenclature found for frontend '$FEC_NAME'."
fi
echo "Getting DUs from '$FESA_MOUNT/local/$FEC_NAME'."
FESA_DATAEXPORT=/fesadata/data/$FEC_NAME
# temporary mount to copy param files
FESA_DU_MOUNT=/tmp/du
[ -d "$FESA_DU_MOUNT" ] || mkdir -p "$FESA_DU_MOUNT"
mount -t nfs4 -o rw $FESA_SERVER:$FESA_EXPORT/local/$FEC_NAME $FESA_DU_MOUNT
if [ $? -eq 0 ]; then
echo "mounted $FESA_SERVER:$FESA_EXPORT/local/$FEC_NAME $FESA_DU_MOUNT"
else
echo "failed to mount $FESA_SERVER:$FESA_EXPORT $FESA_MOUNT"
fi
# find folders with a matching DU, instance, libraries
for i in $FESA_DU_MOUNT/*; do
if [ ! -d $i ]; then
continue # skip non-dirs and nullglob
fi
FESA_DU=$(basename "$i")
FESA_DU_DIR=$FESA_DU_MOUNT/$FESA_DU
echo "found DU $FESA_DU"
PARAM_DEST="/etc/fesa/params"
[ -d "$PARAM_DEST" ] || mkdir -p "$PARAM_DEST"
if ls $FESA_DU_DIR/*.silecsparam &> /dev/null; then
cp $FESA_DU_DIR/*.silecsparam $PARAM_DEST
fi
done
umount $FESA_DU_MOUNT
rmdir $FESA_DU_MOUNT
#!/bin/sh
/opt/nfsinit/global/silecs_yocto
/opt/nfsinit/global/fesa_yocto --dev --nfs --per -u -silecsParamPath,/etc/fesa/params/
#!/bin/sh
/opt/nfsinit/global/silecs_yocto
/opt/nfsinit/global/fesa_yocto --int --nfs --per -u -silecsParamPath,/etc/fesa/params/
#!/bin/sh
/opt/nfsinit/global/silecs_yocto
/opt/nfsinit/global/fesa_yocto --pro --nfs --per -u -silecsParamPath,/etc/fesa/params/
#!/bin/bash
TARGET=x86_64
usage(){
echo "Usage: $0 [--target yocto]"
echo "-t | --target"
echo " $TARGET when not specified"
echo "-h | --help"
exit 1
}
USER_TARGET=$TARGET
# Loop through all the arguments and determine provided options.
while [ "${1:-}" != "" ]; do
case $1 in
-t | --target ) shift
USER_TARGET=$1
;;
-h | --help ) usage
exit
;;
* ) usage
exit 1
esac
shift
done
# Based on the build target select the build directory (build by default & build-yocto for yocto SDK).
# Using a different build directory for yocto builds since mixing between the two cmake versions doesn't work to well.
BUILD_DIR_NAME=build
if [[ $USER_TARGET == yocto ]]; then
TARGET=yocto
BUILD_DIR_NAME=build-yocto
elif [[ $USER_TARGET != x86_64 ]]; then
echo "Unsupported target" $USER_TARGET
usage
exit 1
fi
SCRIPT_PATH=$(dirname $(readlink -f "$0"))
BUILD_DIR=$SCRIPT_PATH/$BUILD_DIR_NAME
echo "------------------------------------------------------------------------"
echo "Build target: " $TARGET
echo "Build directory: " $BUILD_DIR
echo "------------------------------------------------------------------------"
cd $BUILD_DIR
# Run tests and exit if any of them fail.
ctest --output-on-failure || exit 1
cd $SCRIPT_PATH
cmake --install $BUILD_DIR -j 8
#!/bin/sh
set -e
echo "##############################################"
echo "configuration of build environment"
echo "##############################################"
# $WORKSPACE is the jenkins workspace, will be filled by jenkins
export COMMON_MAKE_PATH="$WORKSPACE/../../generics/generic-makefiles"
export SNAP7_BASE="$WORKSPACE/snap7/snap7-full"
export BOOST_HOME="$WORKSPACE/../../generics/boost_1.54.0/boost/1.54.0"
export SILECS_COMM_HOME="$WORKSPACE/silecs-communication-cpp/build"
echo "##############################################"
echo "building snap7"
echo "##############################################"
cd snap7
./build.sh
cd ..
echo "##############################################"
echo "building silecs-communication-cpp"
echo "##############################################"
cd silecs-communication-cpp
make clean
make all CPU=x86_64 -j4
cd ..
echo "##############################################"
echo "building silecs-codegen"
echo "##############################################"
cd silecs-codegen/src/xml
python runTests.py
cd ../../..
echo "##############################################"
echo "building silecs-diagnostic-cpp"
echo "##############################################"
cd silecs-diagnostic-cpp
make clean
make CPU=x86_64 -j1
cd ..
echo "##############################################"
echo "building silecs-cli-client"
echo "##############################################"
cd silecs-cli-client
make clean
make CPU=x86_64 -j1
cd ..
echo "##############################################"
echo "build finished sucessfully"
echo "##############################################"
import os
import argparse
from packaging import version
def get_major(v):
return v._version.release[0]
def get_minor(v):
return v._version.release[1]
def create_link(silecs_deploy_dir, version, link_name):
target = os.path.join(silecs_deploy_dir, version)
link = os.path.join(silecs_deploy_dir, link_name)
try:
os.symlink(target, link)
except FileExistsError as err:
os.unlink(link)
os.symlink(target, link)
print(f"symlink created {link} -> {target}")
def get_available_versions(silecs_deploy_dir):
"""Find available versions of silecs in SILECS_DIR"""
subfolders = [f.name for f in os.scandir(silecs_deploy_dir) if os.path.isdir(f) and not os.path.islink(f) ]
available_versions = []
for f in subfolders:
try:
v = version.Version(f)
available_versions.append(f)
except version.InvalidVersion:
pass
return sorted(available_versions, key= lambda x: version.Version(x), reverse=True)
def get_major_versions(versions):
"""Find all major versions eg ["3.0.1", "2.3.4", "1.4.1"] -> [3, 2, 1]"""
major_versions = []
for v in versions:
v = version.Version(v)
major = get_major(v)
if not major in major_versions:
major_versions.append(major)
return major_versions
def run(silecs_deploy_dir):
try:
versions = get_available_versions(silecs_deploy_dir)
major_versions = get_major_versions(versions)
assert len(versions)
except AssertionError:
print("No versions found")
return
latest_version = versions[0]
# set link for latest version
create_link(silecs_deploy_dir, latest_version, 'latest')
# For each major version create link to newest version
for mv in major_versions:
newest_version_with_major = str([version.Version(v) for v in versions if get_major(version.Version(v)) == mv][0])
create_link(silecs_deploy_dir, newest_version_with_major, str(mv))
print("Links successfully created")
return
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Process some integers.')
parser.add_argument('silecs_deploy_dir', metavar='silecs_deploy_dir', type=str, nargs=1,
help='path to silecs deploy directory')
try:
options = parser.parse_args()
except Exception:
sys.exit(0)
silecs_deploy_dir = options.silecs_deploy_dir[0]
run(silecs_deploy_dir)
cmake_minimum_required(VERSION 3.20.2)
project(silecs-cli-client LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_compile_options(-Wall -Wextra)
add_executable(${PROJECT_NAME} src/silecs-cli-client/main.cpp)
target_link_libraries(${PROJECT_NAME} silecs-comm)
install(
TARGETS ${PROJECT_NAME}
DESTINATION ${CMAKE_PROJECT_VERSION}/${PROJECT_NAME}/bin/${BUILD_TARGET}
)
install(
DIRECTORY examples
DESTINATION ${CMAKE_PROJECT_VERSION}/${PROJECT_NAME}
FILES_MATCHING PATTERN "*.sh*"
)
\ No newline at end of file
# Copyright 2016 CERN and GSI
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
PROJECT = silecs
PRODUCT = cli-client
VERSION = 0.0.0
SKIP_MANIFEST = TRUE
#local
#COMMON_MAKE_PATH ?= /common/home/bel/schwinn/lnx/workspace-silecs-neon/generic-makefiles
#global
COMMON_MAKE_PATH ?= /opt/cern/buildsystem/generic/2.13.2
#Enable C++11 Support
COMPILER_FLAGS += -std=c++11
# product configuration
BIN_NAME = $(PROJECT)-$(PRODUCT)
DBG = false
# Include the generic make file
include $(COMMON_MAKE_PATH)/Make.generic
\ No newline at end of file
BOOST_VERSION ?= 1.54.0
SILECS_COMM_VERSION = 1.0.2
BOOST_HOME ?= /acc/local/$(CPU)/3rdparty/boost/$(BOOST_VERSION)
SILECS_COMM_HOME ?= ../silecs-communication-cpp/build
LIBXML_PATH ?= /usr/include/libxml2/
SNAP7_BASE ?= ../snap7/snap7-full/build/bin/$(CPU)-linux
DEPENDENT_COMPILER_OPTIONS += -I$(SILECS_COMM_HOME)/include
DEPENDENT_COMPILER_OPTIONS += -I$(LIBXML_PATH)
DEPENDENT_COMPILER_OPTIONS += -I$(BOOST_HOME)/include
DEPENDENT_LINKER_OPTIONS += -L$(SNAP7_BASE) -lsnap7
DEPENDENT_LINKER_OPTIONS += -L/usr/lib64 -lxml2
DEPENDENT_LINKER_OPTIONS += -L$(SILECS_COMM_HOME)/lib/$(CPU) -lsilecs-comm
DEPENDENT_LINKER_OPTIONS += -lstdc++ -lxml2 -lboost_system -lboost_filesystem -lcurl
# Set default library search path
DEPENDENT_LINKER_OPTIONS += -Wl,-rpath=$(SNAP7_BASE)
#!/bin/sh
set -e
RELEASE_DIR_BASE=$1
SILECS_VERSION=$2
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
RELEASE_DIR=${RELEASE_DIR_BASE}/${SILECS_VERSION}/silecs-cli-client
if [ -d ${RELEASE_DIR} ]; then
echo "Error: ${RELEASE_DIR} already exists ...skipping"
exit 1
fi
SNAP7_BASE=${RELEASE_DIR_BASE}/snap7/1.4/x86_64-linux
make -C ${SCRIPTPATH} clean
make -C ${SCRIPTPATH} CPU=x86_64 MAJOR=${MAJOR} MINOR=${MINOR} PATCH=${PATCH} SNAP7_BASE=${SNAP7_BASE} -j4
mkdir -p ${RELEASE_DIR}
cp -r ${SCRIPTPATH}/build/bin ${RELEASE_DIR}
cp -r ${SCRIPTPATH}/examples ${RELEASE_DIR}
# Make all files write-protected to prevent overwriting an old version by accident
chmod a-w -R ${RELEASE_DIR}
\ No newline at end of file
......@@ -24,11 +24,9 @@
#include <silecs-communication/interface/utility/XMLParser.h>
#include <silecs-communication/interface/core/SilecsService.h>
#include <silecs-communication/interface/equipment/SilecsCluster.h>
#include <silecs-communication/interface/equipment/SilecsDevice.h>
#include <silecs-communication/interface/equipment/SilecsRegister.h>
#include <boost/assign/list_of.hpp> // init vector of strings
#include <silecs-communication/interface/equipment/SilecsPLC.h>
const std::string startbold = "\e[1m";
const std::string endbold = "\e[0m";
......@@ -154,12 +152,18 @@ std::string getPLCName(Silecs::XMLParser &paramParser)
return mappingNode.getAttribute("plc-name");
}
Silecs::Cluster* getSilecsClusterbyDevice(std::string deviceName, Silecs::XMLParser &paramParser, Silecs::Service *silecsService)
Silecs::PLC& getSilecsPLC(const std::string& plcName, Silecs::Service *silecsService)
{
return silecsService->getPLCHandler().getPLC(plcName);
}
Silecs::SilecsDesign& getSilecsDesignbyDevice(std::string deviceName, Silecs::XMLParser &paramParser, Silecs::Service *silecsService)
{
Silecs::ElementXML classNode = paramParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping/SILECS-Class[Instance/@label='" + deviceName + "']");
std::string className = classNode.getAttribute("name");
std::string classVersion = classNode.getAttribute("version");
return silecsService->getCluster(className, classVersion);
auto& plc = getSilecsPLC(getPLCName(paramParser), silecsService);
return plc.getDeploy().getDesign(className);
}
std::string getSilecsBlockNamebyRegisterName(std::string registerName, Silecs::XMLParser &paramParser)
......@@ -179,9 +183,8 @@ bool isRegisterInBlock(std::string registerName, std::string blockName, Silecs::
std::vector<std::string> getDeviceNames(Silecs::XMLParser &paramParser)
{
std::vector < std::string > deviceNames;
boost::ptr_vector<Silecs::ElementXML> deviceNodes = paramParser.getElementsFromXPath_throwIfEmpty("/SILECS-Param/SILECS-Mapping/SILECS-Class/Instance");
boost::ptr_vector<Silecs::ElementXML>::iterator deviceNode;
for (deviceNode = deviceNodes.begin(); deviceNode != deviceNodes.end(); deviceNode++)
auto deviceNodes = paramParser.getElementsFromXPath("/SILECS-Param/SILECS-Mapping/SILECS-Class/Instance");
for (auto deviceNode = deviceNodes.begin(); deviceNode != deviceNodes.end(); deviceNode++)
{
deviceNames.push_back(deviceNode->getAttribute("label"));
}
......@@ -193,9 +196,8 @@ std::vector<std::string> getBlockNamesFromDeviceName(std::string deviceName, Sil
std::vector < std::string > blockNames;
Silecs::ElementXML classNode = paramParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping/SILECS-Class[Instance/@label='" + deviceName + "']");
std::string className = classNode.getAttribute("name");
boost::ptr_vector<Silecs::ElementXML> blocks = paramParser.getElementsFromXPath_throwIfEmpty("/SILECS-Param/SILECS-Mapping/SILECS-Class[@name='" + className + "']/*[ name()='Acquisition-Block' or name()='Setting-Block' or name()='Command-Block']");
boost::ptr_vector<Silecs::ElementXML>::iterator block;
for (block = blocks.begin(); block != blocks.end(); block++)
auto blocks = paramParser.getElementsFromXPath("/SILECS-Param/SILECS-Mapping/SILECS-Class[@name='" + className + "']/*[ name()='Acquisition-Block' or name()='Setting-Block' or name()='Command-Block']");
for (auto block = blocks.begin(); block != blocks.end(); block++)
{
//std::cout<< block->getAttribute("name") << std::endl;
blockNames.push_back(block->getAttribute("name"));
......@@ -208,9 +210,8 @@ std::vector<std::string> getRegisterNamesFromDeviceBlockName(std::string deviceN
std::vector < std::string > registerNames;
Silecs::ElementXML classNode = paramParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping/SILECS-Class[Instance/@label='" + deviceName + "']");
std::string className = classNode.getAttribute("name");
boost::ptr_vector<Silecs::ElementXML> registerNodes = paramParser.getElementsFromXPath_throwIfEmpty("/SILECS-Param/SILECS-Mapping/SILECS-Class[@name='" + className + "']/*[@name='" + blockName + "']/*[ name()='Acquisition-Register' or name()='Setting-Register' or name()='Volatile-Register']");
boost::ptr_vector<Silecs::ElementXML>::iterator registerNode;
for (registerNode = registerNodes.begin(); registerNode != registerNodes.end(); registerNode++)
auto registerNodes = paramParser.getElementsFromXPath("/SILECS-Param/SILECS-Mapping/SILECS-Class[@name='" + className + "']/*[@name='" + blockName + "']/*[ name()='Acquisition-Register' or name()='Setting-Register' or name()='Volatile-Register']");
for (auto registerNode = registerNodes.begin(); registerNode != registerNodes.end(); registerNode++)
{
//std::cout<< block->getAttribute("name") << std::endl;
registerNames.push_back(registerNode->getAttribute("name"));
......@@ -236,10 +237,10 @@ void printTableHead()
std::cout << "------------------------------------------------------------------------------------------------------------------------------------------------" << std::endl;
}
void printRunState(Silecs::PLC *plc)
void printRunState(Silecs::PLC& plc)
{
std::cout << "------------------------------------------------------------------------------------------------------------------------------------------------" << std::endl;
if (plc->isRunning())
if (plc.isRunning())
std::cout << "plc run-state is: RUNNING" << std::endl;
else
std::cout << "plc run-state is: STOPPED" << std::endl;
......@@ -261,13 +262,12 @@ void printRegister(Silecs::Device *device, Silecs::Register *reg)
void printBlock(Silecs::Device *device, std::string blockName, Silecs::XMLParser &paramParser)
{
device->recv(blockName);
std::vector<Silecs::Register*> regCol = device->getRegisterCollection(blockName);
std::vector<Silecs::Register*>::iterator reg;
for (reg = regCol.begin(); reg != regCol.end(); reg++)
auto& regCol = device->getRegisterCollection(blockName);
for (auto reg = regCol.begin(); reg != regCol.end(); reg++)
{
if (isRegisterInBlock( (*reg)->getName(), blockName, paramParser))
{
printRegister(device, *reg);
printRegister(device, (*reg).get());
}
}
}
......@@ -279,11 +279,10 @@ void printDevice(Silecs::Device *device, Silecs::XMLParser &paramParser)
for (blockName = blockNames.begin(); blockName != blockNames.end(); blockName++)
{
device->recv(*blockName);
std::vector<Silecs::Register*> regCol = device->getRegisterCollection(*blockName);
std::vector<Silecs::Register*>::iterator reg;
for (reg = regCol.begin(); reg != regCol.end(); reg++)
auto& regCol = device->getRegisterCollection(*blockName);
for (auto reg = regCol.begin(); reg != regCol.end(); reg++)
{
printRegister(device, *reg);
printRegister(device, (*reg).get());
}
}
}
......@@ -296,11 +295,9 @@ void setRegister(Silecs::Register *reg, std::string value)
int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
{
std::vector < std::string > mainMenu = boost::assign::list_of("connect to plc-device")("select block")("select register")("print whole device")("print block")("print register")("query plc run state")("cold-restart plc");
Silecs::Cluster *silecsCluster = NULL;
Silecs::PLC *plc = NULL;
Silecs::Device *device = NULL;
Silecs::Register *reg = NULL;
std::vector <std::string> mainMenu = {"connect to plc-device", "select block",
"select register", "print whole device", "print block", "print register",
"query plc run state", "cold-restart plc"};
while (true)
{
......@@ -321,10 +318,8 @@ int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
arg_deviceName = devices[index];
arg_blockName = "";
arg_registerName = "";
silecsCluster = getSilecsClusterbyDevice(arg_deviceName, paramParser, service);
plc = silecsCluster->getPLC(getPLCName(paramParser), arg_parameterFile);
plc->connect(Silecs::MASTER_SYNCHRO, true, arg_checkChecksum);
device = plc->getDevice(arg_deviceName);
auto& plc = getSilecsPLC(getPLCName(paramParser), service);
plc.connect(true, arg_checkChecksum);
break;
}
case 1:
......@@ -356,10 +351,10 @@ int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
if (index == -1)
break;
arg_registerName = registers[index];
reg = device->getRegister(arg_registerName);
break;
}
case 3:
{
if (arg_deviceName.empty())
{
std::cout << "Please connect to a device first! - Press any key to continue." << std::endl;
......@@ -367,9 +362,13 @@ int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
break;
}
printTableHead();
auto& design = getSilecsDesignbyDevice(arg_deviceName, paramParser, service);
auto device = design.getDevice(arg_deviceName);
printDevice(device, paramParser);
break;
}
case 4:
{
if (arg_deviceName.empty() || arg_blockName.empty())
{
std::cout << "Please first connect to a device and select a block! - Press any key to continue." << std::endl;
......@@ -377,9 +376,13 @@ int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
break;
}
printTableHead();
auto& design = getSilecsDesignbyDevice(arg_deviceName, paramParser, service);
auto device = design.getDevice(arg_deviceName);
printBlock(device, arg_blockName, paramParser);
break;
}
case 5:
{
if (arg_deviceName.empty() || arg_blockName.empty() || arg_registerName.empty())
{
std::cout << "Please first connect to device and pick a block and a register! - Press any key to continue." << std::endl;
......@@ -387,26 +390,36 @@ int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
break;
}
printTableHead();
printRegister(device, reg);
auto& design = getSilecsDesignbyDevice(arg_deviceName, paramParser, service);
auto device = design.getDevice(arg_deviceName);
auto& reg = device->getRegister(arg_registerName);
printRegister(device, reg.get());
break;
}
case 6:
{
if (arg_deviceName.empty())
{
std::cout << "Please connect to a device first! - Press any key to continue." << std::endl;
getch();
break;
}
auto& plc = getSilecsPLC(getPLCName(paramParser), service);
printRunState(plc);
break;
}
case 7:
{
if (arg_deviceName.empty())
{
std::cout << "Please connect to a device first! - Press any key to continue." << std::endl;
getch();
break;
}
plc->sendColdRestart();
auto& plc = getSilecsPLC(getPLCName(paramParser), service);
plc.sendColdRestart();
break;
}
default:
std::cout << "Invalid option:" << item << std::endl;
return EXIT_FAILURE;
......@@ -418,10 +431,9 @@ int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
int connectNonInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser, bool periodicOptionSet)
{
Silecs::Cluster *silecsCluster = getSilecsClusterbyDevice(arg_deviceName, paramParser, service);
Silecs::PLC *plc = silecsCluster->getPLC(getPLCName(paramParser), arg_parameterFile);
plc->connect(Silecs::MASTER_SYNCHRO, true, arg_checkChecksum);
if (!plc->isConnected())
auto& plc = getSilecsPLC(getPLCName(paramParser), service);
plc.connect(true, arg_checkChecksum);
if (!plc.isConnected())
{
std::cout << "Error: Failed to connect to PLC." << std::endl;
return EXIT_FAILURE;
......@@ -431,12 +443,13 @@ int connectNonInteractive(Silecs::Service *service, Silecs::XMLParser &paramPars
{
printRunState(plc);
}
Silecs::Device *device = plc->getDevice(arg_deviceName);
auto& design = getSilecsDesignbyDevice(arg_deviceName, paramParser, service);
auto device = design.getDevice(arg_deviceName);
Silecs::Register *reg = NULL;
if (!arg_registerName.empty())
{
reg = device->getRegister(arg_registerName);
reg = device->getRegister(arg_registerName).get();
arg_blockName = getSilecsBlockNamebyRegisterName(arg_registerName, paramParser);
}
......
cmake_minimum_required(VERSION 3.20.2)
project(silecs-codegen)
find_package(Python COMPONENTS Interpreter)
add_test (NAME codegen-tests
COMMAND ${Python_EXECUTABLE} -m unittest
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/src/xml/
)
install (
DIRECTORY ${PROJECT_SOURCE_DIR}/src/xml
DESTINATION ${CMAKE_PROJECT_VERSION}/${PROJECT_NAME}
FILES_MATCHING PATTERN "*.py*")