|
UniSet
2.6.0
|
00001 /* 00002 * Copyright (c) 2015 Pavel Vainerman. 00003 * 00004 * This program is free software: you can redistribute it and/or modify 00005 * it under the terms of the GNU Lesser General Public License as 00006 * published by the Free Software Foundation, version 2.1. 00007 * 00008 * This program is distributed in the hope that it will be useful, but 00009 * WITHOUT ANY WARRANTY; without even the implied warranty of 00010 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00011 * Lesser General Lesser Public License for more details. 00012 * 00013 * You should have received a copy of the GNU Lesser General Public License 00014 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00015 */ 00016 // ----------------------------------------------------------------------------- 00017 #ifndef _MBSlave_H_ 00018 #define _MBSlave_H_ 00019 // ----------------------------------------------------------------------------- 00020 #include <ostream> 00021 #include <string> 00022 #include <memory> 00023 #include <map> 00024 #include <unordered_map> 00025 #include <vector> 00026 #include <condition_variable> 00027 #include <atomic> 00028 #include <mutex> 00029 #include "UniSetObject.h" 00030 #include "modbus/ModbusTypes.h" 00031 #include "modbus/ModbusServerSlot.h" 00032 #include "modbus/ModbusTCPServer.h" 00033 #include "modbus/ModbusTCPServerSlot.h" 00034 #include "PassiveTimer.h" 00035 #include "Trigger.h" 00036 #include "Mutex.h" 00037 #include "SMInterface.h" 00038 #include "SharedMemory.h" 00039 #include "IOBase.h" 00040 #include "VTypes.h" 00041 #include "ThreadCreator.h" 00042 #include "LogServer.h" 00043 #include "LogAgregator.h" 00044 #include "VMonitor.h" 00045 // ----------------------------------------------------------------------------- 00046 #ifndef vmonit 00047 #define vmonit( var ) vmon.add( #var, var ) 00048 #endif 00049 // ------------------------------------------------------------------------- 00050 namespace uniset 00051 { 00052 // ----------------------------------------------------------------------------- 00307 // ----------------------------------------------------------------------------- 00309 class MBSlave: 00310 public UniSetObject 00311 { 00312 public: 00313 MBSlave( uniset::ObjectId objId, uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr, const std::string& prefix = "mbs" ); 00314 virtual ~MBSlave(); 00315 00317 static std::shared_ptr<MBSlave> init_mbslave(int argc, const char* const* argv, 00318 uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr, 00319 const std::string& prefix = "mbs" ); 00320 00322 static void help_print( int argc, const char* const* argv ); 00323 00324 static const int NoSafetyState = -1; 00325 00326 enum AccessMode 00327 { 00328 amRW, 00329 amRO, 00330 amWO 00331 }; 00332 00333 struct BitRegProperty; 00334 00335 struct IOProperty: 00336 public IOBase 00337 { 00338 ModbusRTU::ModbusData mbreg; 00339 AccessMode amode; 00340 VTypes::VType vtype; 00341 size_t wnum; 00342 size_t nbyte; 00343 std::shared_ptr<BitRegProperty> bitreg; 00344 ModbusRTU::RegID regID; 00345 00346 IOProperty(): 00347 mbreg(0), 00348 amode(amRW), 00349 vtype(VTypes::vtUnknown), 00350 wnum(0), 00351 nbyte(0), 00352 regID(0) 00353 {} 00354 00355 friend std::ostream& operator<<( std::ostream& os, IOProperty& p ); 00356 }; 00357 00358 00359 struct BitRegProperty 00360 { 00361 typedef std::vector<IOProperty> BitSensorMap; 00362 00363 ModbusRTU::ModbusData mbreg; 00364 BitSensorMap bvec; 00365 00366 BitRegProperty(): mbreg(0), bvec(ModbusRTU::BitsPerData) {} 00367 00369 bool check( const IOController_i::SensorInfo& si ); 00370 00371 friend std::ostream& operator<<( std::ostream& os, BitRegProperty& p ); 00372 friend std::ostream& operator<<( std::ostream& os, BitRegProperty* p ); 00373 }; 00374 00375 inline long getAskCount() 00376 { 00377 return askCount; 00378 } 00379 00380 inline std::shared_ptr<LogAgregator> getLogAggregator() 00381 { 00382 return loga; 00383 } 00384 inline std::shared_ptr<DebugStream> log() 00385 { 00386 return mblog; 00387 } 00388 00389 virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override; 00390 00391 protected: 00392 00394 ModbusRTU::mbErrCode readCoilStatus( ModbusRTU::ReadCoilMessage& query, 00395 ModbusRTU::ReadCoilRetMessage& reply ); 00397 ModbusRTU::mbErrCode readInputStatus( ModbusRTU::ReadInputStatusMessage& query, 00398 ModbusRTU::ReadInputStatusRetMessage& reply ); 00399 00401 ModbusRTU::mbErrCode readOutputRegisters( ModbusRTU::ReadOutputMessage& query, 00402 ModbusRTU::ReadOutputRetMessage& reply ); 00403 00405 ModbusRTU::mbErrCode readInputRegisters( ModbusRTU::ReadInputMessage& query, 00406 ModbusRTU::ReadInputRetMessage& reply ); 00407 00409 ModbusRTU::mbErrCode forceSingleCoil( ModbusRTU::ForceSingleCoilMessage& query, 00410 ModbusRTU::ForceSingleCoilRetMessage& reply ); 00411 00413 ModbusRTU::mbErrCode forceMultipleCoils( ModbusRTU::ForceCoilsMessage& query, 00414 ModbusRTU::ForceCoilsRetMessage& reply ); 00415 00416 00418 ModbusRTU::mbErrCode writeOutputRegisters( ModbusRTU::WriteOutputMessage& query, 00419 ModbusRTU::WriteOutputRetMessage& reply ); 00420 00422 ModbusRTU::mbErrCode writeOutputSingleRegister( ModbusRTU::WriteSingleOutputMessage& query, 00423 ModbusRTU::WriteSingleOutputRetMessage& reply ); 00424 00426 // ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query, 00427 // ModbusRTU::JournalCommandRetMessage& reply ); 00428 00430 ModbusRTU::mbErrCode setDateTime( ModbusRTU::SetDateTimeMessage& query, 00431 ModbusRTU::SetDateTimeRetMessage& reply ); 00432 00434 ModbusRTU::mbErrCode remoteService( ModbusRTU::RemoteServiceMessage& query, 00435 ModbusRTU::RemoteServiceRetMessage& reply ); 00436 00437 ModbusRTU::mbErrCode fileTransfer( ModbusRTU::FileTransferMessage& query, 00438 ModbusRTU::FileTransferRetMessage& reply ); 00439 00440 ModbusRTU::mbErrCode diagnostics( ModbusRTU::DiagnosticMessage& query, 00441 ModbusRTU::DiagnosticRetMessage& reply ); 00442 00443 ModbusRTU::mbErrCode read4314( ModbusRTU::MEIMessageRDI& query, 00444 ModbusRTU::MEIMessageRetRDI& reply ); 00445 00449 virtual ModbusRTU::mbErrCode checkRegister( ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val ) 00450 { 00451 return ModbusRTU::erNoError; 00452 } 00453 00454 // т.к. в функциях (much_real_read,nuch_real_write) рассчёт на отсортированность IOMap 00455 // то использовать unordered_map нельзя 00456 typedef std::map<ModbusRTU::RegID, IOProperty> RegMap; 00457 00458 typedef std::unordered_map<ModbusRTU::ModbusAddr, RegMap> IOMap; 00459 00460 IOMap iomap; 00462 // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список 00463 // и отдельно его проверяем потом 00464 typedef std::list<IOBase> ThresholdList; 00465 ThresholdList thrlist; 00466 00467 std::shared_ptr<ModbusServerSlot> mbslot; 00468 std::unordered_set<ModbusRTU::ModbusAddr> vaddr; 00469 std::string default_mbaddr = { "" }; 00470 00471 xmlNode* cnode = { 0 }; 00472 std::string s_field = { "" }; 00473 std::string s_fvalue = { "" }; 00474 int default_mbfunc = {0}; // функция по умолчанию, для вычисления RegID 00475 00476 std::shared_ptr<SMInterface> shm; 00477 00478 virtual void sysCommand( const uniset::SystemMessage* msg ) override; 00479 virtual void sensorInfo( const uniset::SensorMessage* sm ) override; 00480 void askSensors( UniversalIO::UIOCommand cmd ); 00481 void waitSMReady(); 00482 virtual void execute_rtu(); 00483 virtual void execute_tcp(); 00484 virtual void updateStatistics(); 00485 virtual void updateTCPStatistics(); 00486 virtual void updateThresholds(); 00487 virtual void postReceiveEvent( ModbusRTU::mbErrCode res ); 00488 00489 virtual bool activateObject() override; 00490 virtual bool deactivateObject() override; 00491 00492 // действия при завершении работы 00493 virtual void sigterm( int signo ) override; 00494 virtual void finalThread(); 00495 00496 virtual void initIterators(); 00497 bool initItem( UniXML::iterator& it ); 00498 bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec ); 00499 00500 void readConfiguration(); 00501 bool check_item( UniXML::iterator& it ); 00502 00503 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData val, const int fn = 0 ); 00504 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, size_t& i, size_t count, const int fn = 0 ); 00505 ModbusRTU::mbErrCode real_read( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData& val, const int fn = 0 ); 00506 ModbusRTU::mbErrCode much_real_read( RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 ); 00507 ModbusRTU::mbErrCode much_real_write(RegMap& rmap, const ModbusRTU::ModbusData regOKOK, ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 ); 00508 00509 ModbusRTU::mbErrCode real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val ); 00510 ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val ); 00511 ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val ); 00512 00513 ModbusRTU::mbErrCode real_write_it(RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData* dat, size_t& i, size_t count ); 00514 ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val ); 00515 ModbusRTU::mbErrCode real_write_prop(IOProperty* p, ModbusRTU::ModbusData* dat, size_t& i, size_t count ); 00516 00517 MBSlave(); 00518 timeout_t initPause = { 3000 }; 00519 uniset::uniset_rwmutex mutex_start; 00520 std::shared_ptr< ThreadCreator<MBSlave> > thr; 00521 00522 std::mutex mutexStartNotify; 00523 std::condition_variable startNotifyEvent; 00524 00525 PassiveTimer ptHeartBeat; 00526 uniset::ObjectId sidHeartBeat = { uniset::DefaultObjectId }; 00527 long maxHeartBeat = { 10 }; 00528 IOController::IOStateList::iterator itHeartBeat; 00529 uniset::ObjectId test_id = { uniset::DefaultObjectId }; 00530 00531 IOController::IOStateList::iterator itAskCount; 00532 uniset::ObjectId askcount_id = { uniset::DefaultObjectId }; 00533 00534 IOController::IOStateList::iterator itRespond; 00535 uniset::ObjectId respond_id = { uniset::DefaultObjectId }; 00536 bool respond_invert = { false }; 00537 00538 PassiveTimer ptTimeout; 00539 long askCount = { 0 }; 00540 00541 std::atomic_bool activated = { false }; 00542 std::atomic_bool cancelled = { false }; 00543 timeout_t activateTimeout = { 20000 }; // msec 00544 bool pingOK = { false }; 00545 timeout_t wait_msec = { 3000 }; 00546 bool force = { false }; 00548 bool mbregFromID = {0}; 00549 bool checkMBFunc = {0}; 00550 bool noMBFuncOptimize = {0}; // флаг отключающий принудительное преобразование функций (0x06->0x10, 0x05->0x0F) см. initItem() 00551 00552 int getOptimizeWriteFunction( const int fn ); // функция возвращает оптимизированную функцию (если оптимизация включена) 00553 00554 typedef std::unordered_map<int, std::string> FileList; 00555 FileList flist; 00556 std::string prefix = { "" }; 00557 std::string prop_prefix = { "" }; 00558 00559 ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET / 2 + 1]; 00561 // данные для ответа на запрос 0x2B(43)/0x0E(14) 00562 // 'MEI' - modbus encapsulated interface 00563 // 'RDI' - read device identification 00564 typedef std::unordered_map<int, std::string> MEIValMap; 00565 typedef std::unordered_map<int, MEIValMap> MEIObjIDMap; 00566 typedef std::unordered_map<int, MEIObjIDMap> MEIDevIDMap; 00567 00568 MEIDevIDMap meidev; 00569 00570 std::shared_ptr<LogAgregator> loga; 00571 std::shared_ptr<DebugStream> mblog; 00572 std::shared_ptr<LogServer> logserv; 00573 std::string logserv_host = {""}; 00574 int logserv_port = {0}; 00575 VMonitor vmon; 00576 std::string mbtype = { "" }; 00577 00578 // ---------------------------------------------------------------------------- 00579 // TCPServer section.. 00580 void initTCPClients( UniXML::iterator confnode ); 00581 00582 timeout_t sessTimeout = { 2000 }; 00583 timeout_t updateStatTime = { 4000 }; 00584 ModbusTCPServer::Sessions sess; 00585 std::mutex sessMutex; 00586 size_t sessMaxNum = { 5 }; 00587 std::shared_ptr<ModbusTCPServerSlot> tcpserver; 00588 00589 struct ClientInfo 00590 { 00591 ClientInfo(): iaddr(""), respond_s(uniset::DefaultObjectId), invert(false), 00592 askCount(0), askcount_s(uniset::DefaultObjectId) 00593 { 00594 ptTimeout.setTiming(0); 00595 } 00596 00597 std::string iaddr = { "" }; 00598 00599 uniset::ObjectId respond_s = { uniset::DefaultObjectId }; 00600 IOController::IOStateList::iterator respond_it; 00601 bool invert = { false }; 00602 PassiveTimer ptTimeout; 00603 timeout_t tout = { 2000 }; 00604 00605 long askCount = { 0 }; 00606 uniset::ObjectId askcount_s = { uniset::DefaultObjectId }; 00607 IOController::IOStateList::iterator askcount_it; 00608 00609 inline void initIterators( const std::shared_ptr<SMInterface>& shm ) 00610 { 00611 shm->initIterator( respond_it ); 00612 shm->initIterator( askcount_it ); 00613 } 00614 00615 const std::string getShortInfo() const; 00616 }; 00617 00618 typedef std::unordered_map<std::string, ClientInfo> ClientsMap; 00619 ClientsMap cmap; 00620 00621 uniset::ObjectId sesscount_id = { uniset::DefaultObjectId }; 00622 IOController::IOStateList::iterator sesscount_it; 00623 00624 std::atomic_bool tcpCancelled = { true }; 00625 }; 00626 // -------------------------------------------------------------------------- 00627 } // end of namespace uniset 00628 // ----------------------------------------------------------------------------- 00629 #endif // _MBSlave_H_ 00630 // -----------------------------------------------------------------------------
1.7.6.1