UniSet  2.2.1
UNetSender.h
00001 #ifndef UNetSender_H_
00002 #define UNetSender_H_
00003 // -----------------------------------------------------------------------------
00004 #include <ostream>
00005 #include <string>
00006 #include <vector>
00007 #include <unordered_map>
00008 #include <cc++/socket.h>
00009 #include "UniSetObject.h"
00010 #include "Trigger.h"
00011 #include "Mutex.h"
00012 #include "SMInterface.h"
00013 #include "SharedMemory.h"
00014 #include "ThreadCreator.h"
00015 #include "UDPPacket.h"
00016 // -----------------------------------------------------------------------------
00017 /*
00018  *    Распределение датчиков по пакетам
00019  *    =========================================================================
00020  *    Все пересылаемые данные разбиваются на группы по частоте посылки("sendfactor").
00021  *    Частота посылки кратна sendpause, задаётся для каждого датчика, при помощи свойства prefix_sendfactor.
00022  *    Внутри каждой группы пакеты набираются по мере "заполнения".
00023  *
00024  *    Добавление датчика в пакет и создание нового пакета при переполнении происходит в функции initItem().
00025  *    Причем так как дискретные и аналоговые датчики обрабатываются отдельно (но пересылаются в одном пакете),
00026  *    то датчики, которые первые переполнятся приводят к тому, что создаётся новый пакет и они добавляются в него,
00027  *    в свою очередь остальные продолжают "добивать" предыдущий пакет.
00028  *    В свою очередь в initItem() каждому UItem в dlist кроме pack_ind присваивается еще и номер пакета pack_num, который гарантировано соответствует
00029  *    существующему пакету, поэтому в дальнейшем при использовании pack_num в качестве ключа в mypacks мы не проверяем пакет на существование.
00030  *
00031  *    ОПТИМИЗАЦИЯ N1: Для оптимизации обработки посылаемых пакетов (на стороне UNetReceiver) сделана следующая логика:
00032  *                  Номер очередного посылаемого пакета меняется (увеличивается) только, если изменились данные с момента
00033                     последней посылки. Для этого по данным каждый раз производится расчёт UNetUDP::makeCRC() и сравнивается с последним..
00034  */
00035 class UNetSender
00036 {
00037     public:
00038         UNetSender( const std::string& host, const ost::tpport_t port, const std::shared_ptr<SMInterface>& smi,
00039                     const std::string& s_field = "", const std::string& s_fvalue = "", const std::string& prefix = "unet",
00040                     size_t maxDCount = UniSetUDP::MaxDCount, size_t maxACount = UniSetUDP::MaxACount );
00041 
00042         virtual ~UNetSender();
00043 
00044         typedef size_t sendfactor_t;
00045 
00046         struct UItem
00047         {
00048             UItem():
00049                 iotype(UniversalIO::UnknownIOType),
00050                 id(UniSetTypes::DefaultObjectId),
00051                 pack_num(0),
00052                 pack_ind(0),
00053                 pack_sendfactor(0) {}
00054 
00055             UniversalIO::IOType iotype;
00056             UniSetTypes::ObjectId id;
00057             IOController::IOStateList::iterator ioit;
00058             size_t pack_num;
00059             size_t pack_ind;
00060             sendfactor_t pack_sendfactor = { 0 };
00061 
00062             friend std::ostream& operator<<( std::ostream& os, UItem& p );
00063         };
00064 
00065         typedef std::vector<UItem> DMap;
00066 
00067         size_t getDataPackCount() const;
00068 
00069         void start();
00070         void stop();
00071 
00072         void send();
00073         void real_send(UniSetUDP::UDPMessage& mypack);
00074 
00076         void updateFromSM();
00077 
00079         void updateSensor( UniSetTypes::ObjectId id, long value );
00080 
00082         void updateItem( DMap::iterator& it, long value );
00083 
00084         inline void setSendPause( int msec )
00085         {
00086             sendpause = msec;
00087         }
00088         inline void setPackSendPause( int msec )
00089         {
00090             packsendpause = msec;
00091         }
00092 
00094         void askSensors( UniversalIO::UIOCommand cmd );
00095 
00097         void initIterators();
00098 
00099         inline std::shared_ptr<DebugStream> getLog()
00100         {
00101             return unetlog;
00102         }
00103 
00104         virtual const std::string getShortInfo() const;
00105 
00106         inline ost::IPV4Address getAddress() const
00107         {
00108             return addr;
00109         }
00110         inline ost::tpport_t getPort() const
00111         {
00112             return port;
00113         }
00114 
00115         inline size_t getADataSize() const
00116         {
00117             return maxAData;
00118         }
00119         inline size_t getDDataSize() const
00120         {
00121             return maxDData;
00122         }
00123 
00124     protected:
00125 
00126         std::string s_field = { "" };
00127         std::string s_fvalue = { "" };
00128         std::string prefix = { "" };
00129 
00130         const std::shared_ptr<SMInterface> shm;
00131         std::shared_ptr<DebugStream> unetlog;
00132 
00133         bool initItem( UniXML::iterator& it );
00134         bool readItem( const std::shared_ptr<UniXML>& xml, UniXML::iterator& it, xmlNode* sec );
00135 
00136         void readConfiguration();
00137 
00138     private:
00139         UNetSender();
00140 
00141         std::shared_ptr<ost::UDPBroadcast> udp;
00142         ost::IPV4Address addr;
00143         ost::tpport_t port = { 0 };
00144         std::string s_host = { "" };
00145 
00146         std::string myname = { "" };
00147         timeout_t sendpause = { 150 };
00148         timeout_t packsendpause = { 5 };
00149         std::atomic_bool activated = { false };
00150 
00151         UniSetTypes::uniset_rwmutex pack_mutex;
00152 
00153         typedef std::unordered_map<sendfactor_t, std::vector<UniSetUDP::UDPMessage>> Packs;
00154 
00155         Packs mypacks;
00156         std::unordered_map<sendfactor_t, size_t> packs_anum;
00157         std::unordered_map<sendfactor_t, size_t> packs_dnum;
00158         DMap dlist;
00159         size_t maxItem = { 0 };
00160         size_t packetnum = { 1 }; 
00161         unsigned short lastcrc = { 0 };
00162         UniSetUDP::UDPPacket s_msg;
00163 
00164         size_t maxAData = { UniSetUDP::MaxACount };
00165         size_t maxDData = { UniSetUDP::MaxDCount };
00166 
00167         std::shared_ptr< ThreadCreator<UNetSender> > s_thr;    // send thread
00168 
00169         size_t ncycle = { 0 }; 
00171 };
00172 // -----------------------------------------------------------------------------
00173 #endif // UNetSender_H_
00174 // -----------------------------------------------------------------------------