UniSet 2.41.2
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
344 struct IOProperty:
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
368 struct BitRegProperty
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 std::string& req, const Poco::URI::QueryParameters& p ) override;
404#endif
405
406 protected:
407
409 ModbusRTU::mbErrCode readCoilStatus( const ModbusRTU::ReadCoilMessage& query,
410 ModbusRTU::ReadCoilRetMessage& reply );
412 ModbusRTU::mbErrCode readInputStatus( const ModbusRTU::ReadInputStatusMessage& query,
413 ModbusRTU::ReadInputStatusRetMessage& reply );
414
416 ModbusRTU::mbErrCode readOutputRegisters( const ModbusRTU::ReadOutputMessage& query,
417 ModbusRTU::ReadOutputRetMessage& reply );
418
420 ModbusRTU::mbErrCode readInputRegisters( const ModbusRTU::ReadInputMessage& query,
421 ModbusRTU::ReadInputRetMessage& reply );
422
424 ModbusRTU::mbErrCode forceSingleCoil( const ModbusRTU::ForceSingleCoilMessage& query,
425 ModbusRTU::ForceSingleCoilRetMessage& reply );
426
428 ModbusRTU::mbErrCode forceMultipleCoils( const ModbusRTU::ForceCoilsMessage& query,
429 ModbusRTU::ForceCoilsRetMessage& reply );
430
431
433 ModbusRTU::mbErrCode writeOutputRegisters( const ModbusRTU::WriteOutputMessage& query,
434 ModbusRTU::WriteOutputRetMessage& reply );
435
437 ModbusRTU::mbErrCode writeOutputSingleRegister( const ModbusRTU::WriteSingleOutputMessage& query,
438 ModbusRTU::WriteSingleOutputRetMessage& reply );
439
441 // ModbusRTU::mbErrCode journalCommand( ModbusRTU::JournalCommandMessage& query,
442 // ModbusRTU::JournalCommandRetMessage& reply );
443
445 ModbusRTU::mbErrCode setDateTime( const ModbusRTU::SetDateTimeMessage& query,
446 ModbusRTU::SetDateTimeRetMessage& reply );
447
449 ModbusRTU::mbErrCode remoteService( const ModbusRTU::RemoteServiceMessage& query,
450 ModbusRTU::RemoteServiceRetMessage& reply );
451
452 ModbusRTU::mbErrCode fileTransfer( const ModbusRTU::FileTransferMessage& query,
453 ModbusRTU::FileTransferRetMessage& reply );
454
455 ModbusRTU::mbErrCode diagnostics( const ModbusRTU::DiagnosticMessage& query,
456 ModbusRTU::DiagnosticRetMessage& reply );
457
458 ModbusRTU::mbErrCode read4314( const ModbusRTU::MEIMessageRDI& query,
459 ModbusRTU::MEIMessageRetRDI& reply );
460
461 // т.к. в функциях (much_real_read,nuch_real_write) расчёт на отсортированность IOMap
462 // то использовать unordered_map нельзя
463 typedef std::map<ModbusRTU::RegID, IOProperty> RegMap;
464
465 typedef std::unordered_map<ModbusRTU::ModbusAddr, RegMap> IOMap;
466
467 IOMap iomap;
468
469 // т.к. пороговые датчики не связаны напрямую с обменом, создаём для них отдельный список
470 // и отдельно его проверяем потом
471 typedef std::list<IOBase> ThresholdList;
472 ThresholdList thrlist;
473
474 std::shared_ptr<ModbusServerSlot> mbslot;
475 std::unordered_set<ModbusRTU::ModbusAddr> vaddr;
476 std::string default_mbaddr = { "" };
477
478 xmlNode* cnode = { 0 };
479 std::string s_field = { "" };
480 std::string s_fvalue = { "" };
481 int default_mbfunc = {0}; // функция по умолчанию, для вычисления RegID
482
483 std::shared_ptr<SMInterface> shm;
484
485 virtual void sysCommand( const uniset::SystemMessage* msg ) override;
486 virtual void sensorInfo( const uniset::SensorMessage* sm ) override;
487 virtual void timerInfo( const uniset::TimerMessage* tm ) override;
488 void askSensors( UniversalIO::UIOCommand cmd );
489 bool waitSMReady();
490 virtual void execute_rtu();
491 virtual void execute_tcp();
492 virtual void updateStatistics();
493 virtual void updateTCPStatistics();
494 virtual void updateThresholds();
495 virtual void postReceiveEvent( ModbusRTU::mbErrCode res );
496 void runTCPServer();
497
498 virtual bool activateObject() override;
499 virtual bool deactivateObject() override;
500
501 // действия при завершении работы
502 virtual void finalThread();
503
504 enum Timer
505 {
506 tmCheckExchange
507 };
508
509 uniset::timeout_t checkExchangeTime = { 10000 }; // контроль "живости" потока обмена, мсек
510
511 virtual void initIterators();
512 bool initItem( UniXML::iterator& it );
513 bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
514
515 void readConfiguration();
516 bool check_item( UniXML::iterator& it );
517
518 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData val, const int fn = 0 );
519 ModbusRTU::mbErrCode real_write( RegMap& rmap, const ModbusRTU::ModbusData regK, const ModbusRTU::ModbusData* dat, size_t& i, size_t count, const int fn = 0 );
520 ModbusRTU::mbErrCode real_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData& val, const int fn = 0 );
521 ModbusRTU::mbErrCode much_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 );
522 ModbusRTU::mbErrCode much_write(RegMap& rmap, const ModbusRTU::ModbusData reg, const ModbusRTU::ModbusData* dat, size_t count, const int fn = 0 );
523 ModbusRTU::mbErrCode bits_read( RegMap& rmap, const ModbusRTU::ModbusData reg, ModbusRTU::BitsBuffer* dat, size_t count, const int fn = 0 );
524
525 ModbusRTU::mbErrCode real_read_it( RegMap& rmap, RegMap::iterator& it, ModbusRTU::ModbusData& val );
526 ModbusRTU::mbErrCode real_bitreg_read_it( std::shared_ptr<BitRegProperty>& bp, ModbusRTU::ModbusData& val );
527 ModbusRTU::mbErrCode real_read_prop( IOProperty* p, ModbusRTU::ModbusData& val );
528
529 ModbusRTU::mbErrCode real_write_it(RegMap& rmap, RegMap::iterator& it, const ModbusRTU::ModbusData* dat, size_t& i, size_t count );
530 ModbusRTU::mbErrCode real_bitreg_write_it( std::shared_ptr<BitRegProperty>& bp, const ModbusRTU::ModbusData val );
531 ModbusRTU::mbErrCode real_write_prop(IOProperty* p, const ModbusRTU::ModbusData* dat, size_t& i, size_t count );
532
533#ifndef DISABLE_REST_API
534 // http api
535 Poco::JSON::Object::Ptr request_regs( const std::string& req, const Poco::URI::QueryParameters& p );
536 Poco::JSON::Object::Ptr get_regs(ModbusRTU::ModbusAddr addr, const RegMap& rmap, const std::vector<std::string>& q_regs );
537 Poco::JSON::Object::Ptr get_reginfo( const IOProperty& prop );
538
539 // params API
540 Poco::JSON::Object::Ptr httpGetParam( const Poco::URI::QueryParameters& p );
541 Poco::JSON::Object::Ptr httpSetParam( const Poco::URI::QueryParameters& p );
542 Poco::JSON::Object::Ptr httpStatus();
543
544 bool httpEnabledSetParams = { false };
545#endif
546 MBSlave();
547 timeout_t initPause = { 3000 };
548 uniset::uniset_rwmutex mutex_start;
549 std::unique_ptr< ThreadCreator<MBSlave> > thr;
550
551 std::mutex mutexStartNotify;
552 std::condition_variable startNotifyEvent;
553
554 PassiveTimer ptHeartBeat;
555 uniset::ObjectId sidHeartBeat = { uniset::DefaultObjectId };
556 long maxHeartBeat = { 10 };
557 IOController::IOStateList::iterator itHeartBeat;
558 uniset::ObjectId sidTestSMReady = {uniset::DefaultObjectId };
559
560 IOController::IOStateList::iterator itAskCount;
562
563 IOController::IOStateList::iterator itRespond;
565 bool respond_invert = { false };
566
567 PassiveTimer ptTimeout;
568 long connCount = { 0 };
569 long restartTCPServerCount = { 0 };
570
571 std::atomic_bool activated = { false };
572 std::atomic_bool canceled = {false };
573 timeout_t activateTimeout = { 20000 }; // msec
574 bool smPingOK = { false };
575 timeout_t wait_msec = { 3000 };
576 bool force = { false };
577
578 bool mbregFromID = {0};
579 bool checkMBFunc = {0};
580 bool noMBFuncOptimize = {0}; // флаг отключающий принудительное преобразование функций (0x06->0x10, 0x05->0x0F) см. initItem()
581
582 int getOptimizeWriteFunction( const int fn ); // функция возвращает оптимизированную функцию (если оптимизация включена)
583
584 typedef std::unordered_map<int, std::string> FileList;
585 FileList flist;
586 std::string prefix = { "" };
587 std::string prop_prefix = { "" };
588
589 ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET / 2 + 1];
590
591 // данные для ответа на запрос 0x2B(43)/0x0E(14)
592 // 'MEI' - modbus encapsulated interface
593 // 'RDI' - read device identification
594 typedef std::unordered_map<int, std::string> MEIValMap;
595 typedef std::unordered_map<int, MEIValMap> MEIObjIDMap;
596 typedef std::unordered_map<int, MEIObjIDMap> MEIDevIDMap;
597
598 MEIDevIDMap meidev;
599
600 std::shared_ptr<LogAgregator> loga;
601 std::shared_ptr<DebugStream> mblog;
602 std::shared_ptr<LogServer> logserv;
603 std::string logserv_host = {""};
604 int logserv_port = {0};
605 VMonitor vmon;
606 std::string mbtype = { "" };
607
608 // ----------------------------------------------------------------------------
609 // TCPServer section..
610 void initTCPClients( UniXML::iterator confnode );
611
612 timeout_t sockTimeout = { 30000 };
613 timeout_t sessTimeout = { 2000 };
614 timeout_t updateStatTime = { 4000 };
615 ModbusTCPServer::Sessions sess;
616 std::mutex sessMutex;
617 size_t sessMaxNum = { 5 };
618 std::shared_ptr<ModbusTCPServerSlot> tcpserver;
619
620 struct ClientInfo
621 {
622 ClientInfo(): iaddr(""), respond_s(uniset::DefaultObjectId), invert(false),
623 askCount(0), askcount_s(uniset::DefaultObjectId)
624 {
625 ptTimeout.setTiming(0);
626 }
627
628 std::string iaddr = { "" };
629
631 IOController::IOStateList::iterator respond_it;
632 bool invert = { false };
633 PassiveTimer ptTimeout;
634 timeout_t tout = { 2000 };
635
636 long askCount = { 0 };
638 IOController::IOStateList::iterator askcount_it;
639
640 inline void initIterators( const std::shared_ptr<SMInterface>& shm )
641 {
642 shm->initIterator( respond_it );
643 shm->initIterator( askcount_it );
644 }
645
646 const std::string getShortInfo() const;
647 };
648
649 typedef std::unordered_map<std::string, ClientInfo> ClientsMap;
650 ClientsMap cmap;
651
652 uniset::ObjectId sesscount_id = { uniset::DefaultObjectId };
653 IOController::IOStateList::iterator sesscount_it;
654
655 std::atomic_bool tcpCancelled = { true };
656
657 bool tcpBreakIfFailRun = { false };
658 timeout_t tcpRepeatCreateSocketPause = { 30000 };
659 };
660 // --------------------------------------------------------------------------
661} // end of namespace uniset
662// -----------------------------------------------------------------------------
663#endif // _MBSlave_H_
664// -----------------------------------------------------------------------------
virtual bool activateObject() override
Активизация объекта (переопределяется для необходимых действий после активизации).
Определения extensions/ModbusSlave/mbslave.cc:1156
IOMap iomap
Определения extensions/ModbusSlave/MBSlave.h:467
ModbusRTU::ModbusData buf[ModbusRTU::MAXLENPACKET/2+1]
Определения extensions/ModbusSlave/MBSlave.h:589
ModbusRTU::mbErrCode readOutputRegisters(const ModbusRTU::ReadOutputMessage &query, ModbusRTU::ReadOutputRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:1699
ModbusRTU::mbErrCode forceSingleCoil(const ModbusRTU::ForceSingleCoilMessage &query, ModbusRTU::ForceSingleCoilRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:3076
ModbusTCPServer::Sessions sess
Определения extensions/ModbusSlave/MBSlave.h:615
ModbusRTU::mbErrCode writeOutputRegisters(const ModbusRTU::WriteOutputMessage &query, ModbusRTU::WriteOutputRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:1744
ModbusRTU::mbErrCode writeOutputSingleRegister(const ModbusRTU::WriteSingleOutputMessage &query, ModbusRTU::WriteSingleOutputRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:1767
ModbusRTU::mbErrCode remoteService(const ModbusRTU::RemoteServiceMessage &query, ModbusRTU::RemoteServiceRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:2880
ModbusRTU::mbErrCode readInputRegisters(const ModbusRTU::ReadInputMessage &query, ModbusRTU::ReadInputRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:2831
ModbusRTU::mbErrCode setDateTime(const ModbusRTU::SetDateTimeMessage &query, ModbusRTU::SetDateTimeRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:2874
timeout_t sessTimeout
Определения extensions/ModbusSlave/MBSlave.h:613
virtual bool deactivateObject() override
Деактивация объекта (переопределяется для необходимых действий при завершении работы).
Определения extensions/ModbusSlave/mbslave.cc:1173
ModbusRTU::mbErrCode readCoilStatus(const ModbusRTU::ReadCoilMessage &query, ModbusRTU::ReadCoilRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:2901
std::unordered_set< ModbusRTU::ModbusAddr > vaddr
Определения extensions/ModbusSlave/MBSlave.h:475
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")
Определения extensions/ModbusSlave/mbslave.cc:1636
bool force
Определения extensions/ModbusSlave/MBSlave.h:576
ModbusRTU::mbErrCode forceMultipleCoils(const ModbusRTU::ForceCoilsMessage &query, ModbusRTU::ForceCoilsRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:3039
ModbusRTU::mbErrCode readInputStatus(const ModbusRTU::ReadInputStatusMessage &query, ModbusRTU::ReadInputStatusRetMessage &reply)
Определения extensions/ModbusSlave/mbslave.cc:2970
timeout_t sockTimeout
Определения extensions/ModbusSlave/MBSlave.h:612
Пассивный таймер
Определения PassiveTimer.h:94
UniSetObject(const std::string &name, const std::string &section)
Определения UniSetObject.cc:89
Определения Calibration.h:27
const ObjectId DefaultObjectId
Определения UniSetTypes.h:71
long ObjectId
Определения UniSetTypes_i.idl:30
Определения IOController_i.idl:64
Определения extensions/ModbusSlave/MBSlave.h:369
ModbusRTU::ModbusData mbreg
Определения extensions/ModbusSlave/MBSlave.h:372
bool check(const IOController_i::SensorInfo &si)
Определения extensions/ModbusSlave/mbslave.cc:1506
Определения extensions/ModbusSlave/MBSlave.h:346
size_t wnum
Определения extensions/ModbusSlave/MBSlave.h:350
ModbusRTU::ModbusData mbreg
Определения extensions/ModbusSlave/MBSlave.h:347
std::shared_ptr< BitRegProperty > bitreg
Определения extensions/ModbusSlave/MBSlave.h:352
VTypes::VType vtype
Определения extensions/ModbusSlave/MBSlave.h:349
size_t nbyte
Определения extensions/ModbusSlave/MBSlave.h:351