Skip to content
Snippets Groups Projects
Commit 846a3fa6 authored by al.schwinn's avatar al.schwinn
Browse files

Bug 1387 - Provide Command-Line Silecs Client

- added interactive-mode
parent 8da90d7e
No related branches found
No related tags found
No related merge requests found
#!/bin/sh #!/bin/sh
set -e set -e
\ No newline at end of file
CPU="x86_64"
SCRIPT=$(readlink -f "$0")
SCRIPTPATH=$(dirname "$SCRIPT") # path where this script is located in
SNAP7_PATH=${SCRIPTPATH}/../../../git/snap7/snap7-full/build/bin/${CPU}-linux
BINARY="${SCRIPTPATH}/../build/bin/${CPU}/silecs-cli-client"
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$SNAP7_PATH
echo "##### LD_LIBRARY_PATH: ###################################################################################"
echo "$LD_LIBRARY_PATH"
echo "##########################################################################################################"
echo ""
PARAM_FILE=/common/home/bel/schwinn/lnx/workspace-silecs-neon/SiemensTestDU/generated/client/tsts7001.silecsparam
# config for SiemensTestDU
ARGUMENTS="-f $PARAM_FILE -i -c"
COMMAND="$BINARY $ARGUMENTS"
$COMMAND
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <getopt.h> #include <getopt.h>
#include <termios.h>// getch
#include <iostream> #include <iostream>
#include <iomanip> // std::right, etc #include <iomanip> // std::right, etc
#include <unistd.h>//usleep #include <unistd.h>//usleep
...@@ -27,6 +28,8 @@ ...@@ -27,6 +28,8 @@
#include <silecs-communication/interface/equipment/SilecsDevice.h> #include <silecs-communication/interface/equipment/SilecsDevice.h>
#include <silecs-communication/interface/equipment/SilecsRegister.h> #include <silecs-communication/interface/equipment/SilecsRegister.h>
#include <boost/assign/list_of.hpp> // init vector of strings
const std::string startbold = "\e[1m"; const std::string startbold = "\e[1m";
const std::string endbold = "\e[0m"; const std::string endbold = "\e[0m";
...@@ -87,6 +90,53 @@ void printHelp() ...@@ -87,6 +90,53 @@ void printHelp()
std::cout << std::endl; std::cout << std::endl;
} }
/* reads from keypress, doesn't echo */
int getch(void)
{
struct termios oldattr, newattr;
int ch;
tcgetattr( STDIN_FILENO, &oldattr );
newattr = oldattr;
newattr.c_lflag &= ~( ICANON | ECHO );
tcsetattr( STDIN_FILENO, TCSANOW, &newattr );
ch = getchar();
tcsetattr( STDIN_FILENO, TCSANOW, &oldattr );
return ch;
}
//returns -1 for "return to previous menu" or array-index of list
int querryUserPickFromList(std::vector<std::string> &list)
{
int selection = -1;
std::vector<std::string>::iterator item;
while(selection < 0 || (unsigned int)selection > list.size())
{
int itemIndex = 1;
std::cout << std::endl;
std::cout << "The following options are available:" << std::endl;
std::cout << std::endl;
for( item = list.begin();item!= list.end(); item++)
{
std::cout << std::setw(5) << std::right << itemIndex << ": " << std::setw(30) << std::left << *item << std::endl;
itemIndex++;
}
std::cout << std::endl;
std::cout << std::setw(5) << std::right << "0" << ": " << std::setw(30) << std::left << "return to previous menu" << std::endl;
std::cout << std::endl;
std::cout << "Waiting for your selection ";
int input = getch();
std::cout << std::endl;
selection = input - 48; //ascii magic
if( selection < 0 || (unsigned int)selection > list.size() )
{
std::cout << "Invalid input: '" << input << "'. press any key to take another try!" << std::endl;
getch();
}
}
return selection-1; // -1 = return ... everything else is array-index
}
std::string getPLCName(Silecs::XMLParser &paramParser) std::string getPLCName(Silecs::XMLParser &paramParser)
{ {
Silecs::ElementXML mappingNode = paramParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping"); Silecs::ElementXML mappingNode = paramParser.getFirstElementFromXPath("/SILECS-Param/SILECS-Mapping");
...@@ -115,6 +165,18 @@ bool isRegisterInBlock(std::string registerName, std::string blockName, Silecs: ...@@ -115,6 +165,18 @@ bool isRegisterInBlock(std::string registerName, std::string blockName, Silecs:
return false; return false;
} }
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++)
{
deviceNames.push_back(deviceNode->getAttribute("label"));
}
return deviceNames;
}
std::vector<std::string> getBlockNamesFromDeviceName(std::string deviceName, Silecs::XMLParser &paramParser) std::vector<std::string> getBlockNamesFromDeviceName(std::string deviceName, Silecs::XMLParser &paramParser)
{ {
std::vector< std::string > blockNames; std::vector< std::string > blockNames;
...@@ -130,6 +192,21 @@ std::vector<std::string> getBlockNamesFromDeviceName(std::string deviceName, Si ...@@ -130,6 +192,21 @@ std::vector<std::string> getBlockNamesFromDeviceName(std::string deviceName, Si
return blockNames; return blockNames;
} }
std::vector<std::string> getRegisterNamesFromDeviceBlockName(std::string deviceName, std::string blockName, Silecs::XMLParser &paramParser)
{
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 + "']/Block[@name='"+ blockName + "']/Register");
boost::ptr_vector<Silecs::ElementXML>::iterator registerNode;
for( registerNode = registerNodes.begin();registerNode!= registerNodes.end(); registerNode++)
{
//std::cout<< block->getAttribute("name") << std::endl;
registerNames.push_back(registerNode->getAttribute("name"));
}
return registerNames;
}
std::string getRegisterValueAsString(Silecs::Register* reg ) std::string getRegisterValueAsString(Silecs::Register* reg )
{ {
std::ostringstream os; std::ostringstream os;
...@@ -208,12 +285,123 @@ void setRegister(Silecs::Register* reg,std::string value) ...@@ -208,12 +285,123 @@ void setRegister(Silecs::Register* reg,std::string value)
int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser) int connectInteractive(Silecs::Service *service, Silecs::XMLParser &paramParser)
{ {
//ask class 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");
//ask device or print all devices Silecs::Cluster *silecsCluster = NULL;
//ask select block or print device Silecs::PLC *plc = NULL;
//ask select register or print block Silecs::Device *device = NULL;
//ask get/set register Silecs::Register* reg = NULL;
//Silecs::Cluster *cluster = NULL;
while(true)
{
std::cout << std::setw(20) << std::right << "Device:" << std::setw(20) << std::left << startbold << arg_deviceName << endbold <<std::endl;
std::cout << std::setw(20) << std::right << "Block:" << std::setw(20) << std::left << startbold << arg_blockName << endbold <<std::endl;
std::cout << std::setw(20) << std::right << "Register:" << std::setw(20) << std::left << startbold << arg_registerName << endbold <<std::endl;
int item = querryUserPickFromList(mainMenu);
switch(item)
{
case -1:
return EXIT_SUCCESS;
case 0:
{
std::vector<std::string> devices = getDeviceNames(paramParser);
int index = querryUserPickFromList(devices);
if( index == -1 )
break;
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);
break;
}
case 1:
{
if(arg_deviceName.empty())
{
std::cout << "Please select a device first! - Press any key to continue." << std::endl;
getch();
break;
}
std::vector<std::string> blocks = getBlockNamesFromDeviceName(arg_deviceName,paramParser);
int index = querryUserPickFromList(blocks);
if( index == -1 )
break;
arg_blockName = blocks[index];
arg_registerName = "";
break;
}
case 2:
{
if(arg_deviceName.empty() || arg_blockName.empty() )
{
std::cout << "Please connect to a device first! - Press any key to continue." << std::endl;
getch();
break;
}
std::vector<std::string> registers = getRegisterNamesFromDeviceBlockName(arg_deviceName,arg_blockName,paramParser);
int index = querryUserPickFromList(registers);
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;
getch();
break;
}
printTableHead();
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;
getch();
break;
}
printTableHead();
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;
getch();
break;
}
printTableHead();
printRegister(device,reg );
break;
case 6:
if(arg_deviceName.empty())
{
std::cout << "Please connect to a device first! - Press any key to continue." << std::endl;
getch();
break;
}
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();
break;
default:
std::cout << "Invalid option:" << item << std::endl;
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }
...@@ -227,7 +415,11 @@ int connectNonInteractive(Silecs::Service *service, Silecs::XMLParser &paramPars ...@@ -227,7 +415,11 @@ int connectNonInteractive(Silecs::Service *service, Silecs::XMLParser &paramPars
std::cout << "Error: Failed to connect to PLC."<< std::endl; std::cout << "Error: Failed to connect to PLC."<< std::endl;
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printRunState(plc);
if( !arg_silent )
{
printRunState(plc);
}
Silecs::Device *device = plc->getDevice(arg_deviceName); Silecs::Device *device = plc->getDevice(arg_deviceName);
Silecs::Register* reg = NULL; Silecs::Register* reg = NULL;
...@@ -350,8 +542,6 @@ int main(int argc, char **argv) ...@@ -350,8 +542,6 @@ int main(int argc, char **argv)
return EXIT_FAILURE; return EXIT_FAILURE;
} }
interactiveOptionSet = true; interactiveOptionSet = true;
std::cout << "TODO: implement interactive-mode" << std::endl;
return EXIT_FAILURE;
break; break;
case 's': case 's':
arg_silent = true; arg_silent = true;
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment