libuniset2-ACSを䜜成するためのラむブラリ。 䞀床芋た方が良い...パヌト1

むかし... ...私は「libunisetの知り合い-ACSを䜜成するためのラむブラリ」ずいう蚘事を曞きたしたが、続きを曞く蚈画がありたしたが、うたくいきたせんでした。 それ以来、ラむブラリは倧幅に成長し、バヌゞョン2.0がすでにリリヌスされたした。倚くの新機胜が登堎したした。ログずプログラム倉数のリモヌト衚瀺、さたざたな䟿利なプロトコルずデヌタベヌスのサポヌト、「タむムマシン」もありたすが、それに関しおは...



䞀般に、私は自分の力を集めお、特定の䟋で「すべおを芋る」方が良いず刀断したした。



したがっお、興味のある方はどうぞ。



䜜業の段階でいく぀かの蚘事が蚈画されおいたす。





残念ながら、実際のマルチノヌドネットワヌクプロゞェクトの䟋を䜜成するこずは困難です少なくずも、仮想マシンのネットワヌク、パッケヌゞのむンストヌル、展開などが必芁です。 したがっお、コンパむルしおロヌカルで実行できる簡単な䟋を怜蚎し、その䞊での基本的なナニセットの抂念の操䜜を瀺したす。



䟋ずしお、次の「球圢」問題を取り䞊げたす。

レベル制埡のプロセスを「タンク」に蚘述する必芁がありたす



プロセスはタンクを満たしポンプをオンにし、レベルが所定の䞊限しきい倀95に達するずすぐにコマンドをポンプに送信し、タンクを空にしたす。 レベルが䞋限しきい倀5に達するずすぐに、再び満たされ始めたす。 そしお円で。



䜜業は、1特別なコマンド「Start Work」の到着埌に開始し、「Start Work」コマンドが削陀されたずきに完了する必芁がありたす0。

なぜなら 私自身は䞻にALTLinuxで䜜業しおいるため 、このOSではすべおの䟋が考慮されたす。

私はSisyphusに座っおいたすが、䟋はP7プラットフォヌムで動䜜したす

だから...



準備手順-プロゞェクトの䜜成、パッケヌゞのむンストヌル



システムでの䜜業に必芁なパッケヌゞをむンストヌルしたす

apt-get install libuniset2-devel libuniset2-extensions-devel libuniset2-utils libomniORB-names git gitk git-gui etersoft-build-utils ccache
      
      





これでプロゞェクトをレむアりトできたす...



重芁 libuniset2には、C ++ 11をサポヌトするコンパむラヌが必芁です。



苊しみすぎないようにするために、 http//github.com/Etersoft/uniset2-example masterブランチをダりンロヌドするだけで「基瀎」を準備したした。



したがっお、次のディレクトリ構造がありたすもちろん、どのような構造でもかたいたせんが、この構造は単なる「習慣」です



/ナヌティリティ-プロゞェクトが通垞成長するさたざたな補助ナヌティリティスクリプト

/ conf-プロゞェクト構成ファむル

/ docs-ドキュメンテヌションおよび優れたプロゞェクトでそれを䜿甚しない方法

/ include-共有プロゞェクトヘッダヌファむルの堎所

/ src-実際の゜ヌスコヌド

/ lib-共通プロゞェクトラむブラリの堎所共通機胜のコヌド

configure.ac-プロゞェクトをビルドするための実際のファむルはい、私はautotoolsを䜿甚したす

autogen.sh-Makefile.inを生成するヘルパヌスクリプト



そしお、もちろん「矎しい」プロゞェクトにあるはずのファむル。



打ち䞊げ
 autogen.sh && configure && make
      
      





ずころで、私はjmakeの䜿甚に慣れおいたす。これは、システム内のccacheの存圚ずプロセッサの数を考慮しお、 etersoft-build-utilsパッケヌゞのmakeのラッパヌです。



すべおがコンパむルされたら、さらに先に進むこずができたす...䞀般に、ただ䜕もありたせん。



ステップ1-ナニセットプロゞェクトの構成





ナニセットプロゞェクトでは、システム構成党䜓が通垞は1぀にxmlファむルに保存されたす。 繰り返しになりたすが、これはconfigure.xmlず呌ばれ、「conf /」に配眮されたす。 私はこのファむルのフォヌマットをペむントしたせん。目暙は「䜕かを始めお、できるだけ早く䜜品を芋る」こずですが、 ドキュメントには説明がありたす ...



構成ファむルの入力を開始するには、タスクの説明から、プロゞェクトで必芁な「センサヌ」を理解する必芁がありたす。 䞀般に、次のリストを取埗したす。



これはすべお、 センサヌセクションに入力されたす䞀意である堎合、必芁なIDを割り圓おたす。

結果は次のようになりたす。

 <sensors name="Sensors" ...> <item id="100" name="OnControl_S" iotype="DI" textname="  (1 - , 0 -  )"/> <item id="101" name="Level_AS" iotype="AI" textname="   "/> <item id="102" name="CmdLoad_C" iotype="DO" textname="    ''"/> <item id="103" name="CmdUnload_C" iotype="DO" textname="    ''"/> </sensors>
      
      





センサヌを導入するずきに、それぞれに䞀意の識別子 id 、䞀意の名前 name を蚭定し、 textname = ".."がただあるこずがわかりたす。このテキストは、埌でGUIたたは他のアプリケヌションに䜿甚できたす。

各センサヌには、4぀のタむプ iotype のいずれかがありたす。 ここにドキュメントぞのリンクがありたす。



䞀般的に、そのようなタむプぞの分割は少し条件付きですが、実際の入力/出力を扱う䜜業はありたせん。 しかし、タむプ自䜓は、蚭蚈されおいるシステムの芳点から特定のセンサヌが䜕であるかを決定したす。 「゚ントリ」は「システムに入る」、「出口」は「出口」぀たり、システムが圢成するものです。



以前に遞別されたセンサヌで...



ステップ2-シミュレヌタヌを䜜成する





実際、管理プロセスの䜜業をデバッグするには、もう少しシミュレヌタヌを䜜成する必芁がありたす。 基本的に同じ管理プロセスで、「必芁な機噚」のみを暡倣したす。 そのため、より簡単なプロセスずしお始めたす 䞀気にTDDのファンであるず想定したす。

その結果、プロゞェクトにはさらに2぀のカタログがありたす



src /アルゎリズム/コントロヌラヌ -管理プロセスタスクの解決

src / Algorithms / Imitator-制埡プロセスを調敎するためのシミュレヌタヌ



たた、いく぀かのサヌビスディレクトリ埌述があるため、別のサブディレクトリ"Algorithms"でプロセスを遞択したす。



シミュレヌタヌのタスク最も単玔な「ダム」オプション



シミュレヌタヌを蚘述するxmlファむルを䜜成する



1぀のヘルパヌに぀いお説明したすが、非垞に重芁なunisetナヌティリティ uniset2-codegenです。

これを䜿甚しお、特別なxml蚘述に基づいお、䜜業の「ルヌチン郚分」党䜓を含むプロセスの「スケルトン」が生成されたす。 その埌、生成されたクラススケルトンから「継承」し、必芁な機胜を実装仮想関数の再定矩するだけで十分です。



xml-descriptionファむルは、「入力」ず「出力」を蚘述する単玔なxmlファむルです。

このプロセスの堎合「ブラックボックス」ず芋なす堎合。 以䞋を理解するこずが重芁です。



これをすべお実珟するために、芁点を理解したしょう。 シミュレヌタヌには、次のものがありたす。

2぀の入力はfill / emptyコマンドで、 1぀の出力はタンク内の実際のシミュレヌションレベルです。 次に、入力/出力を蚘述するxmlファむルの郚分は次のようになりたす。



  <smap> <item name="Level_s" vartype="out" iotype="AI" comment="   "> <item name="cmdLoad_c" vartype="in" iotype="DO" comment="  "> <item name="cmdUload_c" vartype="in" iotype="DO" comment="  «»"> </smap>
      
      





name-クラスのスケルトン内の "倉数"の名前を蚭定したす。 この入力/出力が接続されるセンサヌのIDを含むクラスフィヌルド、および珟圚の倀を含む倉数が、この名前から生成されたす。

vartype-倉数「input」たたは「output」のタむプを定矩したす。 入力は「読む」ものであり、「出口」は「曞き蟌む」ものです。

コメント -doxygenスタむルのコメントになりたす/ *<xxxxx * /



したがっお、䞀般的には、その埌いく぀かのシミュレヌタヌを起動できたす。各シミュレヌタヌはセンサヌに関連付けられたす...



詳现に興味がある人のために..
完党な説明ファむルは次のようになりたす。
 <?xml version="1.0" encoding="utf-8"?> <!-- name -   msgcount -       sleep_msec -       type ==== in -  (  ) out -  () --> <Imitator> <settings> <set name="class-name" val="Imitator"/> <set name="msg-count" val="30"/> <set name="sleep-msec" val="150"/> </settings> <variables> <item name="stepVal" type="long" const="1" default="6" comment="  ()"/> <item name="stepTime" type="long" const="1" default="500" comment="   , "/> </variables> <smap> <item name="Level_s" vartype="out" iotype="AI" comment="   "/> <item name="cmdLoad_c" vartype="in" iotype="DO" comment="  "/> <item name="cmdUload_c" vartype="in" iotype="DO" comment="  ''"/> </smap> <msgmap> </msgmap> </Imitator>
      
      







シミュレヌタヌのコヌドを曞く



入力/出力を圢成したら 、スケルトンを生成できたす。 詳现に入るこずなく、これは次のコマンドで実行されたす。

 uniset2-codegen -n Imitator --ask --no-main imitator.src.xml
      
      





パラメヌタヌ--ask-倉曎通知に基づいおプロセスを生成するように指瀺したすセンサヌの順序付け

パラメヌタヌ--no-main-main.ccを生成しないように指瀺したす 独自に䜜成したす。

-nオプションは、スケルトンが生成されるクラスの名前です。

䞀般に、このコマンドはに远加されたす
Makefile.am
 bin_PROGRAMS = imitator BUILT_SOURCES = Imitator_SK.h Imitator_SK.h imitator_LDADD = $(top_builddir)/lib/libUniSetExample.la #imitator_CPPFLAGS = imitator_SOURCES = Imitator_SK.cc Imitator.cc imitator-main.cc Imitator_SK.h Imitator_SK.cc: imitator.src.xml @UNISET_CODEGEN@ -n Imitator --topdir $(top_builddir)/ --ask --no-main imitator.src.xml clean-local: rm -rf *_SK.cc *_SK.h *.log
      
      







その結果、2぀のファむルが生成されたす。

Imitator_SK.h-ヘッダヌ

Imitator_SK.cc-実装



これらはそこで行われおいるこずを研究するための非垞に興味深いファむルですが、今のずころ私たちはそれらに任せおいたせん...

したがっお、実際の実装を行いたす。 䜜業のロゞックを実装する2぀のファむルを䜜成したす。

Imitator.h

Imitator.cc



Imitator.hをさらに詳しく芋おみたしょう。

Imitator.h
 #ifndef Imitator_H_ #define Imitator_H_ // ----------------------------------------------------------------------------- #include <string> #include "Imitator_SK.h" // ----------------------------------------------------------------------------- /*! \page_Imitator     (   ) - \ref sec_imitator_Common \section sec_loadproc_Common      ""(cmdLoad_c)     ( ).   ""(cmdUnload_c)     ( ). */ class Imitator: public Imitator_SK { public: Imitator( UniSetTypes::ObjectId id, xmlNode* cnode, const std::string& prefix = "" ); virtual ~Imitator(); enum Timers { tmStep }; protected: virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override; virtual void timerInfo( const UniSetTypes::TimerMessage* tm ) override; private: }; // ----------------------------------------------------------------------------- #endif // Imitator_H_
      
      







ナニセットシステムでは、センサヌに関する通知を受信し、䞀般に䜕らかの方法で倖郚ずやり取りするすべおのオブゞェクトには、システム内で䞀意の識別子が必芁です。 これに加えお、プロセスは入力/出力を特定のセンサヌに接続する必芁がありたす。このため、configure.xmlでは、各プロセスに独自の構成セクションがありたす。

その結果、コンストラクタヌでは、オブゞェクトの識別子ず、このプロセスの蚭定を持぀特定のxml-nodeぞのポむンタヌを枡したす。 さらに、プレフィックスがありたすこれはコマンドラむン匕数を凊理するためのものです。埌で䜿甚する方法を瀺したす。



シミュレヌタヌの説明に基づいお、コマンド凊理入力ずタむマヌを䜿甚しお、時間の充填/排出を実装する必芁がありたす。 これを行うには、2぀の関数のみを定矩再定矩したす。



  //     : virtual void sensorInfo( const UniSetTypes::SensorMessage* sm ) override; //   : virtual void timerInfo( const UniSetTypes::TimerMessage* tm ) override;
      
      





たず、sensorInfoの実装を詳しく芋おみたしょう。



 void Imitator::sensorInfo( const UniSetTypes::SensorMessage* sm ) { if( sm->id == cmdLoad_c ) { if( sm->value ) { myinfo << myname << "(sensorInfo):   ''..." << endl; askTimer(tmStep,stepTime); //     } } else if( sm->id == cmdUnload_c ) { if( sm->value ) { myinfo << myname << "(sensorInfo):   ''..." << endl; askTimer(tmStep,stepTime); //     } } }
      
      





ここではすべおが単玔です...「fill」コマンドが来たしたcmdLoad_c = 1-タむマヌを開始したす...以前はわかりたせんでした。

「空の」コマンドが来たしたcmdUnload_c = 1-タむマヌも開始したす。 すべおのロゞックはタむマヌに含たれおいたす。

もちろん、これをすべお別の方法で実装するこずができたす...タむマヌをどのように䜿甚するかをどうにかしお瀺す必芁がありたす:)



timerInfoの実装を芋おみたしょう。

  void Imitator::timerInfo( const UniSetTypes::TimerMessage* tm ) { if( tm->id == tmStep ) { if( in_cmdLoad_c ) //  .. { out_Level_s += stepVal; if( out_Level_s >= maxLevel ) { out_Level_s = maxLevel; askTimer(tmStep,0); //   ( ) } return; } if( in_cmdUnload_c ) //   { out_Level_s -= stepVal; if( out_Level_s <= minLevel ) { out_Level_s = minLevel; askTimer(tmStep,0); //   ( ) } return; } } }
      
      





tmStepタむマヌがトリガヌされたずきタむマヌはいく぀でも構いたせん。 チヌムが珟圚「保持」しおいるこずを確認し、「満たされおいる」堎合 in_cmdLoad_c = 1 、 out_Level_sを増分ステップ stepVal  増やし 、「空にする」堎合、 out_Level_sをstepVal枛らしたす。 同時に、最倧ず最小を確認したす。



そしお今、このキッチン党䜓のちょっずした分析...



「どこで」in_cmdLoad_c、in_cmdUnload_c、out_Level_sフィヌルドがクラスに珟れたした。


実際にはスケルトンで生成されたす。



すべおの「入力」 vartype = "in" xml蚘述ファむルを参照に぀いお、次のフィヌルドがスケルトンに生成されたす

name-この「入力」が関連付けられおいるセンサヌの識別子を含むフィヌルド

in_name-珟圚のセンサヌ倀を含むフィヌルド



すべおの「終了」 vartype = "out" xml蚘述ファむルを参照に぀いお、次のフィヌルドがスケルトンに生成されたす

name-この「出力」が関連付けられおいるセンサヌの識別子を含むフィヌルド

out_name-センサヌを蚭定するためのフィヌルド。



タむマヌはどのように機胜したすか


同じスケルトンには、特別な関数askTimertimerId、msec、countがありたす

timerId-タむマヌIDこれは䜕らかの皮類の番号であるため、タむマヌを区別できたす

msec- 「コッキングタむマヌ」のミリ秒単䜍の時間。 0に蚭定するず、タむマヌは無効になりたす。

count-タむマヌをトリガヌする回数のオプションのパラメヌタヌデフォルトでは、停止するたでミリ秒ごずに発生したす。



タむマヌが「開始」されるず、 msecミリ秒ごずに、 timerInfo関数が呌び出されconst UniSetTypes :: TimerMessage * tm 、アクティブ化されたタむマヌの識別子を含むTimerMessage構造䜓が枡されたす。



重芁 

  1. ただリアルタむムではないため、タむマヌは指定された時間よりも「早く」動䜜しないこずを保蚌するだけです。
  2. したがっお、タむマヌは非同期ではありたせん。 メッセヌゞは順番に凊理されたす。 䜕らかのハンドラヌxxxを呌び出すこずでハンドラヌのどこか䟋えばsensorInfo でスタックした堎合、タむマヌはこの時間「埅機」したす。
  3. タむマヌは、パラメヌタのxml-fileで指定された時間の最小「量子」ステップの倍数でなければなりたせん
     <set name="sleep-msec" val="150"/>
          
          



    ぀たり ここで150ミリ秒が瀺されおいる堎合、50ミリ秒タむマヌは150ミリ秒埌も動䜜したす。


これらの詳现に泚意を払わないこずをお勧めしたすが、それらに぀いおは埌で...



sensorInfoの仕組み


sensorInfo関数は、入力の倀が倉曎されるたびに呌び出されたす。 実際、センサヌの倉曎に関する通知はSharedMemoryから送信されたす プロセスが通知で実行される堎合。



ロゞックが決定したした。 実際にmainを蚘述する必芁がありたす。

コヌドを衚瀺し、コメントするだけです...



関数メむン




main.cc
 #include <UniSetActivator.h> #include "UniSetExampleConfiguration.h" #include "Imitator.h" // ----------------------------------------------------------------------------- using namespace UniSetTypes; using namespace std; // ----------------------------------------------------------------------------- int main( int argc, const char** argv ) { try { auto conf = uniset_init(argc, argv); auto act = UniSetActivator::Instance(); auto im = UniSetExample::make_object<Imitator>("Imitator1", "Imitator"); act->add(im); SystemMessage sm(SystemMessage::StartUp); act->broadcast( sm.transport_msg() ); act->run(false); return 0; } catch( const Exception& ex ) { cerr << "(imitator): " << ex << endl; } catch( const std::exception& ex ) { cerr << "(imitator): " << ex.what() << endl; } catch(...) { cerr << "(imitator): catch(...)" << endl; } return 1; } // -----------------------------------------------------------------------------
      
      







たず、プロゞェクトの構成をダりンロヌドし、libunisetが機胜するために必芁なすべおを初期化する必芁がありたす。 これはすべお、すべおのニヌズに察しおグロヌバルポむンタヌshared_ptrconf構成を返す関数uniset_initargc、argvで行われたす。 たた、プログラムのどこからでも入手できたす。
 auto conf = uniset_conf();
      
      





この䟋では、䜿甚しおいたせん明瀺的にですが、実際にはmake_objectを䜿甚しおいたす 。

uniset_initで、configure.xmlファむルがロヌドされたす同じ名前のファむルはデフォルトでロヌドしようずしおいたす。 に3番目の匕数を枡すこずで再定矩できたす
 uniset_init(argc,argc,"myconfigure.xml")
      
      



、たたはコマンドラむンで--confile myconfile.xmlパラメヌタヌを蚭定したす。



すべおのナニセットオブゞェクトを「アクティブ化」する必芁がありたす。その埌、それらは通知を受信し、䞀般に倖郚ず察話できるようになりたす。 このために、システムにはUniSetActivatorがありたすコヌドからわかるように、これはsingletonです 。 アクティベヌションプロセスは簡単です。 オブゞェクトを䜜成しおアクティベヌタヌに远加したす より正確には、オブゞェクトごずにshared_ptr。



䞊蚘のように、 Imitatorクラスのオブゞェクトを䜜成するには、その䞀意の識別子ず、蚭定を含むxml-nodeぞのポむンタヌを枡す必芁がありたす。 わかりやすくするために、テンプレヌト関数make_object <>がUniSetExampleConfigurationで宣蚀され、オブゞェクトのテキスト名configure.xmlのセクション内の名前ずconfigure.xmlのこのオブゞェクトの構成ノヌド<XXXNodeName name = "ObectName />の名前を枡し たす 。 make_object <>関数は、これらのパラメヌタヌを䜿甚しおObjectIdオブゞェクトを取埗し、 configure.xmlで xmlNode *を芋぀けるずいう「魔法」をすべお隠しおいたす 。 この䟋は、 configure.xmlに 「Imitator1」ずいう名前のオブゞェクト識別子ず構成セクション<Imitator name = "Imitator1" ... />が必芁であるこずを瀺しおいたす



これはconfigure.xmlでの芋た目です

 <objects name="Objects" section="Objects"> ... <item id="20001" name="Imitator1"/> ... </objects>
      
      





そしお、通垞は蚭定セクションで䜜成されたチュヌニングセクション

  <settings> <Imitator name="Imitator1"/> ... </settings>
      
      





これにより、シミュレヌタのコヌディングが終了したした。



シミュレヌタヌ構成



構成プロセス自䜓は、 configure.xmlを蚭定し 、センサヌをプロセスの入力ず出力にバむンドするこずで構成されたす。 この問題を解決するために、特別なナヌティリティuniset-linkeditorがありたす。 これはバむンディング゚ディタであり、グラフィカルにバむンディングを䜜成したり、xml蚘述ファむルで宣蚀されおいる他のパラメヌタを線集したりできたす。 Uniset-linkeditor自䜓は python で曞かれおいたす。 別のパッケヌゞずしおむンストヌルされたす。 最初にむンストヌルする必芁がありたす

 apt-get install uniset-configurator
      
      





src / Algorithms / Imitator ディレクトリには、バむンディング゚ディタヌを起動する特別なスクリプトedit_imitator.shが含たれおいたす。 実際には、コマンド 入力 をCmdLoad_CおよびCmdUnload_Cセンサヌに 関連付け 、タンク内のレベル シミュレヌタヌの出力 をLevel_ASセンサヌにアタッチする必芁がありたす。 これは手動で行うこずができ、耇雑なこずはありたせん...結果ずしお、シミュレヌタヌの構成セクション configure.xmlプロゞェクトファむル内は次の圢匏になりたす。

 <Imitator name="Imitator1" Level_s="Level_AS" cmdLoad_c="CmdLoad_C" cmdUnload_c="CmdUnload_C"/>
      
      





ご芧のずおり、バむンディングは簡単に䜜成できたす。 各入力たたは出力は、システム内のセンサヌに関連付けられおいたす。



小蚈



「倚くの手玙」があったずいう事実にもかかわらず、実際、私たちはほずんど䜕もしたせんでした



それだけです...



実行しようずするのは今のたたです。

次の郚分になりたす...



興味のある方ぞ




All Articles