00001 #!/usr/bin/env python 00002 # -*- coding: euc-jp -*- 00003 00004 ## 00005 # @file PublisherFlush.py 00006 # @brief PublisherFlush class 00007 # @date $Date: 2007/09/06$ 00008 # @author Noriaki Ando <n-ando@aist.go.jp> and Shinji Kurihara 00009 # 00010 # Copyright (C) 2006-2008 00011 # Noriaki Ando 00012 # Task-intelligence Research Group, 00013 # Intelligent Systems Research Institute, 00014 # National Institute of 00015 # Advanced Industrial Science and Technology (AIST), Japan 00016 # All rights reserved. 00017 00018 00019 import OpenRTM_aist 00020 00021 00022 ## 00023 # @if jp 00024 # @class PublisherFlush 00025 # @brief PublisherFlush クラス 00026 # 00027 # Flush 型 Publisher クラス 00028 # バッファ内に格納されている未送信データを送信する。 00029 # データ送出を待つコンシューマを、送出する側と同じスレッドで動作させる。 00030 # 00031 # @else 00032 # @class PublisherFlush 00033 # @brief PublisherFlush class 00034 # @endif 00035 class PublisherFlush(OpenRTM_aist.PublisherBase): 00036 """ 00037 """ 00038 00039 00040 00041 ## 00042 # @if jp 00043 # @brief コンストラクタ 00044 # 00045 # コンストラクタ 00046 # 00047 # @param self 00048 # @param consumer データ送出を待つコンシューマ 00049 # @param property 本Publisherの駆動制御情報を設定したPropertyオブジェクト 00050 # 00051 # @else 00052 # @brief Constructor 00053 # @endif 00054 def __init__(self): 00055 self._rtcout = OpenRTM_aist.Manager.instance().getLogbuf("PublisherFlush") 00056 self._consumer = None 00057 self._active = False 00058 self._profile = None # ConnectorInfo 00059 self._listeners = None # ConnectorListeners 00060 self._retcode = self.PORT_OK 00061 00062 ## 00063 # @if jp 00064 # @brief デストラクタ 00065 # 00066 # デストラクタ 00067 # 当該Publisherを破棄する際に、PublisherFactoryにより呼び出される。 00068 # 00069 # @param self 00070 # 00071 # @else 00072 # @brief Destructor 00073 # @endif 00074 def __del__(self): 00075 # "consumer" should be deleted in the Connector 00076 self._rtcout.RTC_TRACE("~PublisherFlush()") 00077 self._consumer = None 00078 return 00079 00080 ## 00081 # @if jp 00082 # @brief 初期化 00083 # 00084 # このクラスのオブジェクトを使用するのに先立ち、必ずこの関数を呼び 00085 # 出す必要がある。ただし、この PublisherFlush は現状で初期化するパ 00086 # ラメータを持たない。 00087 # 00088 # @param property 本Publisherの駆動制御情報を設定したPropertyオブジェクト 00089 # @return ReturnCode PORT_OK 正常終了 00090 # INVALID_ARGS Properties が不正な値を含む 00091 # 00092 # @else 00093 # @brief initialization 00094 # 00095 # This function have to be called before using this class object. 00096 # However, this PublisherFlush class has no parameters to be initialized. 00097 # 00098 # @param property Property objects that includes the control information 00099 # of this Publisher 00100 # @return ReturnCode PORT_OK normal return 00101 # INVALID_ARGS Properties with invalid values. 00102 # @endif 00103 # 00104 # virtual ReturnCode init(coil::Properties& prop); 00105 def init(self, prop): 00106 self._rtcout.RTC_TRACE("init()") 00107 return self.PORT_OK; 00108 00109 ## 00110 # @if jp 00111 # @brief InPortコンシューマのセット 00112 # 00113 # この関数では、この Publisher に関連付けられるコンシューマをセットする。 00114 # コンシューマオブジェクトがヌルポインタの場合、INVALID_ARGSが返される。 00115 # それ以外の場合は、PORT_OK が返される。 00116 # 00117 # @param consumer Consumer へのポインタ 00118 # @return ReturnCode PORT_OK 正常終了 00119 # INVALID_ARGS 引数に不正な値が含まれている 00120 # 00121 # @else 00122 # @brief Store InPort consumer 00123 # 00124 # This operation sets a consumer that is associated with this 00125 # object. If the consumer object is NULL, INVALID_ARGS will be 00126 # returned. 00127 # 00128 # @param consumer A pointer to a consumer object. 00129 # @return ReturnCode PORT_OK normal return 00130 # INVALID_ARGS given argument has invalid value 00131 # 00132 # PublisherFlush::setConsumer(InPortConsumer* consumer) 00133 def setConsumer(self, consumer): 00134 self._rtcout.RTC_TRACE("setConsumer()") 00135 if not consumer: 00136 return self.INVALID_ARGS 00137 00138 self._consumer = consumer 00139 00140 return self.PORT_OK 00141 00142 ## 00143 # @if jp 00144 # @brief バッファのセット 00145 # 00146 # PublisherFlushでは、バッファを使用しないため、いかなる場合も 00147 # PORT_OK を返す。 00148 # 00149 # @param buffer CDRバッファ 00150 # @return PORT_OK 正常終了 00151 # 00152 # @else 00153 # @brief Setting buffer pointer 00154 # 00155 # Since PublisherFlush does not use any buffers, This function 00156 # always returns PORT_OK. 00157 # 00158 # @param buffer CDR buffer 00159 # @return PORT_OK 00160 # 00161 # @endif 00162 # 00163 # PublisherBase::ReturnCode PublisherFlush::setBuffer(CdrBufferBase* buffer) 00164 def setBuffer(self, buffer): 00165 self._rtcout.RTC_TRACE("setBuffer()") 00166 return self.PORT_OK 00167 00168 ## 00169 # @if jp 00170 # @brief リスナを設定する。 00171 # 00172 # Publisher に対してリスナオブジェクト ConnectorListeners を設定する。 00173 # 各種リスナオブジェクトを含む ConnectorListeners をセットすることで、 00174 # バッファの読み書き、データの送信時等にこれらのリスナをコールする。 00175 # ConnectorListeners オブジェクトの所有権はポートまたは RTObject が持ち 00176 # Publisher 削除時に ConnectorListeners は削除されることはない。 00177 # ConnectorListeners がヌルポインタの場合 INVALID_ARGS を返す。 00178 # 00179 # @param info ConnectorProfile をローカル化したオブジェクト ConnectorInfo 00180 # @param listeners リスナを多数保持する ConnectorListeners オブジェクト 00181 # @return PORT_OK 正常終了 00182 # INVALID_ARGS 不正な引数 00183 # @else 00184 # @brief Set the listener. 00185 # 00186 # This function sets ConnectorListeners listener object to the 00187 # Publisher. By setting ConnectorListeners containing various 00188 # listeners objects, these listeners are called at the time of 00189 # reading and writing of a buffer, and transmission of data 00190 # etc. Since the ownership of the ConnectorListeners object is 00191 # owned by Port or RTObject, the Publisher never deletes the 00192 # ConnectorListeners object. If the given ConnectorListeners' 00193 # pointer is NULL, this function returns INVALID_ARGS. 00194 # 00195 # @param info ConnectorInfo that is localized object of ConnectorProfile 00196 # @param listeners ConnectorListeners that holds various listeners 00197 # @return PORT_OK Normal return 00198 # INVALID_ARGS Invalid arguments 00199 # @endif 00200 # 00201 # virtual ::RTC::DataPortStatus::Enum 00202 # setListener(ConnectorInfo& info, 00203 # RTC::ConnectorListeners* listeners); 00204 def setListener(self, info, listeners): 00205 self._rtcout.RTC_TRACE("setListeners()") 00206 00207 if not listeners: 00208 self._rtcout.RTC_ERROR("setListeners(listeners == 0): invalid argument") 00209 return self.INVALID_ARGS 00210 00211 self._profile = info 00212 self._listeners = listeners 00213 00214 return self.PORT_OK 00215 00216 ## 00217 # @if jp 00218 # @brief データを書き込む 00219 # 00220 # Publisher が保持するコンシューマに対してデータを書き込む。コン 00221 # シューマ、リスナ等が適切に設定されていない等、Publisher オブジェ 00222 # クトが正しく初期化されていない場合、この関数を呼び出すとエラーコー 00223 # ド PRECONDITION_NOT_MET が返され、コンシューマへの書き込み等の操 00224 # 作は一切行われない。 00225 # 00226 # コンシューマへの書き込みに対して、コンシューマがフル状態、コン 00227 # シューマのエラー、コンシューマへの書き込みがタイムアウトした場合 00228 # にはそれぞれ、エラーコード SEND_FULL, SEND_ERROR, SEND_TIMEOUT 00229 # が返される。 00230 # 00231 # これら以外のエラーの場合、PORT_ERROR が返される。 00232 # 00233 # 00234 # @param data 書き込むデータ 00235 # @param sec タイムアウト時間 00236 # @param nsec タイムアウト時間 00237 # 00238 # @return PORT_OK 正常終了 00239 # PRECONDITION_NO_MET consumer, buffer, listener等が適切に設定 00240 # されていない等、このオブジェクトの事前条件 00241 # を満たさない場合。 00242 # SEND_FULL 送信先がフル状態 00243 # SEND_TIMEOUT 送信先がタイムアウトした 00244 # CONNECTION_LOST 接続が切断されたことを検知した。 00245 # 00246 # @else 00247 # @brief Write data 00248 # 00249 # This function writes data into the consumer associated with 00250 # this Publisher. If this function is called without initializing 00251 # correctly such as a consumer, listeners, etc., error code 00252 # PRECONDITION_NOT_MET will be returned and no operation of the 00253 # writing to the consumer etc. will be performed. 00254 # 00255 # When publisher writes data to the buffer, if the consumer 00256 # returns full-status, returns error, is returned with timeout, 00257 # error codes BUFFER_FULL, BUFFER_ERROR and BUFFER_TIMEOUT will 00258 # be returned respectively. 00259 # 00260 # In other cases, PROT_ERROR will be returned. 00261 # 00262 # @param data Data to be wrote to the buffer 00263 # @param sec Timeout time in unit seconds 00264 # @param nsec Timeout time in unit nano-seconds 00265 # @return PORT_OK Normal return 00266 # PRECONDITION_NO_MET Precondition does not met. A consumer, 00267 # a buffer, listenes are not set properly. 00268 # SEND_FULL Data was sent but full-status returned 00269 # SEND_TIMEOUT Data was sent but timeout occurred 00270 # CONNECTION_LOST detected that the connection has been lost 00271 # 00272 # @endif 00273 # 00274 ## PublisherBase::ReturnCode PublisherFlush::write(const cdrMemoryStream& data, 00275 ## unsigned long sec, 00276 ## unsigned long usec) 00277 def write(self, data, sec, usec): 00278 self._rtcout.RTC_PARANOID("write()") 00279 if not self._consumer or not self._listeners: 00280 return self.PRECONDITION_NOT_MET 00281 00282 if self._retcode == self.CONNECTION_LOST: 00283 self._rtcout.RTC_DEBUG("write(): connection lost.") 00284 return self._retcode 00285 00286 self.onSend(data) 00287 00288 self._retcode = self._consumer.put(data) 00289 00290 if self._retcode == self.PORT_OK: 00291 self.onReceived(data) 00292 return self._retcode 00293 elif self._retcode == self.PORT_ERROR: 00294 self.onReceiverError(data) 00295 return self._retcode 00296 elif self._retcode == self.SEND_FULL: 00297 self.onReceiverFull(data) 00298 return self._retcode 00299 elif self._retcode == self.SEND_TIMEOUT: 00300 self.onReceiverTimeout(data) 00301 return self._retcode 00302 elif self._retcode == self.CONNECTION_LOST: 00303 self.onReceiverTimeout(data) 00304 return self._retcode 00305 elif self._retcode == self.UNKNOWN_ERROR: 00306 self.onReceiverError(data) 00307 return self._retcode 00308 else: 00309 self.onReceiverError(data) 00310 return self._retcode 00311 00312 return self._retcode 00313 00314 00315 ## 00316 # @if jp 00317 # 00318 # @brief アクティブ化確認 00319 # 00320 # Publisher はデータポートと同期して activate/deactivate される。 00321 # activate() / deactivate() 関数によって、アクティブ状態と非アクティ 00322 # ブ状態が切り替わる。この関数により、現在アクティブ状態か、非アク 00323 # ティブ状態かを確認することができる。 00324 # 00325 # @return 状態確認結果(アクティブ状態:true、非アクティブ状態:false) 00326 # 00327 # @else 00328 # 00329 # @brief If publisher is active state 00330 # 00331 # A Publisher can be activated/deactivated synchronized with the 00332 # data port. The active state and the non-active state are made 00333 # transition by the "activate()" and the "deactivate()" functions 00334 # respectively. This function confirms if the publisher is in 00335 # active state. 00336 # 00337 # @return Result of state confirmation 00338 # (Active state:true, Inactive state:false) 00339 # 00340 # @endif 00341 # 00342 ## bool PublisherFlush::isActive() 00343 def isActive(self): 00344 return self._active 00345 00346 00347 ## 00348 # @if jp 00349 # @brief アクティブ化する 00350 # 00351 # Publisher をアクティブ化する。この関数を呼び出すことにより、 00352 # Publisherが持つ、データを送信するスレッドが動作を開始する。初期 00353 # 化が行われていないなどにより、事前条件を満たさない場合、エラーコー 00354 # ド PRECONDITION_NOT_MET を返す。 00355 # 00356 # @return PORT_OK 正常終了 00357 # PRECONDITION_NOT_MET 事前条件を満たさない 00358 # 00359 # @else 00360 # @brief activation 00361 # 00362 # This function activates the publisher. By calling this 00363 # function, this publisher starts the thread that pushes data to 00364 # InPort. If precondition such as initialization process and so 00365 # on is not met, the error code PRECONDITION_NOT_MET is returned. 00366 # 00367 # @return PORT_OK normal return 00368 # PRECONDITION_NOT_MET precondition is not met 00369 # 00370 # @endif 00371 # 00372 ## PublisherBase::ReturnCode PublisherFlush::activate() 00373 def activate(self): 00374 if self._active: 00375 return self.PRECONDITION_NOT_MET 00376 00377 self._active = True 00378 00379 return self.PORT_OK 00380 00381 ## 00382 # @if jp 00383 # @brief 非アクティブ化する 00384 # 00385 # Publisher を非アクティブ化する。この関数を呼び出すことにより、 00386 # Publisherが持つ、データを送信するスレッドが動作を停止する。初期 00387 # 化が行われていないなどにより、事前条件を満たさない場合、エラーコー 00388 # ド PRECONDITION_NOT_MET を返す。 00389 # 00390 # @return PORT_OK 正常終了 00391 # PRECONDITION_NOT_MET 事前条件を満たさない 00392 # 00393 # @else 00394 # @brief deactivation 00395 # 00396 # This function deactivates the publisher. By calling this 00397 # function, this publisher stops the thread that pushes data to 00398 # InPort. If precondition such as initialization process and so 00399 # on is not met, the error code PRECONDITION_NOT_MET is returned. 00400 # 00401 # @return PORT_OK normal return 00402 # PRECONDITION_NOT_MET precondition is not met 00403 # 00404 # @endif 00405 # 00406 ## PublisherBase::ReturnCode PublisherFlush::deactivate() 00407 def deactivate(self): 00408 if not self._active: 00409 return self.PRECONDITION_NOT_MET 00410 00411 self._active = False 00412 00413 return self.PORT_OK 00414 00415 ## 00416 # @if jp 00417 # @brief ON_SENDのリスナへ通知する。 00418 # @param data cdrMemoryStream 00419 # @else 00420 # @brief Notify an ON_SEND event to listners 00421 # @param data cdrMemoryStream 00422 # @endif 00423 # 00424 # inline void onSend(const cdrMemoryStream& data) 00425 def onSend(self, data): 00426 if self._listeners is not None and self._profile is not None: 00427 self._listeners.connectorData_[OpenRTM_aist.ConnectorDataListenerType.ON_SEND].notify(self._profile, data) 00428 return 00429 00430 ## 00431 # @if jp 00432 # @brief ON_RECEIVEDのリスナへ通知する。 00433 # @param data cdrMemoryStream 00434 # @else 00435 # @brief Notify an ON_RECEIVED event to listeners 00436 # @param data cdrMemoryStream 00437 # @endif 00438 # 00439 # inline void onReceived(const cdrMemoryStream& data) 00440 def onReceived(self, data): 00441 if self._listeners is not None and self._profile is not None: 00442 self._listeners.connectorData_[OpenRTM_aist.ConnectorDataListenerType.ON_RECEIVED].notify(self._profile, data) 00443 return 00444 00445 ## 00446 # @if jp 00447 # @brief ON_RECEIVER_FULLのリスナへ通知する。 00448 # @param data cdrMemoryStream 00449 # @else 00450 # @brief Notify an ON_RECEIVER_FULL event to listeners 00451 # @param data cdrMemoryStream 00452 # @endif 00453 # 00454 # inline void onReceiverFull(const cdrMemoryStream& data) 00455 def onReceiverFull(self, data): 00456 if self._listeners is not None and self._profile is not None: 00457 self._listeners.connectorData_[OpenRTM_aist.ConnectorDataListenerType.ON_RECEIVER_FULL].notify(self._profile, data) 00458 return 00459 00460 ## 00461 # @if jp 00462 # @brief ON_RECEIVER_TIMEOUTのリスナへ通知する。 00463 # @param data cdrMemoryStream 00464 # @else 00465 # @brief Notify an ON_RECEIVER_TIMEOUT event to listeners 00466 # @param data cdrMemoryStream 00467 # @endif 00468 # 00469 # inline void onReceiverTimeout(const cdrMemoryStream& data) 00470 def onReceiverTimeout(self, data): 00471 if self._listeners is not None and self._profile is not None: 00472 self._listeners.connectorData_[OpenRTM_aist.ConnectorDataListenerType.ON_RECEIVER_TIMEOUT].notify(self._profile, data) 00473 return 00474 00475 ## 00476 # @if jp 00477 # @brief ON_RECEIVER_ERRORのリスナへ通知する。 00478 # @param data cdrMemoryStream 00479 # @else 00480 # @brief Notify an ON_RECEIVER_ERROR event to listeners 00481 # @param data cdrMemoryStream 00482 # @endif 00483 # 00484 # inline void onReceiverError(const cdrMemoryStream& data) 00485 def onReceiverError(self, data): 00486 if self._listeners is not None and self._profile is not None: 00487 self._listeners.connectorData_[OpenRTM_aist.ConnectorDataListenerType.ON_RECEIVER_ERROR].notify(self._profile, data) 00488 return 00489 00490 00491 def PublisherFlushInit(): 00492 OpenRTM_aist.PublisherFactory.instance().addFactory("flush", 00493 OpenRTM_aist.PublisherFlush, 00494 OpenRTM_aist.Delete)