UniSet  2.24.2
UNetSender.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 UNetSender_H_
18 #define UNetSender_H_
19 // -----------------------------------------------------------------------------
20 #include <ostream>
21 #include <string>
22 #include <vector>
23 #include <limits>
24 #include <unordered_map>
25 #include "UniSetObject.h"
26 #include "Trigger.h"
27 #include "Mutex.h"
28 #include "SMInterface.h"
29 #include "SharedMemory.h"
30 #include "ThreadCreator.h"
31 #include "UDPPacket.h"
32 #include "UNetTransport.h"
33 // --------------------------------------------------------------------------
34 namespace uniset
35 {
36  // -----------------------------------------------------------------------------
37  /*
38  * Распределение датчиков по пакетам
39  * =========================================================================
40  * Все пересылаемые данные разбиваются на группы по частоте посылки("sendfactor").
41  * Частота посылки кратна sendpause, задаётся для каждого датчика, при помощи свойства prefix_sendfactor.
42  * Внутри каждой группы пакеты набираются по мере "заполнения".
43  *
44  * Добавление датчика в пакет и создание нового пакета при переполнении происходит в функции initItem().
45  * Причем так как дискретные и аналоговые датчики обрабатываются отдельно (но пересылаются в одном пакете),
46  * то датчики, которые первые переполнятся приводят к тому, что создаётся новый пакет и они добавляются в него,
47  * в свою очередь остальные продолжают "добивать" предыдущий пакет.
48  * В initItem() каждому UItem в dlist кроме pack_ind присваивается еще и номер пакета pack_num, который гарантировано соответствует
49  * существующему пакету, поэтому в дальнейшем при использовании pack_num в качестве ключа в mypacks мы не проверяем пакет на существование.
50  *
51  * Создание соединения
52  * ======================================
53  * Попытка создать соединение производиться сразу в конструкторе, если это не получается,
54  * то в потоке "посылки", с заданным периодом (checkConnectionTime) идёт попытка создать соединение..
55  * и так бесконечно, пока не получиться. Это важно для систем, где в момент загрузки программы
56  * (в момент создания объекта UNetSender) ещё может быть не поднята сеть или какой-то сбой с сетью и требуется
57  * ожидание (без вылета программы) пока "внешняя система мониторинга" не поднимет сеть).
58  * Если такая логика не требуется, то можно задать в конструкторе флаг nocheckconnection=true,
59  * тогда при создании объекта UNetSender, в конструкторе будет
60  * выкинуто исключение при неудачной попытке создания соединения.
61  * \warning setCheckConnectionPause(msec) должно быть кратно sendpause!
62  */
63  class UNetSender final
64  {
65  public:
66  UNetSender( std::unique_ptr<UNetSendTransport>&& transport, const std::shared_ptr<SMInterface>& smi
67  , bool nocheckConnection = false
68  , const std::string& s_field = ""
69  , const std::string& s_fvalue = ""
70  , const std::string& prop_prefix = "unet"
71  , const std::string& prefix = "unet"
72  , size_t maxDCount = UniSetUDP::MaxDCount
73  , size_t maxACount = UniSetUDP::MaxACount );
74 
75  ~UNetSender();
76 
77  typedef size_t sendfactor_t;
78 
79  static const long not_specified_value = { std::numeric_limits<long>::max() };
80 
81  struct UItem
82  {
83  UItem():
84  iotype(UniversalIO::UnknownIOType),
86  pack_num(0),
87  pack_ind(0),
88  pack_sendfactor(0) {}
89 
90  UniversalIO::IOType iotype;
92  IOController::IOStateList::iterator ioit;
93  size_t pack_num;
94  size_t pack_ind;
95  sendfactor_t pack_sendfactor = { 0 };
96  long undefined_value = { not_specified_value };
97  friend std::ostream& operator<<( std::ostream& os, UItem& p );
98  };
99 
100  typedef std::unordered_map<uniset::ObjectId, UItem> UItemMap;
101 
102  size_t getDataPackCount() const noexcept;
103 
104  void start();
105  void stop();
106 
107  void send() noexcept;
108 
109  struct PackMessage
110  {
111  PackMessage( uniset::UniSetUDP::UDPMessage&& m ) noexcept: msg(std::move(m)) {}
112  PackMessage( const uniset::UniSetUDP::UDPMessage& m ) = delete;
113 
114  PackMessage() noexcept {}
115 
118  };
119 
120  void real_send( PackMessage& mypack ) noexcept;
121 
123  void updateFromSM();
124 
126  void updateSensor( uniset::ObjectId id, long value );
127 
129  void updateItem( const UItem& it, long value );
130 
131  inline void setSendPause( int msec ) noexcept
132  {
133  sendpause = msec;
134  }
135  inline void setPackSendPause( int msec ) noexcept
136  {
137  packsendpause = msec;
138  }
139  inline void setPackSendPauseFactor( int factor ) noexcept
140  {
141  packsendpauseFactor = factor;
142  }
143 
144  void setCheckConnectionPause( int msec ) noexcept;
145 
147  void askSensors( UniversalIO::UIOCommand cmd );
148 
150  void initIterators() noexcept;
151 
152  inline std::shared_ptr<DebugStream> getLog() noexcept
153  {
154  return unetlog;
155  }
156 
157  std::string getShortInfo() const noexcept;
158 
159  inline size_t getADataSize() const noexcept
160  {
161  return maxAData;
162  }
163  inline size_t getDDataSize() const noexcept
164  {
165  return maxDData;
166  }
167 
168  protected:
169 
170  std::string s_field = { "" };
171  std::string s_fvalue = { "" };
172  std::string prop_prefix = { "" };
173 
174  const std::shared_ptr<SMInterface> shm;
175  std::shared_ptr<DebugStream> unetlog;
176 
177  bool initItem( UniXML::iterator& it );
178  bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
179 
180  void readConfiguration();
181 
182  bool createConnection( bool throwEx );
183 
184  private:
185  UNetSender();
186 
187  std::unique_ptr<UNetSendTransport> transport;
188 
189  std::string myname = { "" };
190  timeout_t sendpause = { 150 };
191  timeout_t packsendpause = { 5 };
192  int packsendpauseFactor = { 1 };
193  timeout_t writeTimeout = { 1000 }; // msec
194  std::atomic_bool activated = { false };
195  PassiveTimer ptCheckConnection;
196 
197  typedef std::unordered_map<sendfactor_t, std::vector<PackMessage>> Packs;
198 
199  // mypacks заполняется в начале и дальше с ним происходит только чтение
200  // (меняются данные внутри пакетов, но не меняется само количество пакетов)
201  // поэтому mutex-ом его не защищаем
202  Packs mypacks;
203  std::unordered_map<sendfactor_t, size_t> packs_anum;
204  std::unordered_map<sendfactor_t, size_t> packs_dnum;
205  UItemMap items;
206  size_t packetnum = { 1 };
208  size_t maxAData = { UniSetUDP::MaxACount };
209  size_t maxDData = { UniSetUDP::MaxDCount };
210 
211  std::unique_ptr< ThreadCreator<UNetSender> > s_thr; // send thread
212 
213  size_t ncycle = { 0 };
215  };
216  // --------------------------------------------------------------------------
217 } // end of namespace uniset
218 // -----------------------------------------------------------------------------
219 #endif // UNetSender_H_
220 // -----------------------------------------------------------------------------
Definition: DebugStream.h:62
Definition: UNetSender.h:64
void initIterators() noexcept
Definition: UNetSender.cc:514
void updateSensor(uniset::ObjectId id, long value)
Definition: UNetSender.cc:160
void updateFromSM()
Definition: UNetSender.cc:133
void updateItem(const UItem &it, long value)
Definition: UNetSender.cc:171
void askSensors(UniversalIO::UIOCommand cmd)
Definition: UNetSender.cc:520
Definition: Mutex.h:32
Definition: CommonEventLoop.h:15
const ObjectId DefaultObjectId
Definition: UniSetTypes.h:70
long ObjectId
Definition: UniSetTypes_i.idl:30
Definition: UNetSender.h:110
Definition: UNetSender.h:82
Definition: UDPPacket.h:88