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 (69)
Showing
with 532 additions and 396 deletions
......@@ -9,3 +9,6 @@ venv
builds
builds/*
.data
build
build-yocto
test/build-test
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
# List of silecs packages which can be released
PACKAGES="silecs-codegen silecs-model 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_FULL=$1
SILECS_VERSION_MAJOR=`echo ${SILECS_VERSION_FULL} | cut -d. -f1`
SILECS_VERSION_MINOR=`echo ${SILECS_VERSION_FULL} | cut -d. -f2`
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_FULL}
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_FULL}/silecs_environment
echo $SILECS_ENV_FILE
touch $SILECS_ENV_FILE
echo -e "SILECS_VERSION=${SILECS_VERSION_FULL}" >> $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"
# Update link to latest version
LATEST_LINK=${RELEASE_DIR_BASE}/latest
if [ -L ${LATEST_LINK} ]; then
rm ${LATEST_LINK}
fi
ln -fvs ${RELEASE_DIR_BASE}/${SILECS_VERSION_FULL} ${LATEST_LINK}
# Update link to major.minor version
MAJOR_MINOR_LINK=${RELEASE_DIR_BASE}/${SILECS_VERSION_MAJOR}.${SILECS_VERSION_MINOR}
if [ -L ${MAJOR_MINOR_LINK} ]; then
rm ${MAJOR_MINOR_LINK}
fi
ln -fvs ${RELEASE_DIR_BASE}/${SILECS_VERSION_FULL} ${MAJOR_MINOR_LINK}
# Update link to major version
MAJOR_LINK=${RELEASE_DIR_BASE}/${SILECS_VERSION_MAJOR}
if [ -L ${MAJOR_LINK} ]; then
rm ${MAJOR_LINK}
fi
ln -fvs ${RELEASE_DIR_BASE}/${SILECS_VERSION_FULL} ${MAJOR_LINK}
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 "##############################################"
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/
GSI_SILECS_BASE = /common/usr/cscofe/silecs
SNAP7_BASE ?= $(GSI_SILECS_BASE)/snap7/latest
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)/lib/$(CPU)-linux -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)/lib/$(CPU)-linux
#!/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
make -C ${SCRIPTPATH} clean
make -C ${SCRIPTPATH} CPU=x86_64 MAJOR=${MAJOR} MINOR=${MINOR} PATCH=${PATCH} -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*")
#!/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-codegen
if [ -d ${RELEASE_DIR} ]; then
echo "Error: ${RELEASE_DIR} already exists ...skipping"
exit 1
fi
cd ${SCRIPTPATH}/src/xml
python3 -m unittest
mkdir -p ${RELEASE_DIR}
cp -r ${SCRIPTPATH}/src/xml ${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
......@@ -9,6 +9,7 @@
# be specialized on call to append the string to be stored in the file.
#
import string
import time
......@@ -54,17 +55,17 @@ def toWordArray(strg):
#=========================================================================
# C Source template (.c file)
#=========================================================================
header = """
header = string.Template("""
/* +-------------------------------------------------------------------
* | Copyright CERN 2015
* | SILECS - BE/CO-SRC
* | April 2015
* +-------------------------------------------------------------------
*
* Release : %s
* Release : ${silecsRelease}
*
* The following code has been automatically generated by SILECS.
* Code regeneration will overwrite it.
*
* N.B: This file relies on the existence of explicit C data type such
* as int8_t, uint8_t, int16_t, etc....
......@@ -73,7 +74,7 @@ header = """
* web page before including this header file.
*/
#define MODBUS_START_ADDRESS %s
#define MODBUS_START_ADDRESS ${baseAddress}
/*---------------------------------------------------------------------
* DT
......@@ -94,7 +95,7 @@ typedef struct
} dt;
#define _frombcd(a) (int)(((a>>4)*10)+(a&0x0F))
#define _tobcd(a) (((unsigned char)((a)/10)<<4)+((a)%%10))
#define _tobcd(a) (((unsigned char)((a)/10)<<4)+((a)%10))
void SILECS_set_dt(int8_t sc_100 ,int8_t sc, int8_t mn,int8_t hh,int8_t dd,int8_t mm,int32_t yy, dt *date)
{
......@@ -105,80 +106,72 @@ void SILECS_set_dt(int8_t sc_100 ,int8_t sc, int8_t mn,int8_t hh,int8_t dd,int8_
date->dd = _tobcd(dd);
date->mm = _tobcd(mm);
date->yy2 = _tobcd((int8_t)(yy/100));
date->yy1 = _tobcd((int8_t)(yy%%100));
date->yy1 = _tobcd((int8_t)(yy%100));
}
"""
""")
#=========================================================================
# DATA TYPE DEFINITION
#=========================================================================
firstBlockUDT = """
firstBlockUDT = string.Template("""
/*---------------------------------------------------------------------
* %s / v%s
* ${className} / v${classVersion}
* BLOCK Type definition
*---------------------------------------------------------------------
*/
"""
""")
blockUDT = """
blockUDT = string.Template("""
typedef struct
{
%s
} _%s_%s;
"""
$regList
} _${className}_${blockName};
""")
regScalar = """ %s %s;
"""
regScalar = string.Template(""" ${regFormat} ${regName};
""")
regArray = """ %s %s[%s];
"""
regArray = string.Template(""" ${regFormat} ${regName}[${strLen}];
""")
regArray2d = """ %s %s[%s][%s];
"""
regArray2d = string.Template(""" ${regFormat} ${regName}[${regDim}][${strLen}];
""")
stringArray = """ %s %s[%s][%s][%s];
"""
stringArray = string.Template(""" ${regFormat} ${regName}[${regDim}][${regDim2}][${strLen}];
""")
#=========================================================================
# INSTANTIATION
#=========================================================================
allocationComment = """
allocationComment = string.Template("""
/*---------------------------------------------------------------------
* MEMORY ALLOCATION
* PROTOCOL: %s
* PROTOCOL: ${plcProtocol}
*---------------------------------------------------------------------
*/
"""
""")
#======= DEVICE MODE =================
deviceModeBlockInstantiation = string.Template(""" _${className}_${blockName} ${blockName};
""")
deviceModeBlockInstantiation = """ _%s_%s %s;
"""
#deviceModeClass_deviceNumber = """
# struct {
# _%s_%s %s;
# } %s_device[%s];
#"""
deviceModeClass_deviceNumber = """
deviceModeClass_deviceNumber = string.Template("""
struct {
%s
} %s_device[NB_%s_DEVICE];
"""
deviceModeClass_deviceList = """
${blockList}
} ${className}_device[NB_${className}_DEVICE];
""")
deviceModeClass_deviceList = string.Template("""
struct {
%s
} %s;
"""
${blockList}
} ${deviceList};
""")
deviceMode_dataInstantiation = """
deviceMode_dataInstantiation = string.Template("""
typedef struct {
%s
${classList}
} _SILECS_DATA_SEGMENT;
#define SILECS_DATA_SEGMENT_MODBUS_SIZE (sizeof(_SILECS_DATA_SEGMENT)/2)
......@@ -188,21 +181,20 @@ union silecsData {
uint16_t array[SILECS_DATA_SEGMENT_MODBUS_SIZE];
} silecsData;
"""
""")
#======= BLOCK MODE =================
blockModeDeviceInstantiation_deviceList = string.Template(""" _${className}_${blockName} ${deviceName};
""")
blockModeDeviceInstantiation_deviceList = """ _%s_%s %s;
"""
blockModeBlockInstantiation = """
blockModeBlockInstantiation = string.Template("""
struct {
%s } %s_%s;
"""
${deviceList} } ${className}_${blockName};
""")
blockMode_dataInstantiation = """
blockMode_dataInstantiation = string.Template("""
typedef struct {
%s
${classList}
} _SILECS_DATA_SEGMENT;
#define SILECS_DATA_SEGMENT_MODBUS_SIZE (sizeof(_SILECS_DATA_SEGMENT)/2)
......@@ -212,7 +204,7 @@ union modbus_data {
uint16_t array[SILECS_DATA_SEGMENT_MODBUS_SIZE];
} silecsData;
"""
""")
#=========================================================================
# init
......@@ -223,44 +215,43 @@ globalAllocation = """
uint16_t modbus_data = & data;
"""
initFunctionDeviceMode = """
initFunctionDeviceMode = string.Template("""
/* Initialization function */
int SILECS_init()
{
/* Silecs version initialization */
strcpy((unsigned char *)silecsData.data.SilecsHeader_device[0].hdrBlk._version, "%s");
strcpy((unsigned char *)silecsData.data.SilecsHeader_device[0].hdrBlk._version, "${version}");
/* Silecs checksum initialization */
silecsData.data.SilecsHeader_device[0].hdrBlk._checksum = %s;
silecsData.data.SilecsHeader_device[0].hdrBlk._checksum = ${checksum};
/* Silecs user initialization */
strcpy((unsigned char *)silecsData.data.SilecsHeader_device[0].hdrBlk._user, "%s");
strcpy((unsigned char *)silecsData.data.SilecsHeader_device[0].hdrBlk._user, "${user}");
/* Silecs date initialization */
SILECS_set_dt(%s,%s,%s,%s,%s,%s,%s,&silecsData.data.SilecsHeader_device[0].hdrBlk._date);
SILECS_set_dt(${dt6},${dt5},${dt4},${dt3},${dt2},${dt1},${dt0},&silecsData.data.SilecsHeader_device[0].hdrBlk._date);
}
"""
""")
#initFunctionBlockMode = """
initFunctionBlockMode = """
initFunctionBlockMode = string.Template("""
/* Initialization function */
int SILECS_init()
{
/* Silecs version initialization */
strcpy((unsigned char *)silecsData.data.SilecsHeader_hdrBlk.device[0]._version, "%s");
strcpy((unsigned char *)silecsData.data.SilecsHeader_hdrBlk.device[0]._version, "${version}");
/* Silecs checksum initialization */
silecsData.data.SilecsHeader_hdrBlk.device[0]._checksum = %s;
silecsData.data.SilecsHeader_hdrBlk.device[0]._checksum = ${checksum};
/* Silecs user initialization */
strcpy((unsigned char *)silecsData.data.SilecsHeader_hdrBlk.device[0]._user, "%s");
strcpy((unsigned char *)silecsData.data.SilecsHeader_hdrBlk.device[0]._user, "${user}");
/* Silecs date initialization */
SILECS_set_dt(%s,%s,%s,%s,%s,%s,%s,&silecsData.data.SilecsHeader_hdrBlk.device[0]._date);
SILECS_set_dt(${dt6},${dt5},${dt4},${dt3},${dt2},${dt1},${dt0},&silecsData.data.SilecsHeader_hdrBlk.device[0]._date);
}
"""
""")
#=========================================================================
# Example generation
......@@ -270,19 +261,19 @@ instantiationExample = """/*
* Automatically generated Addressing example
*"""
deviceModeDeviceListExample = """
* This example shows how to address the register %s of block %s
* of device %s of the class %s
deviceModeDeviceListExample = string.Template("""
* This example shows how to address the register ${registerName} of block ${blockName}
* of device ${deviceLabel} of the class ${className}
*
* silecsData.%s_%s.%s.%s = ....;
*/"""
* silecsData.${className}_${deviceLabel}.${blockName}.${registerName} = ....;
*/""")
blockModeDeviceListExample = """
* This example shows how to address the register %s of block %s
* of device %s of the class %s
blockModeDeviceListExample = string.Template("""
* This example shows how to address the register ${registerName} of block ${blockName}
* of device ${deviceLabel} of the class ${className}
*
* silecsData.%s_%s.%s.%s = ....;
*/"""
* silecsData.${className}_${blockName}.${deviceLabel}.${registerName} = ....;
*/""")
#=========================================================================
# C code generation Sub-function
......@@ -290,33 +281,33 @@ blockModeDeviceListExample = """
# HEADER file ------------------------------------------------------------
def cHeader(silecsRelease, baseAddress):
return header %(silecsRelease, baseAddress)
return header.substitute(silecsRelease=silecsRelease, baseAddress=baseAddress)
# REGISTER definition ----------------------------------------------------
def cRegister(regName, regFormat, regDim, regDim2=1, strLen=1):
if strLen > 1: # if it's a string
if regDim2 > 1: # add another pair of brackets to hold the string length in case second dimension of array is set
return stringArray %(whichDIGIFormat[regFormat], regName, regDim, regDim2, strLen)
return stringArray.substitute(regFormat=whichDIGIFormat[regFormat], regName=regName, regDim=regDim, regDim2=regDim2, strLen=strLen)
elif regDim > 1: # reuse the array2D syntax
return regArray2d %(whichDIGIFormat[regFormat], regName, regDim, strLen)
return regArray2d.substitute(regFormat=whichDIGIFormat[regFormat], regName=regName, regDim=regDim, strLen=strLen)
else: # regular string register
return regArray %(whichDIGIFormat[regFormat], regName, strLen)
return regArray.substitute(regFormat=whichDIGIFormat[regFormat], regName=regName, strLen=strLen)
else:
if regDim == 1 and regDim2 == 1: # scalar
return regScalar %(whichDIGIFormat[regFormat], regName)
return regScalar.substitute(regFormat=whichDIGIFormat[regFormat], regName=regName)
elif regDim > 1 and regDim2 == 1: # array
return regArray %(whichDIGIFormat[regFormat], regName, regDim)
return regArray.substitute(regFormat=whichDIGIFormat[regFormat], regName=regName, strLen=regDim)
else: # dim1>=1 and for whatever dim2, use double array syntax
return regArray2d %(whichDIGIFormat[regFormat], regName, regDim, regDim2)
return regArray2d.substitute(regFormat=whichDIGIFormat[regFormat], regName=regName, regDim=regDim, strLen=regDim2)
def cFirstBlockUDT(className, classVersion):
return firstBlockUDT %(className, classVersion)
return firstBlockUDT.substitute(className=className, classVersion=classVersion)
# BLOCK type definition (UDT) --------------------------------------------
def cBlockUDT(className, blockName, regList):
return blockUDT %(regList, className, blockName)
return blockUDT.substitute(regList=regList, className=className, blockName=blockName)
#============= DEVICE instantiation =============
......@@ -324,46 +315,46 @@ def cBlockUDT(className, blockName, regList):
# GLOBAL instantiation ----------------------------------------------
def cAllocationComment(plcProtocol):
return allocationComment %(plcProtocol)
return allocationComment.substitute(plcProtocol=plcProtocol)
# DEVICE MODE instantiation ----------------------------------------------
def cDeviceModeBlockInstantiation(className, blockName):
return deviceModeBlockInstantiation %(className, blockName, blockName)
return deviceModeBlockInstantiation.substitute(className=className, blockName=blockName)
def cDeviceModeClass_deviceNumber(className, blockList):
return deviceModeClass_deviceNumber %(blockList, className, className)
return deviceModeClass_deviceNumber.substitute(blockList=blockList, className=className)
def cDeviceModeClass_deviceList(blockList, deviceList):
return deviceModeClass_deviceList %(blockList, deviceList)
return deviceModeClass_deviceList.substitute(blockList=blockList, deviceList=deviceList)
def cDeviceModeDataInstantiation(classList):
return deviceMode_dataInstantiation %(classList)
return deviceMode_dataInstantiation.substitute(classList=classList)
# BLOCK MODE instantiation ----------------------------------------------
def cBlockModeDeviceInstantiation_deviceList(className, blockName, deviceName):
return blockModeDeviceInstantiation_deviceList %(className, blockName, deviceName)
return blockModeDeviceInstantiation_deviceList.substitute(className=className, blockName=blockName, deviceName=deviceName)
def cBlockModeBlockInstantiation(deviceList, className, blockName):
return blockModeBlockInstantiation %(deviceList, className, blockName)
return blockModeBlockInstantiation.substitute(deviceList=deviceList, className=className, blockName=blockName)
def cBlockModeDataInstantiation(classList):
return blockMode_dataInstantiation %(classList)
return blockMode_dataInstantiation.substitute(classList=classList)
# Init Function ----------------------------------------------
def cInitDeviceMode(ieVersion,ieChecks,ieUser):
dt = time.localtime(time.time())
return initFunctionDeviceMode %("SILECS_"+ieVersion,ieChecks,ieUser,dt[6],dt[5],dt[4],dt[3],dt[2],dt[1],dt[0])
return initFunctionDeviceMode.substitute(version="SILECS_"+ieVersion, checksum=ieChecks, user=ieUser, dt6=dt[6], dt5=dt[5], dt4=dt[4], dt3=dt[3], dt2=dt[2], dt1=dt[1], dt0=dt[0])
def cInitBlockMode(ieVersion,ieChecks,ieUser):
dt = time.localtime(time.time())
return initFunctionBlockMode %("SILECS_"+ieVersion,ieChecks,ieUser,dt[6],dt[5],dt[4],dt[3],dt[2],dt[1],dt[0])
return initFunctionBlockMode.substitute(version="SILECS_"+ieVersion, checksum=ieChecks, user=ieUser, dt6=dt[6], dt5=dt[5], dt4=dt[4], dt3=dt[3], dt2=dt[2], dt1=dt[1], dt0=dt[0])
# Example function ----------------------------------------------
def cExample(plcProtocol,className, blockName, registerName, deviceLabel =''):
if plcProtocol == 'DEVICE_MODE':
return instantiationExample + deviceModeDeviceListExample %(registerName, blockName, deviceLabel, className, className, deviceLabel, blockName, registerName)
return instantiationExample + deviceModeDeviceListExample.substitute(registerName=registerName, blockName=blockName, deviceLabel=deviceLabel, className=className)
else:
return instantiationExample + blockModeDeviceListExample %(registerName, blockName, deviceLabel, className, className, blockName, deviceLabel, registerName)
return instantiationExample + blockModeDeviceListExample.substitute(registerName=registerName, blockName=blockName, deviceLabel=deviceLabel, className=className)