UniSet @VERSION@
extensions/ModbusSlave/MBSlave.h
1/*
2 * Copyright (c) 2015 Pavel Vainerman.
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License as
6 * published by the Free Software Foundation, version 2.1.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Lesser Public License for more details.
12 *
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16// -----------------------------------------------------------------------------
17#ifndef _MBSlave_H_
18#define _MBSlave_H_
19// -----------------------------------------------------------------------------
20#include <ostream>
21#include <string>
22#include <memory>
23#include <map>
24#include <unordered_map>
25#include <vector>
26#include <condition_variable>
27#include <atomic>
28#include <mutex>
29#include "UniSetObject.h"
30#include "modbus/ModbusTypes.h"
31#include "modbus/ModbusServerSlot.h"
32#include "modbus/ModbusTCPServer.h"
33#include "modbus/ModbusTCPServerSlot.h"
34#include "PassiveTimer.h"
35#include "Trigger.h"
36#include "Mutex.h"
37#include "SMInterface.h"
38#include "SharedMemory.h"
39#include "IOBase.h"
40#include "VTypes.h"
41#include "ThreadCreator.h"
42#include "LogServer.h"
43#include "LogAgregator.h"
44#include "VMonitor.h"
45#include "USingleProcess.h"
46// -----------------------------------------------------------------------------
47#ifndef vmonit
48#define vmonit( var ) vmon.add( #var, var )
49#endif
50// -------------------------------------------------------------------------
51namespace uniset
52{
53 // -----------------------------------------------------------------------------
314 // -----------------------------------------------------------------------------
316 class MBSlave:
317 private USingleProcess,
318 public UniSetObject
319 {
320 public:
321 MBSlave( uniset::ObjectId objId, uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr, const std::string& prefix = "mbs" );
322 virtual ~MBSlave();
323
325 static std::shared_ptr<MBSlave> init_mbslave(int argc, const char* const* argv,
326 uniset::ObjectId shmID, const std::shared_ptr<SharedMemory>& ic = nullptr,
327 const std::string& prefix = "mbs" );
328
329 static void help_print( int argc, const char* const* argv );
330
331 static const int NoSafetyState = -1;
332
333 enum AccessMode
334 {
335 amRW,
336 amRO,
337 amWO
338 };
339
340 std::string amode2str( AccessMode m );
341
342 struct BitRegProperty;
343
345 public IOBase
346 {
347 ModbusRTU::ModbusData mbreg;
348 AccessMode amode;
349 VTypes::VType vtype;
350 size_t wnum;
351 size_t nbyte;
352 std::shared_ptr<BitRegProperty> bitreg;
353 ModbusRTU::RegID regID;
354
355 IOProperty():
356 mbreg(0),
357 amode(amRW),
358 vtype(VTypes::vtUnknown),
359 wnum(0),
360 nbyte(0),
361 regID(0)
362 {}
363
364 friend std::ostream& operator<<( std::ostream& os, IOProperty& p );
365 };
366
367
369 {
370 typedef std::vector<IOProperty> BitSensorMap;
371
372 ModbusRTU::ModbusData mbreg;
373 BitSensorMap bvec;
374
375 BitRegProperty(): mbreg(0), bvec(ModbusRTU::BitsPerData) {}
376
378 bool check( const IOController_i::SensorInfo& si );
379
380 friend std::ostream& operator<<( std::ostream& os, BitRegProperty& p );
381 friend std::ostream& operator<<( std::ostream& os, BitRegProperty* p );
382 };
383
384 inline long getConnCount()
385 {
386 return connCount;
387 }
388
389 inline std::shared_ptr<LogAgregator> getLogAggregator()
390 {
391 return loga;
392 }
393 inline std::shared_ptr<DebugStream> log()
394 {
395 return mblog;
396 }
397
398 virtual uniset::SimpleInfo* getInfo( const char* userparam = 0 ) override;
399
400#ifndef DISABLE_REST_API
401 // http API
402 virtual Poco::JSON::Object::Ptr httpHelp( const Poco::URI::QueryParameters& p ) override;
403 virtual Poco::JSON::Object::Ptr httpRequest( const UHttp::HttpRequestContext& ctx ) override;
404 virtual Poco::JSON::Object::Ptr httpGetMyInfo( Poco::JSON::Object::Ptr root ) override;
405#endif
406
407 protected:
408
410 ModbusRTU::mbErrCode readCoilStatus( const ModbusRTU::ReadCoilMessage& query,
411 ModbusRTU::ReadCoilRetMessage& reply );
413 ModbusRTU::mbErrCode readInputStatus( const ModbusRTU::ReadInputStatusMessage& query,
414 ModbusRTU::ReadInputStatusRetMessage& reply );
415
417 ModbusRTU::mbErrCode readOutputRegisters( const ModbusRTU::ReadOutputMessage& query,
418 ModbusRTU::ReadOutputRetMessage& reply );
419
421 ModbusRTU::mbErrCode readInputRegisters( const ModbusRTU::ReadInputMessage& query,
422 ModbusRTU::ReadInputRetMessage& reply );
423
425 ModbusRTU::mbErrCode forceSingleCoil( const ModbusRTU::ForceSingleCoilMessage& query,
426 ModbusRTU::ForceSingleCoilRetMessage& reply );
427
429 ModbusRTU::mbErrCode forceMultipleCoils( const ModbusRTU::ForceCoilsMessage& query,
430 ModbusRTU::ForceCoilsRetMessage& reply );
431
432
434 ModbusRTU::mbErrCode writeOutputRegisters( const ModbusRTU::WriteOutputMessage& query,
435 ModbusRTU::WriteOutputRetMessage& reply );
436
438 ModbusRTU::mbErrCode writeOutputSingleRegister( const ModbusRTU::WriteSingleOutputMessage& query,
439 ModbusRTU::WriteSingleOutputRetMessage& reply );
440
442 // ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
443 // ModbusRTU::JournalCommandRetMessage& reply );
444
446 ModbusRTU::mbErrCode setDateTime( const ModbusRTU::SetDateTimeMessage& query,
447 ModbusRTU::SetDateTimeRetMessage& reply );
448
450 ModbusRTU::mbErrCode remoteService( const ModbusRTU::RemoteServiceMessage& query,
451 ModbusRTU::RemoteServiceRetMessage& reply );
452
453 ModbusRTU::mbErrCode fileTransfer( const ModbusRTU::FileTransferMessage& query,
454 ModbusRTU::FileTransferRetMessage& reply );
455
456 ModbusRTU::mbErrCode diagnostics( const ModbusRTU::DiagnosticMessage& query,
457 ModbusRTU::DiagnosticRetMessage& reply );
458
459 ModbusRTU::mbErrCode read4314( const ModbusRTU::MEIMessageRDI& query,
460 ModbusRTU::MEIMessageRetRDI& reply );
461
462 // т.к. в функциях (much_real_read,nuch_real_write) расчёт на отсортированность IOMap
463 // то использовать unordered_map нельзя
464 typedef std::map<ModbusRTU::RegID, IOProperty> RegMap;
465
466 typedef std::unordered_map<ModbusRTU::ModbusAddr, RegMap> IOMap;
467
468 IOMap iomap;
470 // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
471 // и отдельно его проверяем потом
472 typedef std::list<IOBase> ThresholdList;
473 ThresholdList thrlist;
474
475 std::shared_ptr<ModbusServerSlot> mbslot;
476 std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
477 std::string default_mbaddr = { "" };
478 ModbusRTU::ModbusAddr myaddr = { ModbusRTU::BroadcastAddr }; // default
479
480 xmlNode* cnode = { 0 };
481 std::string s_field = { "" };
482 std::string s_fvalue = { "" };
483 int default_mbfunc = {0}; // функция по умолчанию, для вычисления RegID
484
485 std::shared_ptr<SMInterface> shm;
486
487 virtual void sysCommand( const uniset::SystemMessage* msg ) override;
488 virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
489 virtual void timerInfo( const uniset::TimerMessage* tm ) override;
490 void askSensors( UniversalIO::UIOCommand cmd );
491 bool waitSMReady();
492 virtual void execute_rtu();
493 virtual void execute_tcp();
494 virtual void updateStatistics();
495 virtual void updateTCPStatistics();
496 virtual void updateThresholds();
497 virtual void postReceiveEvent( ModbusRTU::mbErrCode res );
498 void runTCPServer();
499
500 virtual bool activateObject() override;
501 virtual bool deactivateObject() override;
502
503 // действия при завершении работы
504 virtual void finalThread();
505
506 enum Timer
507 {
508 tmCheckExchange
509 };
510
511 uniset::timeout_t checkExchangeTime = { 10000 }; // контроль "живости" потока обмена, мсек
512
513 virtual void initIterators();
514 bool initItem( UniXML::iterator& it );
515 bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
516
517 void readConfiguration();
518 bool check_item( UniXML::iterator& it );
519
520 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val, const int fn = 0 );
521 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regK, const ModbusRTU::ModbusData* dat, size_t& i, size_t count, const int fn = 0 );
522 ModbusRTU::mbErrCode real_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val, const int fn = 0 );
523 ModbusRTU::mbErrCode much_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 );
524 ModbusRTU::mbErrCode much_write(RegMap& rmap, const ModbusRTU::ModbusData reg, const ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 );
525 ModbusRTU::mbErrCode bits_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::BitsBuffer* dat, size_t count, const int fn = 0 );
526
527 ModbusRTU::mbErrCode real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val );
528 ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val );
529 ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val );
530
531 ModbusRTU::mbErrCode real_write_it(RegMap& rmap, RegMap::iterator& it, const ModbusRTU::ModbusData* dat, size_t& i, size_t count );
532 ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val );
533 ModbusRTU::mbErrCode real_write_prop(IOProperty* p, const ModbusRTU::ModbusData* dat, size_t& i, size_t count );
534
535#ifndef DISABLE_REST_API
536 // http api
537 Poco::JSON::Object::Ptr httpGetParam( const Poco::URI::QueryParameters& p );
538 Poco::JSON::Object::Ptr httpSetParam( const Poco::URI::QueryParameters& p );
539 Poco::JSON::Object::Ptr httpStatus();
540 Poco::JSON::Object::Ptr httpGet( const Poco::URI::QueryParameters& p );
541 Poco::JSON::Object::Ptr httpRegisters( const Poco::URI::QueryParameters& p );
542
543 bool httpEnabledSetParams = { false };
544#endif
545 MBSlave();
546 timeout_t initPause = { 3000 };
547 uniset::uniset_rwmutex mutex_start;
548 std::unique_ptr< ThreadCreator<MBSlave> > thr;
549
550 std::mutex mutexStartNotify;
551 std::condition_variable startNotifyEvent;
552
553 PassiveTimer ptHeartBeat;
554 uniset::ObjectId sidHeartBeat = { uniset::DefaultObjectId };
555 long maxHeartBeat = { 10 };
556 IOController::IOStateList::iterator itHeartBeat;
557 uniset::ObjectId sidTestSMReady = {uniset::DefaultObjectId };
558
559 IOController::IOStateList::iterator itAskCount;
561
562 IOController::IOStateList::iterator itRespond;
564 bool respond_invert = { false };
565
566 PassiveTimer ptTimeout;
567 long connCount = { 0 };
568 long restartTCPServerCount = { 0 };
569
570 std::atomic_bool activated = { false };
571 std::atomic_bool canceled = {false };
572 timeout_t activateTimeout = { 20000 }; // msec
573 bool smPingOK = { false };
574 timeout_t wait_msec = { 3000 };
575 bool force = { false };
577 bool mbregFromID = {0};
578 bool checkMBFunc = {0};
579 bool noMBFuncOptimize = {0}; // флаг отключающий принудительное преобразование функций (0x06->0x10, 0x05->0x0F) см. initItem()
580
581 int getOptimizeWriteFunction( const int fn ); // функция возвращает оптимизированную функцию (если оптимизация включена)
582
583 typedef std::unordered_map<int, std::string> FileList;
584 FileList flist;
585 std::string prefix = { "" };
586 std::string prop_prefix = { "" };
587
588 ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET / 2 + 1];
590 // данные для ответа на запрос 0x2B(43)/0x0E(14)
591 // 'MEI' - modbus encapsulated interface
592 // 'RDI' - read device identification
593 typedef std::unordered_map<int, std::string> MEIValMap;
594 typedef std::unordered_map<int, MEIValMap> MEIObjIDMap;
595 typedef std::unordered_map<int, MEIObjIDMap> MEIDevIDMap;
596
597 MEIDevIDMap meidev;
598
599 std::shared_ptr<LogAgregator> loga;
600 std::shared_ptr<DebugStream> mblog;
601 std::shared_ptr<LogServer> logserv;
602 std::string logserv_host = {""};
603 int logserv_port = {0};
604 VMonitor vmon;
605 std::string mbtype = { "" };
606
607 // ----------------------------------------------------------------------------
608 // TCPServer section..
609 void initTCPClients( UniXML::iterator confnode );
610
611 timeout_t sockTimeout = { 30000 };
612 timeout_t sessTimeout = { 2000 };
613 timeout_t updateStatTime = { 4000 };
614 ModbusTCPServer::Sessions sess;
615 std::mutex sessMutex;
616 size_t sessMaxNum = { 5 };
617 std::shared_ptr<ModbusTCPServerSlot> tcpserver;
618
620 {
621 ClientInfo(): iaddr(""), respond_s(uniset::DefaultObjectId), invert(false),
622 askCount(0), askcount_s(uniset::DefaultObjectId)
623 {
624 ptTimeout.setTiming(0);
625 }
626
627 std::string iaddr = { "" };
628
630 IOController::IOStateList::iterator respond_it;
631 bool invert = { false };
632 PassiveTimer ptTimeout;
633 timeout_t tout = { 2000 };
634
635 long askCount = { 0 };
637 IOController::IOStateList::iterator askcount_it;
638
639 inline void initIterators( const std::shared_ptr<SMInterface>& shm )
640 {
641 shm->initIterator( respond_it );
642 shm->initIterator( askcount_it );
643 }
644
645 const std::string getShortInfo() const;
646 };
647
648 typedef std::unordered_map<std::string, ClientInfo> ClientsMap;
649 ClientsMap cmap;
650
651 uniset::ObjectId sesscount_id = { uniset::DefaultObjectId };
652 IOController::IOStateList::iterator sesscount_it;
653
654 std::atomic_bool tcpCancelled = { true };
655
656 bool tcpBreakIfFailRun = { false };
657 timeout_t tcpRepeatCreateSocketPause = { 30000 };
658 };
659 // --------------------------------------------------------------------------
660} // end of namespace uniset
661// -----------------------------------------------------------------------------
662#endif // _MBSlave_H_
663// -----------------------------------------------------------------------------
Definition Utilities/MBTester/MBSlave.h:14
Definition extensions/ModbusSlave/MBSlave.h:319
virtual bool activateObject() override
Активизация объекта (переопределяется для необходимых действий после активизации)
Definition extensions/ModbusSlave/MBSlave.cc:1260
IOMap iomap
Definition extensions/ModbusSlave/MBSlave.h:468
ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET/2+1]
Definition extensions/ModbusSlave/MBSlave.h:588
ModbusRTU::mbErrCode readOutputRegisters(const ModbusRTU::ReadOutputMessage &query, ModbusRTU::ReadOutputRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:1825
ModbusRTU::mbErrCode forceSingleCoil(const ModbusRTU::ForceSingleCoilMessage &query, ModbusRTU::ForceSingleCoilRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3380
ModbusTCPServer::Sessions sess
Definition extensions/ModbusSlave/MBSlave.h:614
ModbusRTU::mbErrCode writeOutputRegisters(const ModbusRTU::WriteOutputMessage &query, ModbusRTU::WriteOutputRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:1870
ModbusRTU::mbErrCode writeOutputSingleRegister(const ModbusRTU::WriteSingleOutputMessage &query, ModbusRTU::WriteSingleOutputRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:1894
ModbusRTU::mbErrCode remoteService(const ModbusRTU::RemoteServiceMessage &query, ModbusRTU::RemoteServiceRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3181
ModbusRTU::mbErrCode readInputRegisters(const ModbusRTU::ReadInputMessage &query, ModbusRTU::ReadInputRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3131
ModbusRTU::mbErrCode setDateTime(const ModbusRTU::SetDateTimeMessage &query, ModbusRTU::SetDateTimeRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3175
timeout_t sessTimeout
Definition extensions/ModbusSlave/MBSlave.h:612
virtual bool deactivateObject() override
Деактивация объекта (переопределяется для необходимых действий при завершении работы)
Definition extensions/ModbusSlave/MBSlave.cc:1277
ModbusRTU::mbErrCode readCoilStatus(const ModbusRTU::ReadCoilMessage &query, ModbusRTU::ReadCoilRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3202
std::unordered_set< ModbusRTU::ModbusAddr > vaddr
Definition extensions/ModbusSlave/MBSlave.h:476
static std::shared_ptr< MBSlave > init_mbslave(int argc, const char *const *argv, uniset::ObjectId shmID, const std::shared_ptr< SharedMemory > &ic=nullptr, const std::string &prefix="mbs")
Definition extensions/ModbusSlave/MBSlave.cc:1762
bool force
Definition extensions/ModbusSlave/MBSlave.h:575
ModbusRTU::mbErrCode forceMultipleCoils(const ModbusRTU::ForceCoilsMessage &query, ModbusRTU::ForceCoilsRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3342
ModbusRTU::mbErrCode readInputStatus(const ModbusRTU::ReadInputStatusMessage &query, ModbusRTU::ReadInputStatusRetMessage &reply)
Definition extensions/ModbusSlave/MBSlave.cc:3272
timeout_t sockTimeout
Definition extensions/ModbusSlave/MBSlave.h:611
Пассивный таймер
Definition PassiveTimer.h:94
Definition MessageType.h:127
Definition MessageType.h:171
Definition MessageType.h:214
Definition USingleProcess.h:28
Definition UniSetObject.h:80
Definition Mutex.h:32
Definition AccessConfig.h:30
const ObjectId DefaultObjectId
Definition UniSetTypes.h:71
long ObjectId
Definition UniSetTypes_i.idl:30
Definition IOController_i.idl:64
Definition IOBase.h:35
Definition extensions/ModbusSlave/MBSlave.h:369
ModbusRTU::ModbusData mbreg
Definition extensions/ModbusSlave/MBSlave.h:372
bool check(const IOController_i::SensorInfo &si)
Definition extensions/ModbusSlave/MBSlave.cc:1616
Definition extensions/ModbusSlave/MBSlave.h:620
Definition extensions/ModbusSlave/MBSlave.h:346
size_t wnum
Definition extensions/ModbusSlave/MBSlave.h:350
ModbusRTU::ModbusData mbreg
Definition extensions/ModbusSlave/MBSlave.h:347
std::shared_ptr< BitRegProperty > bitreg
Definition extensions/ModbusSlave/MBSlave.h:352
VTypes::VType vtype
Definition extensions/ModbusSlave/MBSlave.h:349
size_t nbyte
Definition extensions/ModbusSlave/MBSlave.h:351
Definition UniSetTypes_i.idl:65