From c3f595442ba92b5070db3ab899b6b3b2b3c86702 Mon Sep 17 00:00:00 2001 From: Florian Pose <fp@igh-essen.com> Date: Thu, 11 Mar 2010 14:29:43 +0100 Subject: [PATCH] Implemented SoE IDN parser for strings like 'P-0-0150'; moved data type information string to DataTypeHandler. --- TODO | 2 - tool/CommandDownload.cpp | 4 +- tool/CommandRegRead.cpp | 4 +- tool/CommandRegWrite.cpp | 4 +- tool/CommandSoeRead.cpp | 27 ++++++---- tool/CommandSoeRead.h | 6 +-- tool/CommandSoeWrite.cpp | 24 +++++---- tool/CommandSoeWrite.h | 6 +-- tool/CommandUpload.cpp | 4 +- tool/DataTypeHandler.cpp | 14 +++++ tool/DataTypeHandler.h | 2 + tool/Makefile.am | 2 + tool/SoeCommand.cpp | 108 +++++++++++++++++++++++++++++++++++++++ tool/SoeCommand.h | 51 ++++++++++++++++++ 14 files changed, 215 insertions(+), 43 deletions(-) create mode 100644 tool/SoeCommand.cpp create mode 100644 tool/SoeCommand.h diff --git a/TODO b/TODO index e7b21e0d..8c61b06d 100644 --- a/TODO +++ b/TODO @@ -40,8 +40,6 @@ Version 1.5.0: - Implement indent in 'ethercat ma' - Implement 0xXXXX:YY format for specifying SDOs. - Lookup codes for 64bit data types. - - Move data type usage string into DataTypeHandler. - - Implement interpretation of SoE '[SP]-x-yyy' strings. - Implement reading from stream for soe_write. Future issues: diff --git a/tool/CommandDownload.cpp b/tool/CommandDownload.cpp index 47ec9c15..ee008f13 100644 --- a/tool/CommandDownload.cpp +++ b/tool/CommandDownload.cpp @@ -59,9 +59,7 @@ string CommandDownload::helpString() const << "information service or the SDO is not in the dictionary," << endl << "the --type option is mandatory." << endl << endl - << "These are the valid SDO entry data types:" << endl - << " int8, int16, int32, uint8, uint16, uint32, string," << endl - << " octet_string." << endl + << typeInfo() << endl << "Arguments:" << endl << " INDEX is the SDO index and must be an unsigned" << endl diff --git a/tool/CommandRegRead.cpp b/tool/CommandRegRead.cpp index 5689d523..8847ba7b 100644 --- a/tool/CommandRegRead.cpp +++ b/tool/CommandRegRead.cpp @@ -62,9 +62,7 @@ string CommandRegRead::helpString() const << " can be omitted), if a selected data type" << endl << " implies a length." << endl << endl - << "These are the valid data types:" << endl - << " int8, int16, int32, int64, uint8, uint16, uint32," << endl - << " uint64, string, raw." << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl diff --git a/tool/CommandRegWrite.cpp b/tool/CommandRegWrite.cpp index 9927f3d4..0c6ed512 100644 --- a/tool/CommandRegWrite.cpp +++ b/tool/CommandRegWrite.cpp @@ -64,9 +64,7 @@ string CommandRegWrite::helpString() const << " stdin. If a datatype was specified, VALUE is" << endl << " interpreted respective to the given type." << endl << endl - << "These are the valid data types:" << endl - << " int8, int16, int32, int64, uint8, uint16, uint32," << endl - << " uint64, string." << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl diff --git a/tool/CommandSoeRead.cpp b/tool/CommandSoeRead.cpp index 7623d8a8..6edb894d 100644 --- a/tool/CommandSoeRead.cpp +++ b/tool/CommandSoeRead.cpp @@ -37,7 +37,7 @@ using namespace std; /*****************************************************************************/ CommandSoeRead::CommandSoeRead(): - Command("soe_read", "Read an SoE IDN from a slave.") + SoeCommand("soe_read", "Read an SoE IDN from a slave.") { } @@ -47,20 +47,27 @@ string CommandSoeRead::helpString() const { stringstream str; - str << getName() << " [OPTIONS] <INDEX> <SUBINDEX>" << endl + str << getName() << " [OPTIONS] <IDN>" << endl << endl << getBriefDescription() << endl << endl << "This command requires a single slave to be selected." << endl << endl << "Arguments:" << endl - << " IDN is the IDN and must be an unsigned" << endl - << " 16 bit number." << endl + << " IDN is the IDN and must be either an unsigned" << endl + << " 16 bit number acc. to IEC 61800-7-204:" << endl + << " Bit 15: (0) Standard data, (1) Product data" << endl + << " Bit 14 - 12: Parameter set (0 - 7)" << endl + << " Bit 11 - 0: Data block number" << endl + << " or a string like 'P-0-150'." << endl + << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl << " --position -p <pos> Slave selection. See the help of" << endl << " the 'slaves' command." << endl + << " --type -t <type> Data type (see above)." << endl << endl << numericInfo(); @@ -72,7 +79,7 @@ string CommandSoeRead::helpString() const void CommandSoeRead::execute(const StringVector &args) { SlaveList slaves; - stringstream err, strIdn; + stringstream err; const DataType *dataType = NULL; ec_ioctl_slave_soe_read_t ioctl; @@ -81,12 +88,10 @@ void CommandSoeRead::execute(const StringVector &args) throwInvalidUsageException(err); } - strIdn << args[0]; - strIdn - >> resetiosflags(ios::basefield) // guess base from prefix - >> ioctl.idn; - if (strIdn.fail()) { - err << "Invalid IDN '" << args[0] << "'!"; + try { + ioctl.idn = parseIdn(args[0]); + } catch (runtime_error &e) { + err << "Invalid IDN '" << args[0] << "': " << e.what(); throwInvalidUsageException(err); } diff --git a/tool/CommandSoeRead.h b/tool/CommandSoeRead.h index c7cff524..31ac9fe6 100644 --- a/tool/CommandSoeRead.h +++ b/tool/CommandSoeRead.h @@ -30,14 +30,12 @@ #ifndef __COMMANDSOEREAD_H__ #define __COMMANDSOEREAD_H__ -#include "Command.h" -#include "DataTypeHandler.h" +#include "SoeCommand.h" /****************************************************************************/ class CommandSoeRead: - public Command, - public DataTypeHandler + public SoeCommand { public: CommandSoeRead(); diff --git a/tool/CommandSoeWrite.cpp b/tool/CommandSoeWrite.cpp index 1d93f48d..a67345b4 100644 --- a/tool/CommandSoeWrite.cpp +++ b/tool/CommandSoeWrite.cpp @@ -37,7 +37,7 @@ using namespace std; /*****************************************************************************/ CommandSoeWrite::CommandSoeWrite(): - Command("soe_write", "Write an SoE IDN to a slave.") + SoeCommand("soe_write", "Write an SoE IDN to a slave.") { } @@ -47,17 +47,23 @@ string CommandSoeWrite::helpString() const { stringstream str; - str << getName() << " [OPTIONS] <INDEX> <SUBINDEX> <VALUE>" << endl + str << getName() << " [OPTIONS] <IDN> <VALUE>" << endl << endl << getBriefDescription() << endl << endl << "This command requires a single slave to be selected." << endl << endl << "Arguments:" << endl - << " IDN is the IDN and must be an unsigned" << endl - << " 16 bit number." << endl + << " IDN is the IDN and must be either an unsigned" << endl + << " 16 bit number acc. to IEC 61800-7-204:" << endl + << " Bit 15: (0) Standard data, (1) Product data" << endl + << " Bit 14 - 12: Parameter set (0 - 7)" << endl + << " Bit 11 - 0: Data block number" << endl + << " or a string like 'P-0-150'." << endl << " VALUE is the value to write and is interpreted" << endl << " as the given datatype (see above)." << endl + << endl + << typeInfo() << endl << "Command-specific options:" << endl << " --alias -a <alias>" << endl @@ -85,12 +91,10 @@ void CommandSoeWrite::execute(const StringVector &args) throwInvalidUsageException(err); } - strIdn << args[0]; - strIdn - >> resetiosflags(ios::basefield) // guess base from prefix - >> ioctl.idn; - if (strIdn.fail()) { - err << "Invalid IDN '" << args[0] << "'!"; + try { + ioctl.idn = parseIdn(args[0]); + } catch (runtime_error &e) { + err << "Invalid IDN '" << args[0] << "': " << e.what(); throwInvalidUsageException(err); } diff --git a/tool/CommandSoeWrite.h b/tool/CommandSoeWrite.h index 3c507b4a..c5cc14f5 100644 --- a/tool/CommandSoeWrite.h +++ b/tool/CommandSoeWrite.h @@ -30,14 +30,12 @@ #ifndef __COMMANDSOEWRITE_H__ #define __COMMANDSOEWRITE_H__ -#include "Command.h" -#include "DataTypeHandler.h" +#include "SoeCommand.h" /****************************************************************************/ class CommandSoeWrite: - public Command, - public DataTypeHandler + public SoeCommand { public: CommandSoeWrite(); diff --git a/tool/CommandUpload.cpp b/tool/CommandUpload.cpp index 0f960585..7a186f54 100644 --- a/tool/CommandUpload.cpp +++ b/tool/CommandUpload.cpp @@ -59,9 +59,7 @@ string CommandUpload::helpString() const << "information service or the SDO is not in the dictionary," << endl << "the --type option is mandatory." << endl << endl - << "These are the valid SDO entry data types:" << endl - << " int8, int16, int32, uint8, uint16, uint32, string," << endl - << " octet_string." << endl + << typeInfo() << endl << "Arguments:" << endl << " INDEX is the SDO index and must be an unsigned" << endl diff --git a/tool/DataTypeHandler.cpp b/tool/DataTypeHandler.cpp index 028c451c..2dfaf838 100644 --- a/tool/DataTypeHandler.cpp +++ b/tool/DataTypeHandler.cpp @@ -64,6 +64,20 @@ const DataTypeHandler::DataType *DataTypeHandler::findDataType( /****************************************************************************/ +string DataTypeHandler::typeInfo() +{ + stringstream s; + + s + << "These are valid data types to use with" << endl + << "the --type option:" << endl + << " int8, int16, int32, uint8, uint16, uint32, string," << endl + << " octet_string." << endl; + return s.str(); +} + +/****************************************************************************/ + const DataTypeHandler::DataType *DataTypeHandler::findDataType(uint16_t code) { const DataType *d; diff --git a/tool/DataTypeHandler.h b/tool/DataTypeHandler.h index 2a0e08a0..90648957 100644 --- a/tool/DataTypeHandler.h +++ b/tool/DataTypeHandler.h @@ -51,6 +51,8 @@ class DataTypeHandler size_t byteSize; }; + static std::string typeInfo(); + static const DataType *findDataType(const std::string &); static const DataType *findDataType(uint16_t); static size_t interpretAsType(const DataType *, const std::string &, diff --git a/tool/Makefile.am b/tool/Makefile.am index ba4d7fcd..b1de2434 100644 --- a/tool/Makefile.am +++ b/tool/Makefile.am @@ -66,6 +66,7 @@ ethercat_SOURCES = \ MasterDevice.cpp \ NumberListParser.cpp \ SdoCommand.cpp \ + SoeCommand.cpp \ main.cpp \ sii_crc.cpp @@ -106,6 +107,7 @@ noinst_HEADERS = \ MasterDevice.h \ NumberListParser.h \ SdoCommand.h \ + SoeCommand.h \ sii_crc.h if ENABLE_EOE diff --git a/tool/SoeCommand.cpp b/tool/SoeCommand.cpp new file mode 100644 index 00000000..70030e20 --- /dev/null +++ b/tool/SoeCommand.cpp @@ -0,0 +1,108 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master 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 the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +#include <iomanip> +using namespace std; + +#include "SoeCommand.h" + +/*****************************************************************************/ + +SoeCommand::SoeCommand(const string &name, const string &briefDesc): + Command(name, briefDesc) +{ +} + +/*****************************************************************************/ + +uint16_t SoeCommand::parseIdn(const string &str) +{ + uint16_t idn = 0x0000; + stringstream s, err; + + if (!str.length()) { + err << "Zero-size string not allowed!"; + throw runtime_error(err.str()); + } + + if (str[0] == 'S' || str[0] == 'P') { + unsigned int num; + unsigned char c; + + s << str; + + s >> c; + if (c == 'P') { + idn |= 0x8000; + } + + s >> c; + if (s.fail() || c != '-') { + err << "'-' expected!"; + throw runtime_error(err.str()); + } + + s >> num; + if (s.fail() || num > 7) { + err << "Invalid parameter set number!"; + throw runtime_error(err.str()); + } + idn |= num << 12; + + s >> c; + if (s.fail() || c != '-') { + err << "'-' expected!"; + throw runtime_error(err.str()); + } + + s >> num; + if (s.fail() || num > 4095) { + err << "Invalid data block number!"; + throw runtime_error(err.str()); + } + idn |= num; + + s.peek(); + if (!s.eof()) { + err << "Additional input!"; + throw runtime_error(err.str()); + } + } else { + s << str; + s >> resetiosflags(ios::basefield) >> idn; + if (s.fail()) { + err << "Invalid number!"; + throw runtime_error(err.str()); + } + } + + return idn; +} + +/****************************************************************************/ diff --git a/tool/SoeCommand.h b/tool/SoeCommand.h new file mode 100644 index 00000000..478bec90 --- /dev/null +++ b/tool/SoeCommand.h @@ -0,0 +1,51 @@ +/***************************************************************************** + * + * $Id$ + * + * Copyright (C) 2006-2009 Florian Pose, Ingenieurgemeinschaft IgH + * + * This file is part of the IgH EtherCAT Master. + * + * The IgH EtherCAT Master is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License version 2, as + * published by the Free Software Foundation. + * + * The IgH EtherCAT Master 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 the IgH EtherCAT Master; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * --- + * + * The license mentioned above concerns the source code only. Using the + * EtherCAT technology and brand is only permitted in compliance with the + * industrial property and similar rights of Beckhoff Automation GmbH. + * + ****************************************************************************/ + +#ifndef __SOECOMMAND_H__ +#define __SOECOMMAND_H__ + +#include "Command.h" +#include "DataTypeHandler.h" + +/****************************************************************************/ + +class SoeCommand: + public Command, + public DataTypeHandler +{ + public: + SoeCommand(const string &, const string &); + + protected: + static uint16_t parseIdn(const string &); +}; + +/****************************************************************************/ + +#endif -- GitLab