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