UniSet  2.6.0
IOController.h
00001 /*
00002  * Copyright (c) 2015 Pavel Vainerman.
00003  *
00004  * This program is free software: you can redistribute it and/or modify
00005  * it under the terms of the GNU Lesser General Public License as
00006  * published by the Free Software Foundation, version 2.1.
00007  *
00008  * This program is distributed in the hope that it will be useful, but
00009  * WITHOUT ANY WARRANTY; without even the implied warranty of
00010  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00011  * Lesser General Lesser Public License for more details.
00012  *
00013  * You should have received a copy of the GNU Lesser General Public License
00014  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00015  */
00016 // --------------------------------------------------------------------------
00021 // --------------------------------------------------------------------------
00022 #ifndef IOController_H_
00023 #define IOController_H_
00024 //---------------------------------------------------------------------------
00025 #include <unordered_map>
00026 #include <list>
00027 #include <sigc++/sigc++.h>
00028 #include "IOController_i.hh"
00029 #include "UniSetTypes.h"
00030 #include "UniSetManager.h"
00031 #include "Configuration.h"
00032 #include "Mutex.h"
00033 //---------------------------------------------------------------------------
00034 namespace uniset
00035 {
00037 class IOController:
00038     public UniSetManager,
00039     public POA_IOController_i
00040 {
00041     public:
00042 
00043         IOController( const std::string& name, const std::string& section );
00044         IOController( const uniset::ObjectId id );
00045         virtual ~IOController();
00046 
00047         virtual uniset::ObjectType getType() override
00048         {
00049             return uniset::ObjectType("IOController");
00050         }
00051 
00052         virtual uniset::SimpleInfo* getInfo( const char* userparam = "" ) override;
00053 
00054         virtual CORBA::Long getValue( uniset::ObjectId sid ) override;
00055 
00056         //     -------------------- !!!!!!!!! ---------------------------------
00057         //        Реализуются конкретным i/o контроллером
00058         //        Не забывайте писать реализацию этих функций
00059         virtual void setValue( uniset::ObjectId sid, CORBA::Long value,
00060                                uniset::ObjectId sup_id = uniset::DefaultObjectId ) override;
00061 
00062         //     ----------------------------------------------------------------
00063         virtual void setUndefinedState( uniset::ObjectId sid,
00064                                         CORBA::Boolean undefined,
00065                                         uniset::ObjectId sup_id = uniset::DefaultObjectId ) override;
00066 
00067 
00068         virtual IOController_i::SensorInfoSeq* getSensorSeq( const uniset::IDSeq& lst ) override;
00069         virtual uniset::IDSeq* setOutputSeq( const IOController_i::OutSeq& lst, uniset::ObjectId sup_id ) override;
00070 
00071         //     ----------------------------------------------------------------
00072         virtual UniversalIO::IOType getIOType( uniset::ObjectId sid ) override;
00073 
00074         virtual IOController_i::SensorInfoSeq* getSensorsMap() override;
00075         virtual IOController_i::SensorIOInfo getSensorIOInfo( uniset::ObjectId sid ) override;
00076 
00077         virtual CORBA::Long getRawValue( uniset::ObjectId sid ) override;
00078         virtual void calibrate( uniset::ObjectId sid,
00079                                 const IOController_i::CalibrateInfo& ci,
00080                                 uniset::ObjectId adminId ) override;
00081 
00082         IOController_i::CalibrateInfo getCalibrateInfo( uniset::ObjectId sid ) override;
00083 
00084         inline IOController_i::SensorInfo SensorInfo( const uniset::ObjectId sid,
00085                                                       const uniset::ObjectId node = uniset::uniset_conf()->getLocalNode())
00086         {
00087             IOController_i::SensorInfo si;
00088             si.id = sid;
00089             si.node = node;
00090             return si;
00091         };
00092 
00093         uniset::Message::Priority getPriority( const uniset::ObjectId id );
00094 
00095         virtual IOController_i::ShortIOInfo getTimeChange( const uniset::ObjectId id ) override;
00096 
00097         virtual IOController_i::ShortMapSeq* getSensors() override;
00098 
00099 #ifndef DISABLE_REST_API
00100         // http API
00101         virtual Poco::JSON::Object::Ptr httpHelp( const Poco::URI::QueryParameters& p ) override;
00102         virtual Poco::JSON::Object::Ptr httpRequest( const std::string& req, const Poco::URI::QueryParameters& p ) override;
00103 #endif
00104 
00105     public:
00106 
00107         // предварительное объявление..
00108         struct USensorInfo;
00109         typedef std::unordered_map<uniset::ObjectId, std::shared_ptr<USensorInfo>> IOStateList;
00110 
00111         // ================== Достпуные сигналы =================
00117         typedef sigc::signal<void, std::shared_ptr<USensorInfo>&, IOController*> ChangeSignal;
00118         typedef sigc::signal<void, std::shared_ptr<USensorInfo>&, IOController*> ChangeUndefinedStateSignal;
00119 
00120         // signal по изменению определённого датчика
00121         ChangeSignal signal_change_value( uniset::ObjectId sid );
00122 
00123         // signal по изменению любого датчика
00124         ChangeSignal signal_change_value();
00125 
00126         // сигналы по изменению флага "неопределённое состояние" (обрыв датчика например)
00127         ChangeUndefinedStateSignal signal_change_undefined_state( uniset::ObjectId sid );
00128         ChangeUndefinedStateSignal signal_change_undefined_state();
00129         // -----------------------------------------------------------------------------------------
00130         // полнейшее нарушение икапсуляции
00131         // но пока, это попытка оптимизировать работу с IOController через указатель.
00132         // Т.е. работая с датчиками через итераторы..
00133         inline IOStateList::iterator ioBegin()
00134         {
00135             return ioList.begin();
00136         }
00137         inline IOStateList::iterator ioEnd()
00138         {
00139             return ioList.end();
00140         }
00141         inline IOStateList::iterator find( uniset::ObjectId k )
00142         {
00143             return ioList.find(k);
00144         }
00145         inline int ioCount() const
00146         {
00147             return ioList.size();
00148         }
00149 
00150     protected:
00151 
00152         // доступ к элементам через итератор
00153         // return итоговое значение
00154         virtual long localSetValueIt( IOStateList::iterator& it, const uniset::ObjectId sid,
00155                                       CORBA::Long value, uniset::ObjectId sup_id );
00156 
00157         virtual long localGetValue( IOStateList::iterator& it, const uniset::ObjectId sid );
00158 
00163         virtual void localSetUndefinedState( IOStateList::iterator& it, bool undefined,
00164                                              const uniset::ObjectId sid );
00165 
00166         // -- работа через указатель ---
00167         virtual long localSetValue( std::shared_ptr<USensorInfo>& usi, CORBA::Long value, uniset::ObjectId sup_id );
00168         long localGetValue( std::shared_ptr<USensorInfo>& usi) ;
00169 
00170 #ifndef DISABLE_REST_API
00171         // http API
00172         virtual Poco::JSON::Object::Ptr request_get( const std::string& req, const Poco::URI::QueryParameters& p );
00173         virtual Poco::JSON::Object::Ptr request_sensors( const std::string& req, const Poco::URI::QueryParameters& p );
00174         void getSensorInfo( Poco::JSON::Array::Ptr& jdata, std::shared_ptr<USensorInfo>& s , bool shortInfo = false );
00175 #endif
00176 
00177         // переопределяем для добавления вызова регистрации датчиков
00178         virtual bool deactivateObject() override;
00179         virtual bool activateObject() override;
00180 
00182         virtual void activateInit();
00183 
00185         virtual void sensorsRegistration() {};
00187         virtual void sensorsUnregistration();
00188 
00189         typedef sigc::signal<void, std::shared_ptr<USensorInfo>&, IOController*> InitSignal;
00190 
00191         // signal по изменению определённого датчика
00192         InitSignal signal_init();
00193 
00197         void ioRegistration(std::shared_ptr<USensorInfo>& usi, bool force = false );
00198 
00200         void ioUnRegistration( const uniset::ObjectId sid );
00201 
00202         // ------------------------------
00203         inline IOController_i::SensorIOInfo
00204         SensorIOInfo(long v, UniversalIO::IOType t, const IOController_i::SensorInfo& si,
00205                      uniset::Message::Priority p = uniset::Message::Medium,
00206                      long defval = 0, IOController_i::CalibrateInfo* ci = 0,
00207                      uniset::ObjectId sup_id = uniset::DefaultObjectId )
00208         {
00209             IOController_i::SensorIOInfo ai;
00210             ai.si = si;
00211             ai.type = t;
00212             ai.value = v;
00213             ai.priority = p;
00214             ai.default_val = defval;
00215             ai.real_value = v;
00216             ai.blocked = false;
00217             ai.supplier = sup_id;
00218 
00219             if( ci != 0 )
00220                 ai.ci = *ci;
00221             else
00222             {
00223                 ai.ci.minRaw = 0;
00224                 ai.ci.maxRaw = 0;
00225                 ai.ci.minCal = 0;
00226                 ai.ci.maxCal = 0;
00227                 ai.ci.precision = 0;
00228             }
00229 
00230             return std::move(ai);
00231         };
00232 
00234         virtual void logging( uniset::SensorMessage& sm );
00235 
00237         virtual void dumpToDB();
00238 
00239         IOController();
00240 
00241         // доступ к списку c изменением только для своих
00242         IOStateList::iterator myioBegin();
00243         IOStateList::iterator myioEnd();
00244         IOStateList::iterator myiofind( uniset::ObjectId id );
00245         size_t ioCount();
00246         // --------------------------
00247 
00248     private:
00249         friend class NCRestorer;
00250         friend class SMInterface;
00251 
00252         std::mutex siganyMutex;
00253         ChangeSignal sigAnyChange;
00254 
00255         std::mutex siganyundefMutex;
00256         ChangeSignal sigAnyUndefChange;
00257         InitSignal sigInit;
00258 
00259         IOStateList ioList;    
00260         uniset::uniset_rwmutex ioMutex; 
00262         bool isPingDBServer;    // флаг связи с DBServer-ом
00263 
00264         std::mutex loggingMutex; 
00266     public:
00267         struct USensorInfo:
00268             public IOController_i::SensorIOInfo
00269         {
00270             USensorInfo( const USensorInfo& ) = delete;
00271             const USensorInfo& operator=(const USensorInfo& ) = delete;
00272             USensorInfo( USensorInfo&& ) = default;
00273             USensorInfo& operator=(USensorInfo&& ) = default;
00274 
00275             USensorInfo(): d_value(1), d_off_value(0)
00276             {
00277                 d_si.id = uniset::DefaultObjectId;
00278                 d_si.node = uniset::DefaultObjectId;
00279                 default_val = 0;
00280                 value = default_val;
00281                 real_value = default_val;
00282                 dbignore = false;
00283                 undefined = false;
00284                 blocked = false;
00285                 supplier = uniset::DefaultObjectId;
00286             }
00287 
00288             virtual ~USensorInfo() {}
00289 
00290             USensorInfo(IOController_i::SensorIOInfo& r);
00291             USensorInfo(IOController_i::SensorIOInfo* r);
00292             USensorInfo(const IOController_i::SensorIOInfo& r);
00293 
00294             USensorInfo& operator=(IOController_i::SensorIOInfo& r);
00295             const USensorInfo& operator=(const IOController_i::SensorIOInfo& r);
00296             USensorInfo& operator=(IOController_i::SensorIOInfo* r);
00297 
00298             // Дополнительные (вспомогательные поля)
00299             uniset::uniset_rwmutex val_lock; 
00301             static const size_t MaxUserData = 4;
00302             void* userdata[MaxUserData] = { nullptr, nullptr, nullptr, nullptr }; 
00304             // сигнал для реализации механизма зависимостией..
00305             // (все зависимые датчики подключаются к нему (см. NCRestorer::init_depends_signals)
00306             uniset::uniset_rwmutex changeMutex;
00307             ChangeSignal sigChange;
00308 
00309             uniset::uniset_rwmutex undefMutex;
00310             ChangeUndefinedStateSignal sigUndefChange;
00311 
00312             IOController_i::SensorInfo d_si = { uniset::DefaultObjectId, uniset::DefaultObjectId };  
00313             long d_value = { 1 }; 
00314             long d_off_value = { 0 }; 
00315             std::shared_ptr<USensorInfo> d_usi; // shared_ptr на датчик от которого зависит этот.
00316 
00317             size_t nchanges = { 0 }; // количество изменений датчика
00318 
00319             // функция обработки информации об изменении состояния датчика, от которого зависит данный
00320             void checkDepend( std::shared_ptr<USensorInfo>& d_usi, IOController* );
00321 
00322             void init( const IOController_i::SensorIOInfo& s );
00323 
00324             inline IOController_i::SensorIOInfo makeSensorIOInfo()
00325             {
00326                 uniset::uniset_rwmutex_rlock lock(val_lock);
00327                 IOController_i::SensorIOInfo s(*this);
00328                 return std::move(s);
00329             }
00330 
00331             inline uniset::SensorMessage makeSensorMessage()
00332             {
00333                 uniset::SensorMessage sm;
00334                 sm.id           = si.id;
00335                 sm.node         = si.node; // uniset_conf()->getLocalNode()?
00336                 sm.sensor_type  = type;
00337                 sm.priority     = (uniset::Message::Priority)priority;
00338 
00339                 // лочим только изменяемые поля
00340                 {
00341                     uniset::uniset_rwmutex_rlock lock(val_lock);
00342                     sm.value        = value;
00343                     sm.sm_tv.tv_sec    = tv_sec;
00344                     sm.sm_tv.tv_nsec   = tv_nsec;
00345                     sm.ci           = ci;
00346                     sm.supplier     = supplier;
00347                     sm.undefined    = undefined;
00348                 }
00349 
00350                 return std::move(sm);
00351             }
00352         };
00353 };
00354 // -------------------------------------------------------------------------
00355 } // end of uniset namespace
00356 // --------------------------------------------------------------------------
00357 #endif
00358 // --------------------------------------------------------------------------