diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp index b84af33f7d35a9ace89b5b232c008e445db0b707..9770f08a6b95d0d2dea97e29c722ab05a0461df7 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.cpp @@ -157,7 +157,7 @@ namespace Silecs "PlcBrand=" << brand_ << ", " << "PlcSystem=" << system_ << ", " << "PlcModel=" << model_ << ", " << - "ProtocolAddress=" << baseAddr_ << ", " << + "ProtocolAddress=" << baseMemAddr_ << ", " << "ProtocolMode=" << protocolMode_ << ", " << "InstanceNumber=" << deviceCol_.size(); } @@ -241,8 +241,35 @@ namespace Silecs std::string PLC::getModel() { return model_; } std::string PLC::getProtocolType() { return protocolType_; } std::string PLC::getProtocolMode() { return protocolMode_; } - unsigned long PLC::getBaseAddress() { return baseAddr_; } + unsigned long PLC::getBaseAddress() + { + return baseMemAddr_; + } + + long PLC::getMemBaseAddress() + { + return baseMemAddr_; + } + + long PLC::getDIBaseAddress() + { + return baseDIAddr_; + } + long PLC::getDOBaseAddress() + { + return baseDOAddr_; + } + + long PLC::getAIBaseAddress() + { + return baseAIAddr_; + } + + long PLC::getAOBaseAddress() + { + return baseAOAddr_; + } deviceVectorType& PLC::getDeviceMap() { return deviceCol_; } std::string PLC::getLocalRelease() { return localRelease_; } std::string PLC::getLocalOwner() { return localOwner_; } @@ -377,7 +404,11 @@ namespace Silecs system_ = mappingNode.getAttribute("plc-system"); protocolMode_ = mappingNode.getAttribute("protocol"); model_ = mappingNode.getAttribute("plc-model"); - StringUtilities::fromString(baseAddr_,mappingNode.getAttribute("address") ); + StringUtilities::fromString(baseMemAddr_,mappingNode.getAttribute("address") ); + StringUtilities::fromString(baseDIAddr_,mappingNode.getAttribute("DI-address") ); + StringUtilities::fromString(baseDOAddr_,mappingNode.getAttribute("DO-address") ); + StringUtilities::fromString(baseAIAddr_,mappingNode.getAttribute("AI-address") ); + StringUtilities::fromString(baseAOAddr_,mappingNode.getAttribute("AO-address") ); usedMem_ = mappingNode.getAttribute("used-mem"); typeID_ = whichPLCType(model_); brandID_ = whichPLCBrand(brand_); diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h index b3387d288ccb427bb682be04196eda5820c15f2a..76abfa3dfa110ffa15253edee83ba430cd3cca97 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsPLC.h @@ -173,13 +173,54 @@ namespace Silecs */ std::string getProtocolMode(); - /*! - * \brief Returns the base address of the SILECS configuration within the PLC memory - * \return DB number for SIMATIC-S7 - * \return 16bits absolute memory address for UNITY Premium/Quantum - * \return 32bits absolute memory address for UNITY M340 - */ - unsigned long getBaseAddress(); + /*! + * \deprecated Use getMemBaseAddress() instead + * \brief Returns the memory base address of the SILECS configuration within the PLC + * \return DB number for SIMATIC-S7 + * \return 16bits absolute memory address for UNITY Premium/Quantum + * \return 32bits absolute memory address for UNITY M340 + */ + unsigned long getBaseAddress(); + + /*! + * \brief Returns the memory base address of the SILECS configuration within the PLC + * \return DB number for SIMATIC-S7 + * \return 16bits absolute memory address for UNITY Premium/Quantum + * \return 32bits absolute memory address for UNITY M340 + */ + long getMemBaseAddress(); + + /*! + * \brief Returns the digital input base address of the SILECS configuration within the PLC + * \return byte address for SIMATIC-S7 + * \return byte address for MODBUS TCP + * \return -1 in case of non existent address + */ + long getDIBaseAddress(); + + /*! + * \brief Returns the digital output base address of the SILECS configuration within the PLC + * \return byte address for SIMATIC-S7 + * \return byte address for MODBUS TCP + * \return -1 in case of non existent address + */ + long getDOBaseAddress(); + + /*! + * \brief Returns the analog input base address of the SILECS configuration within the PLC + * \return byte address for SIMATIC-S7 + * \return byte address for MODBUS TCP + * \return -1 in case of non existent address + */ + long getAIBaseAddress(); + + /*! + * \brief Returns the analog output base address of the SILECS configuration within the PLC + * \return byte address for SIMATIC-S7 + * \return byte address for MODBUS TCP + * \return -1 in case of non existent address + */ + long getAOBaseAddress(); /*! * \brief Extracts SILECS release information from the client configuration parameters. @@ -482,8 +523,12 @@ namespace Silecs ProtocolMode protocolModeID_; //BlockMode, DeviceMode enumeration ProtocolType protocolTypeID_; //Modbus, S7 enumeration - long baseAddr_; - std::string usedMem_; + long baseMemAddr_; + long baseDIAddr_; + long baseDOAddr_; + long baseAIAddr_; + long baseAOAddr_; + std::string usedMem_; string parameterFile_; diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp index ec6ff934ed6c7cef010a1415d3ec7e4bfb84a386..6831c73ba0d29e02d8427ea3329767b83f20a30b 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.cpp @@ -16,6 +16,7 @@ #include <silecs-communication/interface/core/SilecsService.h> #include <silecs-communication/interface/utility/XMLParser.h> #include <silecs-communication/interface/equipment/SilecsPLC.h> +#include <silecs-communication/interface/equipment/SilecsBlock.h> #include <silecs-communication/interface/equipment/SilecsDevice.h> #include <silecs-communication/interface/equipment/SilecsRegister.h> #include <silecs-communication/interface/utility/SilecsException.h> @@ -654,53 +655,112 @@ namespace Silecs bool Register::isReadable() { return (accessType_ != Output); } bool Register::isWritable() { return (accessType_ != Input); } - bool Register::isIORegister() { return (accessArea_ != Memory); } - bool Register::isMemoryRegister() { return (accessArea_ == Memory); } - + bool Register::hasInputAccess() + { + return (accessType_ != Output); + } + bool Register::hasOutputAccess() + { + return (accessType_ != Input); + } + bool Register::isIORegister() + { + return (accessArea_ == Digital || accessArea_ == Analog); + } + bool Register::isDIRegister() + { + return (accessArea_ == Digital && accessType_ == Input); + } + bool Register::isDORegister() + { + return (accessArea_ == Digital && accessType_ == Output); + } + bool Register::isAIRegister() + { + return (accessArea_ == Analog && accessType_ == Input); + } + bool Register::isAORegister() + { + return (accessArea_ == Analog && accessType_ == Output); + } + bool Register::isMemoryRegister() + { + return (accessArea_ == Memory); + } + bool Register::isRetentive() + { + return !isVolatile_; + } bool Register::isVolatile(){ return isVolatile_; } bool Register::isScalar() { return ((dimension1_ == 1) && (dimension2_ == 1)); } bool Register::isSingleArray() { return ((dimension1_ > 1) && (dimension2_ == 1)); } bool Register::isDoubleArray() { return (dimension2_ > 1); } bool Register::isInitialized() { return isInitialized_; } + std::string Register::whichAccessArea(AccessArea area) + { + return Block::whichAccessArea(area); + } + FormatType Register::whichFormatType(std::string type) { - StringUtilities::toLower(type); -#ifndef __x86_64__ -//SLC5 (32bits platform) still uses deprecated types ======== - if (type == "byte") return uChar; - else if (type == "int") return Short; - else if (type == "word") return uShort; - else if (type == "dint") return Long; - else if (type == "dword") return uLong; - else if (type == "real") return Float; -#else -//SLC6 (64bits platform) ==================================== - if (type == "byte") return uInt8; - else if (type == "int") return Int16; - else if (type == "word") return uInt16; - else if (type == "dint") return Int32; - else if (type == "dword") return uInt32; - else if (type == "real") return Float32; -#endif -// ANY platform ============================================= - if (type == "char") return Char; - - else if (type == "dt") return Date; - else if (type == "date") return Date; - - else if (type == "int8") return Int8; - else if (type == "uint8") return uInt8; - else if (type == "int16") return Int16; - else if (type == "uint16") return uInt16; - else if (type == "int32") return Int32; - else if (type == "uint32") return uInt32; - else if (type == "int64") return Int64; - else if (type == "uint64") return uInt64; - else if (type == "float32") return Float32; - else if (type == "float64") return Float64; - else if (type == "string") return String; - else throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_FORMAT_TYPE, type); + StringUtilities::toLower(type); + #ifndef __x86_64__ + //SLC5 (32bits platform) still uses deprecated types ======== + if (type == "byte") return uChar; + else if (type == "int") return Short; + else if (type == "word") return uShort; + else if (type == "dint") return Long; + else if (type == "dword") return uLong; + else if (type == "real") return Float; + #else + //SLC6 (64bits platform) ==================================== + if (type == "byte") + return uInt8; + else if (type == "int") + return Int16; + else if (type == "word") + return uInt16; + else if (type == "dint") + return Int32; + else if (type == "dword") + return uInt32; + else if (type == "real") + return Float32; + #endif + // ANY platform ============================================= + if (type == "char") + return Char; + + else if (type == "dt") + return Date; + else if (type == "date") + return Date; + + else if (type == "int8") + return Int8; + else if (type == "uint8") + return uInt8; + else if (type == "int16") + return Int16; + else if (type == "uint16") + return uInt16; + else if (type == "int32") + return Int32; + else if (type == "uint32") + return uInt32; + else if (type == "int64") + return Int64; + else if (type == "uint64") + return uInt64; + else if (type == "float32") + return Float32; + else if (type == "float64") + return Float64; + else if (type == "string") + return String; + else + throw SilecsException(__FILE__, __LINE__, DATA_UNKNOWN_FORMAT_TYPE, type); } diff --git a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h index da180948667a03c30624cb92c5780a56a1fb3f15..ac6805f241d5645a8693dfd2e67bd3f5f2f21402 100644 --- a/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h +++ b/silecs-communication-cpp/src/silecs-communication/interface/equipment/SilecsRegister.h @@ -152,21 +152,64 @@ namespace Silecs */ timeval getTimeStamp(); - bool isReadable(); - - bool isWritable(); - - /*! - * \brief A register can be Memory or IO peripheral register. - * \return true if the register is an IO register (Digital, Analog) - */ - bool isIORegister(); - - /*! - * \brief A register can be Memory or IO peripheral register. - * \return true if the register is a Memory register - */ - bool isMemoryRegister(); + /*! + * \brief A register can have read-only, write-only or read-write access mode as defined in the Class design. + * \return true if register has read-only or read-write access mode + */ + bool hasInputAccess(); + bool isReadable(); + + /*! + * \brief A register can have read-only, write-only or read-write access mode as defined in the Class design. + * \return true if the register has write-only or read-write access mode + */ + bool hasOutputAccess(); + bool isWritable(); + + /*! + * \brief A register can be Memory or IO peripheral register. + * \return true if the register is an IO register (Digital, Analog) + */ + bool isIORegister(); + + /*! + * \brief A register can belong to either digital or analog IO + * \return true if the register is digital input register + */ + bool isDIRegister(); + + /*! + * \brief A register can belong to either digital or analog IO + * \return true if the register is digital output register + */ + bool isDORegister(); + + /*! + * \brief A register can belong to either digital or analog IO + * \return true if the register is analog input register + */ + bool isAIRegister(); + + /*! + * \brief A register can belong to either digital or analog IO + * \return true if the register is analog output register + */ + bool isAORegister(); + + /*! + * \brief A register can be Memory or IO peripheral register. + * \return true if the register is a Memory register + */ + bool isMemoryRegister(); + + /*! + * \brief A retentive register can be a persistent or a constant data. + * Its value must be initialized at the system start-up. + * - From the client side if the synchro register is 'Slave' + * - From the PLC side if the synchro register is 'Master' + * \return true if the register has Master or Slave synchro as defined in the Class design + */ + bool isRetentive(); /*! * \brief A register that has not persistent or constant value is Volatile. @@ -1587,12 +1630,18 @@ namespace Silecs */ void printVal(); - /// @cond - /*! - * \fn whichFormatType - * \return Enumeration value of the given format-type string - */ - FormatType whichFormatType(std::string type); + /*! + * \fn whichAccessArea + * \return the string of the given access-area enum + */ + std::string whichAccessArea(AccessArea area); + + /// @cond + /*! + * \fn whichFormatType + * \return Enumeration value of the given format-type string + */ + FormatType whichFormatType(std::string type); bool isInitialized(); /// @endcond diff --git a/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.cpp b/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.cpp index 5ca9d91db63502baba5789075837d2cf78f2585b..52f5b790d2d32e2041bb5027e22addc8ad8799c7 100755 --- a/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.cpp +++ b/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.cpp @@ -878,50 +878,36 @@ void silecsModule::setArrayRegValue(Item *currentItem, std::vector<QString> *dat } } - -HeaderInformations* silecsModule::getHeaderInformations(std::string plcName, string parameterFile) +HeaderInformations* silecsModule::getHeaderInformations(std::string plcName) { HeaderInformations* headerInfos = new HeaderInformations(); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; Silecs::Cluster *headerCluster = silecsService->getCluster(HEADER_NAME,HEADER_VERSION); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; - Silecs::PLC *plc = headerCluster->getPLC(plcName, parameterFile); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; + + Silecs::PLC *plc = headerCluster->getPLC(plcName); + Silecs::Device *device = plc->getDevice(HEADER_DEVICE); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; + plc->connect(Silecs::MASTER_SYNCHRO,true); //connection will cause automatic Header registers uploading - std::cout << "getHeaderInformations " << __LINE__ << std::endl; + Silecs::Register *reg; - std::cout << "getHeaderInformations " << __LINE__ << std::endl; - // get/set release + reg = device->getRegister(HEADER_RELEASE_REG); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; headerInfos->setheaderRelease(reg->getValString()); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; - // get/set release reg = device->getRegister(HEADER_OWNER_REG); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; headerInfos->setheaderOwner(reg->getValString()); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; - // get/set release reg = device->getRegister(HEADER_DATE_REG); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; headerInfos->setheaderDate(reg->getInputValAsString()); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; - // get/set release - // TODO: Fix checksum stuff for GSI - //reg = device->getRegister(HEADER_CHECKSUM_REG); - //headerInfos->setHeaderChecksum(reg->getInputValAsString()); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; + reg = device->getRegister(HEADER_CHECKSUM_REG); + headerInfos->setHeaderChecksum(reg->getInputValAsString()); + // disconnect plc - if(plc->isConnected()) + if(plc->isConnected(false)) plc->disconnect(); - std::cout << "getHeaderInformations " << __LINE__ << std::endl; + return headerInfos; } - void silecsModule::updateClusterItem(Item *Cluster,bool updateInputBufferOnly) { int numberOfPLC = Cluster->childCount(); diff --git a/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.h b/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.h index fea4e78e1a042636c8fb7d20b4b1f6705a2cfc58..e61118e437544bace6830a070decd160c781a237 100755 --- a/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.h +++ b/silecs-diagnostic-cpp/src/silecs-diagnostic/silecsmodule.h @@ -111,7 +111,7 @@ public: * Get Header for the given plc name * return a heade info with all the data set */ - HeaderInformations* getHeaderInformations(std::string plcName, string parameterFile); + HeaderInformations* getHeaderInformations(std::string plcName); /** * Count the number of PLC connected diff --git a/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.cpp b/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.cpp index 1ea5bfd2cc371e8b39c13c8bd18ffc1b54a4dc2f..a996a0727ada3865bdc807d08aabc3486de18853 100755 --- a/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.cpp +++ b/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.cpp @@ -55,6 +55,13 @@ std::string Utils::convertLong(long number) return tmp; } +std::string Utils::convertHex(long number) +{ + std::stringstream stream; + stream << std::hex << number; + return stream.str(); +} + Item* Utils::addTreeItem(Item *parent,QString name ,QString description, QString type, void* linkedObject,QString icon) { Item *itm = new Item(linkedObject); @@ -106,26 +113,26 @@ void Utils::displayClusterInformation(Silecs::Cluster *cluster,QTextEdit *consol } + void Utils::displayPLCInformation(Silecs::PLC *plc,QTextEdit *console) { std::string text = ""; - //TODO: GSI Add Header Info - if(plc->isConnected()) + if(plc->isConnected(false)) { -// text.append("<h3><font color ='green'>This PLC is currently connected</font></h3><hr/>"); -// -// HeaderInformations *headerInfo = mysilecs->getHeaderInformations(plc->getName(),plc->getParamsFileName()); -// text.append("<h3><font color ='green'>PLC Runtime information</font></h3>"); -// text.append("<ul>"); -// text.append("<li>PLC HEADER DATA uploaded from: "+plc->getName()+"</li>"); -// text.append("<li>Software Release: "+headerInfo->getheaderRelease()+"</li>"); -// text.append("<li>Mapping Owner: "+headerInfo->getheaderOwner()+"</li>"); -// text.append("<li>Mapping Checksum: "+headerInfo->getHeaderChecksum()+"</li>"); -// text.append("<li>Generation Date: "+headerInfo->getheaderDate()+"</li>"); -// text.append("</ul><hr/>"); -// -// delete headerInfo; + text.append("<h3><font color ='green'>This PLC is currently connected</font></h3><hr/>"); + + HeaderInformations *headerInfo = mysilecs->getHeaderInformations(plc->getName()); + text.append("<h3><font color ='green'>PLC Runtime information</font></h3>"); + text.append("<ul>"); + text.append("<li>PLC HEADER DATA uploaded from: "+plc->getName()+"</li>"); + text.append("<li>Software Release: "+headerInfo->getheaderRelease()+"</li>"); + text.append("<li>Mapping Owner: "+headerInfo->getheaderOwner()+"</li>"); + text.append("<li>Mapping Checksum: "+headerInfo->getHeaderChecksum()+"</li>"); + text.append("<li>Generation Date: "+headerInfo->getheaderDate()+"</li>"); + text.append("</ul><hr/>"); + + delete headerInfo; } else text.append("<h3>This PLC is currently disconnected</h3><hr/>"); @@ -143,7 +150,32 @@ void Utils::displayPLCInformation(Silecs::PLC *plc,QTextEdit *console) text.append("<ul>"); text.append("<li>Protocol type: "+plc->getProtocolType()+"</li>"); text.append("<li>Protocol mode: "+plc->getProtocolMode()+"</li>"); - text.append("<li>Base address: "+convertLong(plc->getBaseAddress())+"</li>"); + + if (plc->getMemBaseAddress() > -1) + text.append("<li>Memory Base address: "+convertLong(plc->getMemBaseAddress())+" (0x"+convertHex(plc->getMemBaseAddress())+")"+ "</li>"); + else + text.append("<li>Memory Base address: Not applicable</li>"); + + if (plc->getDIBaseAddress() > -1) + text.append("<li>DI Base address: "+convertLong(plc->getDIBaseAddress())+" (0x"+convertHex(plc->getDIBaseAddress())+")"+ "</li>"); + else + text.append("<li>DI Base address: Not applicable</li>"); + + if (plc->getDOBaseAddress() > -1) + text.append("<li>DO Base address: "+convertLong(plc->getDOBaseAddress())+" (0x"+convertHex(plc->getDOBaseAddress())+")"+ "</li>"); + else + text.append("<li>DO Base address: Not applicable</li>"); + + if (plc->getAIBaseAddress() > -1) + text.append("<li>AI Base address: "+convertLong(plc->getAIBaseAddress())+" (0x"+convertHex(plc->getAIBaseAddress())+")"+ "</li>"); + else + text.append("<li>AI Base address: Not applicable</li>"); + + if (plc->getAOBaseAddress() > -1) + text.append("<li>AO Base address: "+convertLong(plc->getAOBaseAddress())+" (0x"+convertHex(plc->getAOBaseAddress())+")"+ "</li>"); + else + text.append("<li>AO Base address: Not applicable</li>"); + text.append("</ul><hr/>"); text.append("<h3>PLC generation information</h3>"); @@ -184,18 +216,25 @@ void Utils::displayRegisterInformation(Silecs::Register *reg,QTextEdit *console) text.append("<li>Last update: "+reg->getTimeStampAsString()+"</li>"); // Access method - if(reg->isReadable() && reg->isWritable()) + if(reg->hasInputAccess() && reg->hasOutputAccess()) text.append("<li>Access method: Read / Write </li>"); else { - if(reg->isReadable()) text.append("<li>Access method: Read only </li>"); + if(reg->hasInputAccess()) text.append("<li>Access method: Read only </li>"); else text.append("<li>Access method: Write only </li>"); } + text.append("<li>Access area: "+reg->whichAccessArea(reg->getAccessArea())+"</li>"); + + // Retentive volatile + if(reg->isRetentive()) + text.append("<li>Storage method: Retentive</li>"); + else + text.append("<li>Storage method: Volatile</li>"); + text.append("</ul>"); console->setText(QString::fromStdString(text)); - } void Utils::displayRegisterValue(Silecs::Register *reg, diff --git a/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.h b/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.h index 13666ee36a6061549418b4c1c65bdff2e59cfe25..2a7bb83e0670df4adec088643b3f9691eef268e8 100755 --- a/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.h +++ b/silecs-diagnostic-cpp/src/silecs-diagnostic/utils.h @@ -55,6 +55,11 @@ namespace Utils { */ std::string convertLong(long number); + /** + * Convert a long number in the equivalent string (hex) + */ + std::string convertHex(long number); + /** * Add an element to the tree */