From 347bc0039b82fc73707b65411d2fb477856659dd Mon Sep 17 00:00:00 2001 From: Kei Okada Date: Fri, 19 Dec 2014 17:26:19 +0900 Subject: [PATCH] Imported upstream version '3.0.1' of 'upstream' --- LICENSE.txt | 223 ++ MANIFEST.in | 51 + README.txt | 246 ++ README_ja.txt | 217 ++ bash_completion | 836 +++++++ doc/cheatsheet/cheatsheet.pdf | Bin 0 -> 31392 bytes doc/cheatsheet/cheatsheet.tex | 127 + doc/common/common_body.txt | 84 + doc/common/common_opts.txt | 9 + doc/common/docinfo_block.txt | 7 + doc/common/ja/common_body.txt | 81 + doc/common/ja/common_opts.txt | 9 + doc/common/ja/docinfo_block.txt | 7 + doc/common/ja/start_stop_plans.txt | 45 + doc/common/start_stop_plans.txt | 58 + doc/make_docs | 214 ++ doc/rest/ja/rtact.txt | 59 + doc/rest/ja/rtcat.txt | 74 + doc/rest/ja/rtcheck.txt | 72 + doc/rest/ja/rtcomp.txt | 120 + doc/rest/ja/rtcon.txt | 110 + doc/rest/ja/rtconf.txt | 161 ++ doc/rest/ja/rtcryo.txt | 92 + doc/rest/ja/rtcwd.txt | 61 + doc/rest/ja/rtdeact.txt | 59 + doc/rest/ja/rtdel.txt | 75 + doc/rest/ja/rtdis.txt | 73 + doc/rest/ja/rtdoc.txt | 167 ++ doc/rest/ja/rtexit.txt | 42 + doc/rest/ja/rtfind.txt | 86 + doc/rest/ja/rtinject.txt | 132 ++ doc/rest/ja/rtlog.txt | 256 ++ doc/rest/ja/rtls.txt | 106 + doc/rest/ja/rtmgr.txt | 92 + doc/rest/ja/rtprint.txt | 105 + doc/rest/ja/rtpwd.txt | 29 + doc/rest/ja/rtreset.txt | 58 + doc/rest/ja/rtresurrect.txt | 66 + doc/rest/ja/rtshell.txt | 210 ++ doc/rest/ja/rtstart.txt | 69 + doc/rest/ja/rtstodot.txt | 61 + doc/rest/ja/rtstop.txt | 70 + doc/rest/ja/rtteardown.txt | 61 + doc/rest/ja/rtvlog.txt | 67 + doc/rest/rtact.txt | 61 + doc/rest/rtcat.txt | 78 + doc/rest/rtcheck.txt | 75 + doc/rest/rtcomp.txt | 116 + doc/rest/rtcon.txt | 114 + doc/rest/rtconf.txt | 173 ++ doc/rest/rtcryo.txt | 95 + doc/rest/rtcwd.txt | 61 + doc/rest/rtdeact.txt | 61 + doc/rest/rtdel.txt | 75 + doc/rest/rtdis.txt | 75 + doc/rest/rtdoc.txt | 171 ++ doc/rest/rtexit.txt | 43 + doc/rest/rtfind.txt | 88 + doc/rest/rtinject.txt | 134 ++ doc/rest/rtlog.txt | 260 +++ doc/rest/rtls.txt | 106 + doc/rest/rtmgr.txt | 94 + doc/rest/rtprint.txt | 118 + doc/rest/rtpwd.txt | 37 + doc/rest/rtreset.txt | 60 + doc/rest/rtresurrect.txt | 68 + doc/rest/rtshell.txt | 224 ++ doc/rest/rtstart.txt | 71 + doc/rest/rtstodot.txt | 65 + doc/rest/rtstop.txt | 71 + doc/rest/rtteardown.txt | 63 + doc/rest/rtvlog.txt | 67 + rtact | 32 + rtact.bat | 13 + rtcat | 34 + rtcat.bat | 13 + rtcheck | 32 + rtcheck.bat | 13 + rtcomp | 32 + rtcomp.bat | 13 + rtcon | 32 + rtcon.bat | 13 + rtconf | 34 + rtconf.bat | 13 + rtcryo | 32 + rtcryo.bat | 13 + rtcwd.bat | 15 + rtdeact | 32 + rtdeact.bat | 13 + rtdel | 32 + rtdel.bat | 13 + rtdis | 32 + rtdis.bat | 13 + rtdoc | 31 + rtdoc.bat | 13 + rtexit | 32 + rtexit.bat | 13 + rtfind | 35 + rtfind.bat | 13 + rtinject | 31 + rtinject.bat | 13 + rtlog | 32 + rtlog.bat | 13 + rtls | 35 + rtls.bat | 13 + rtmgr | 32 + rtmgr.bat | 13 + rtprint | 32 + rtprint.bat | 13 + rtpwd | 47 + rtpwd.bat | 13 + rtreset | 32 + rtreset.bat | 13 + rtresurrect | 32 + rtresurrect.bat | 13 + rtshell/__init__.py | 25 + rtshell/actions.py | 807 +++++++ rtshell/comp_mgmt.py | 194 ++ rtshell/fmt.py | 61 + rtshell/gen_comp.py | 219 ++ rtshell/ilog.py | 365 +++ rtshell/modmgr.py | 237 ++ rtshell/option_store.py | 31 + rtshell/path.py | 45 + rtshell/plan.py | 643 +++++ rtshell/port_types.py | 220 ++ rtshell/rtact.py | 35 + rtshell/rtcat.py | 473 ++++ rtshell/rtcheck.py | 229 ++ rtshell/rtcomp.py | 288 +++ rtshell/rtcon.py | 126 + rtshell/rtconf.py | 246 ++ rtshell/rtcryo.py | 302 +++ rtshell/rtcwd.py | 106 + rtshell/rtdeact.py | 35 + rtshell/rtdel.py | 125 + rtshell/rtdis.py | 163 ++ rtshell/rtdoc.py | 270 +++ rtshell/rtexit.py | 99 + rtshell/rtfind.py | 171 ++ rtshell/rtinject.py | 185 ++ rtshell/rtinject_comp.py | 65 + rtshell/rtlog.py | 403 ++++ rtshell/rtlog_comps.py | 271 +++ rtshell/rtls.py | 356 +++ rtshell/rtmgr.py | 223 ++ rtshell/rtprint.py | 147 ++ rtshell/rtprint_comp.py | 42 + rtshell/rtreset.py | 36 + rtshell/rtresurrect.py | 281 +++ rtshell/rts_exceptions.py | 563 +++++ rtshell/rtstart.py | 152 ++ rtshell/rtstodot.py | 154 ++ rtshell/rtstop.py | 128 + rtshell/rtteardown.py | 148 ++ rtshell/rtvlog.py | 128 + rtshell/simpkl_log.py | 406 ++++ rtshell/state_control_base.py | 97 + rtshell/text_log.py | 76 + rtstart | 32 + rtstart.bat | 13 + rtstodot | 32 + rtstodot.bat | 13 + rtstop | 32 + rtstop.bat | 13 + rtteardown | 32 + rtteardown.bat | 13 + rtvlog | 32 + rtvlog.bat | 13 + setup.py | 237 ++ shell_support.in | 20 + test/MyData/__init__.py | 13 + test/MyData__POA/__init__.py | 13 + test/blorg.py | 5 + test/c1.rtlog | Bin 0 -> 1221 bytes test/c1_comp | 89 + test/c2_comp | 94 + test/doc2_comp | 70 + test/doc_comp | 100 + test/err_comp | 73 + test/logfile_unittests.py | 1598 +++++++++++++ test/mp1_comp | 80 + test/output.rtlog | Bin 0 -> 1446 bytes test/output_comp | 78 + test/output_noport_comp | 68 + test/rtc.conf | 13 + test/rtsystem.xml | 112 + test/std.conf | 10 + test/std_comp | 87 + test/sys.dot | 7 + test/sys.rtsys | 36 + test/test.idl | 8 + test/test_cmds.py | 3483 ++++++++++++++++++++++++++++ test/test_idl.py | 40 + test/test_mod1.py | 6 + test/test_mod1__POA.py | 1 + test/test_mod2.py | 1 + test/test_mod2__POA.py | 1 + test/unittests.py | 109 + test/zombie_comp | 77 + 200 files changed, 24684 insertions(+) create mode 100644 LICENSE.txt create mode 100644 MANIFEST.in create mode 100644 README.txt create mode 100644 README_ja.txt create mode 100644 bash_completion create mode 100644 doc/cheatsheet/cheatsheet.pdf create mode 100644 doc/cheatsheet/cheatsheet.tex create mode 100644 doc/common/common_body.txt create mode 100644 doc/common/common_opts.txt create mode 100644 doc/common/docinfo_block.txt create mode 100755 doc/common/ja/common_body.txt create mode 100755 doc/common/ja/common_opts.txt create mode 100644 doc/common/ja/docinfo_block.txt create mode 100755 doc/common/ja/start_stop_plans.txt create mode 100644 doc/common/start_stop_plans.txt create mode 100755 doc/make_docs create mode 100644 doc/rest/ja/rtact.txt create mode 100644 doc/rest/ja/rtcat.txt create mode 100644 doc/rest/ja/rtcheck.txt create mode 100644 doc/rest/ja/rtcomp.txt create mode 100644 doc/rest/ja/rtcon.txt create mode 100644 doc/rest/ja/rtconf.txt create mode 100644 doc/rest/ja/rtcryo.txt create mode 100644 doc/rest/ja/rtcwd.txt create mode 100644 doc/rest/ja/rtdeact.txt create mode 100644 doc/rest/ja/rtdel.txt create mode 100644 doc/rest/ja/rtdis.txt create mode 100644 doc/rest/ja/rtdoc.txt create mode 100644 doc/rest/ja/rtexit.txt create mode 100644 doc/rest/ja/rtfind.txt create mode 100644 doc/rest/ja/rtinject.txt create mode 100644 doc/rest/ja/rtlog.txt create mode 100644 doc/rest/ja/rtls.txt create mode 100644 doc/rest/ja/rtmgr.txt create mode 100644 doc/rest/ja/rtprint.txt create mode 100644 doc/rest/ja/rtpwd.txt create mode 100644 doc/rest/ja/rtreset.txt create mode 100644 doc/rest/ja/rtresurrect.txt create mode 100644 doc/rest/ja/rtshell.txt create mode 100644 doc/rest/ja/rtstart.txt create mode 100644 doc/rest/ja/rtstodot.txt create mode 100644 doc/rest/ja/rtstop.txt create mode 100644 doc/rest/ja/rtteardown.txt create mode 100644 doc/rest/ja/rtvlog.txt create mode 100644 doc/rest/rtact.txt create mode 100644 doc/rest/rtcat.txt create mode 100644 doc/rest/rtcheck.txt create mode 100644 doc/rest/rtcomp.txt create mode 100644 doc/rest/rtcon.txt create mode 100644 doc/rest/rtconf.txt create mode 100644 doc/rest/rtcryo.txt create mode 100644 doc/rest/rtcwd.txt create mode 100644 doc/rest/rtdeact.txt create mode 100644 doc/rest/rtdel.txt create mode 100644 doc/rest/rtdis.txt create mode 100644 doc/rest/rtdoc.txt create mode 100644 doc/rest/rtexit.txt create mode 100644 doc/rest/rtfind.txt create mode 100644 doc/rest/rtinject.txt create mode 100644 doc/rest/rtlog.txt create mode 100644 doc/rest/rtls.txt create mode 100644 doc/rest/rtmgr.txt create mode 100644 doc/rest/rtprint.txt create mode 100644 doc/rest/rtpwd.txt create mode 100644 doc/rest/rtreset.txt create mode 100644 doc/rest/rtresurrect.txt create mode 100644 doc/rest/rtshell.txt create mode 100644 doc/rest/rtstart.txt create mode 100644 doc/rest/rtstodot.txt create mode 100644 doc/rest/rtstop.txt create mode 100644 doc/rest/rtteardown.txt create mode 100644 doc/rest/rtvlog.txt create mode 100755 rtact create mode 100644 rtact.bat create mode 100755 rtcat create mode 100644 rtcat.bat create mode 100755 rtcheck create mode 100644 rtcheck.bat create mode 100755 rtcomp create mode 100644 rtcomp.bat create mode 100755 rtcon create mode 100644 rtcon.bat create mode 100755 rtconf create mode 100644 rtconf.bat create mode 100755 rtcryo create mode 100644 rtcryo.bat create mode 100644 rtcwd.bat create mode 100755 rtdeact create mode 100644 rtdeact.bat create mode 100755 rtdel create mode 100644 rtdel.bat create mode 100755 rtdis create mode 100644 rtdis.bat create mode 100755 rtdoc create mode 100644 rtdoc.bat create mode 100755 rtexit create mode 100644 rtexit.bat create mode 100755 rtfind create mode 100644 rtfind.bat create mode 100755 rtinject create mode 100644 rtinject.bat create mode 100755 rtlog create mode 100644 rtlog.bat create mode 100755 rtls create mode 100644 rtls.bat create mode 100755 rtmgr create mode 100644 rtmgr.bat create mode 100755 rtprint create mode 100644 rtprint.bat create mode 100755 rtpwd create mode 100644 rtpwd.bat create mode 100755 rtreset create mode 100644 rtreset.bat create mode 100755 rtresurrect create mode 100644 rtresurrect.bat create mode 100644 rtshell/__init__.py create mode 100644 rtshell/actions.py create mode 100644 rtshell/comp_mgmt.py create mode 100644 rtshell/fmt.py create mode 100644 rtshell/gen_comp.py create mode 100644 rtshell/ilog.py create mode 100644 rtshell/modmgr.py create mode 100644 rtshell/option_store.py create mode 100644 rtshell/path.py create mode 100644 rtshell/plan.py create mode 100644 rtshell/port_types.py create mode 100644 rtshell/rtact.py create mode 100644 rtshell/rtcat.py create mode 100644 rtshell/rtcheck.py create mode 100644 rtshell/rtcomp.py create mode 100644 rtshell/rtcon.py create mode 100644 rtshell/rtconf.py create mode 100644 rtshell/rtcryo.py create mode 100644 rtshell/rtcwd.py create mode 100644 rtshell/rtdeact.py create mode 100644 rtshell/rtdel.py create mode 100644 rtshell/rtdis.py create mode 100644 rtshell/rtdoc.py create mode 100644 rtshell/rtexit.py create mode 100644 rtshell/rtfind.py create mode 100644 rtshell/rtinject.py create mode 100644 rtshell/rtinject_comp.py create mode 100644 rtshell/rtlog.py create mode 100644 rtshell/rtlog_comps.py create mode 100644 rtshell/rtls.py create mode 100644 rtshell/rtmgr.py create mode 100644 rtshell/rtprint.py create mode 100644 rtshell/rtprint_comp.py create mode 100644 rtshell/rtreset.py create mode 100644 rtshell/rtresurrect.py create mode 100644 rtshell/rts_exceptions.py create mode 100644 rtshell/rtstart.py create mode 100644 rtshell/rtstodot.py create mode 100644 rtshell/rtstop.py create mode 100644 rtshell/rtteardown.py create mode 100644 rtshell/rtvlog.py create mode 100644 rtshell/simpkl_log.py create mode 100644 rtshell/state_control_base.py create mode 100644 rtshell/text_log.py create mode 100755 rtstart create mode 100644 rtstart.bat create mode 100755 rtstodot create mode 100644 rtstodot.bat create mode 100755 rtstop create mode 100644 rtstop.bat create mode 100755 rtteardown create mode 100644 rtteardown.bat create mode 100755 rtvlog create mode 100644 rtvlog.bat create mode 100644 setup.py create mode 100644 shell_support.in create mode 100644 test/MyData/__init__.py create mode 100644 test/MyData__POA/__init__.py create mode 100644 test/blorg.py create mode 100644 test/c1.rtlog create mode 100755 test/c1_comp create mode 100755 test/c2_comp create mode 100755 test/doc2_comp create mode 100755 test/doc_comp create mode 100755 test/err_comp create mode 100755 test/logfile_unittests.py create mode 100755 test/mp1_comp create mode 100644 test/output.rtlog create mode 100755 test/output_comp create mode 100755 test/output_noport_comp create mode 100644 test/rtc.conf create mode 100644 test/rtsystem.xml create mode 100644 test/std.conf create mode 100755 test/std_comp create mode 100644 test/sys.dot create mode 100644 test/sys.rtsys create mode 100644 test/test.idl create mode 100755 test/test_cmds.py create mode 100644 test/test_idl.py create mode 100644 test/test_mod1.py create mode 100644 test/test_mod1__POA.py create mode 100644 test/test_mod2.py create mode 100644 test/test_mod2__POA.py create mode 100755 test/unittests.py create mode 100755 test/zombie_comp diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..6a93b27 --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,223 @@ +Copyright (C) 2009-2014 + Geoffrey Biggs and contributors + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Eclipse Public License -v 1.0 + +THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC +LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM +CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT. + +1. DEFINITIONS + +"Contribution" means: + +a) in the case of the initial Contributor, the initial code and documentation +distributed under this Agreement, and + +b) in the case of each subsequent Contributor: + +i) changes to the Program, and + +ii) additions to the Program; + +where such changes and/or additions to the Program originate from and are +distributed by that particular Contributor. A Contribution 'originates' from a +Contributor if it was added to the Program by such Contributor itself or anyone +acting on such Contributor's behalf. Contributions do not include additions to +the Program which: (i) are separate modules of software distributed in +conjunction with the Program under their own license agreement, and (ii) are +not derivative works of the Program. + +"Contributor" means any person or entity that distributes the Program. + +"Licensed Patents " mean patent claims licensable by a Contributor which are +necessarily infringed by the use or sale of its Contribution alone or when +combined with the Program. + +"Program" means the Contributions distributed in accordance with this +Agreement. + +"Recipient" means anyone who receives the Program under this Agreement, +including all Contributors. + +2. GRANT OF RIGHTS + +a) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free copyright license to +reproduce, prepare derivative works of, publicly display, publicly perform, +distribute and sublicense the Contribution of such Contributor, if any, and +such derivative works, in source code and object code form. + +b) Subject to the terms of this Agreement, each Contributor hereby grants +Recipient a non-exclusive, worldwide, royalty-free patent license under +Licensed Patents to make, use, sell, offer to sell, import and otherwise +transfer the Contribution of such Contributor, if any, in source code and +object code form. This patent license shall apply to the combination of the +Contribution and the Program if, at the time the Contribution is added by the +Contributor, such addition of the Contribution causes such combination to be +covered by the Licensed Patents. The patent license shall not apply to any +other combinations which include the Contribution. No hardware per se is +licensed hereunder. + +c) Recipient understands that although each Contributor grants the licenses to +its Contributions set forth herein, no assurances are provided by any +Contributor that the Program does not infringe the patent or other intellectual +property rights of any other entity. Each Contributor disclaims any liability +to Recipient for claims brought by any other entity based on infringement of +intellectual property rights or otherwise. As a condition to exercising the +rights and licenses granted hereunder, each Recipient hereby assumes sole +responsibility to secure any other intellectual property rights needed, if any. +For example, if a third party patent license is required to allow Recipient to +distribute the Program, it is Recipient's responsibility to acquire that +license before distributing the Program. + +d) Each Contributor represents that to its knowledge it has sufficient +copyright rights in its Contribution, if any, to grant the copyright license +set forth in this Agreement. + +3. REQUIREMENTS + +A Contributor may choose to distribute the Program in object code form under +its own license agreement, provided that: + +a) it complies with the terms and conditions of this Agreement; and + +b) its license agreement: + +i) effectively disclaims on behalf of all Contributors all warranties and +conditions, express and implied, including warranties or conditions of title +and non-infringement, and implied warranties or conditions of merchantability +and fitness for a particular purpose; + +ii) effectively excludes on behalf of all Contributors all liability for +damages, including direct, indirect, special, incidental and consequential +damages, such as lost profits; + +iii) states that any provisions which differ from this Agreement are offered by +that Contributor alone and not by any other party; and + +iv) states that source code for the Program is available from such Contributor, +and informs licensees how to obtain it in a reasonable manner on or through a +medium customarily used for software exchange. + +When the Program is made available in source code form: + +a) it must be made available under this Agreement; and + +b) a copy of this Agreement must be included with each copy of the Program. + +Contributors may not remove or alter any copyright notices contained within the +Program. + +Each Contributor must identify itself as the originator of its Contribution, if +any, in a manner that reasonably allows subsequent Recipients to identify the +originator of the Contribution. + +4. COMMERCIAL DISTRIBUTION + +Commercial distributors of software may accept certain responsibilities with +respect to end users, business partners and the like. While this license is +intended to facilitate the commercial use of the Program, the Contributor who +includes the Program in a commercial product offering should do so in a manner +which does not create potential liability for other Contributors. Therefore, if +a Contributor includes the Program in a commercial product offering, such +Contributor ("Commercial Contributor") hereby agrees to defend and indemnify +every other Contributor ("Indemnified Contributor") against any losses, damages +and costs (collectively "Losses") arising from claims, lawsuits and other legal +actions brought by a third party against the Indemnified Contributor to the +extent caused by the acts or omissions of such Commercial Contributor in +connection with its distribution of the Program in a commercial product +offering. The obligations in this section do not apply to any claims or Losses +relating to any actual or alleged intellectual property infringement. In order +to qualify, an Indemnified Contributor must: a) promptly notify the Commercial +Contributor in writing of such claim, and b) allow the Commercial Contributor +to control, and cooperate with the Commercial Contributor in, the defense and +any related settlement negotiations. The Indemnified Contributor may +participate in any such claim at its own expense. + +For example, a Contributor might include the Program in a commercial product +offering, Product X. That Contributor is then a Commercial Contributor. If that +Commercial Contributor then makes performance claims, or offers warranties +related to Product X, those performance claims and warranties are such +Commercial Contributor's responsibility alone. Under this section, the +Commercial Contributor would have to defend claims against the other +Contributors related to those performance claims and warranties, and if a court +requires any other Contributor to pay any damages as a result, the Commercial +Contributor must pay those damages. + +5. NO WARRANTY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN +"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR +IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, +NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each +Recipient is solely responsible for determining the appropriateness of using +and distributing the Program and assumes all risks associated with its exercise +of rights under this Agreement , including but not limited to the risks and +costs of program errors, compliance with applicable laws, damage to or loss of +data, programs or equipment, and unavailability or interruption of operations. + +6. DISCLAIMER OF LIABILITY + +EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY +CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST +PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS +GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. + +7. GENERAL + +If any provision of this Agreement is invalid or unenforceable under applicable +law, it shall not affect the validity or enforceability of the remainder of the +terms of this Agreement, and without further action by the parties hereto, such +provision shall be reformed to the minimum extent necessary to make such +provision valid and enforceable. + +If Recipient institutes patent litigation against any entity (including a +cross-claim or counterclaim in a lawsuit) alleging that the Program itself +(excluding combinations of the Program with other software or hardware) +infringes such Recipient's patent(s), then such Recipient's rights granted +under Section 2(b) shall terminate as of the date such litigation is filed. + +All Recipient's rights under this Agreement shall terminate if it fails to +comply with any of the material terms or conditions of this Agreement and does +not cure such failure in a reasonable period of time after becoming aware of +such noncompliance. If all Recipient's rights under this Agreement terminate, +Recipient agrees to cease use and distribution of the Program as soon as +reasonably practicable. However, Recipient's obligations under this Agreement +and any licenses granted by Recipient relating to the Program shall continue +and survive. + +Everyone is permitted to copy and distribute copies of this Agreement, but in +order to avoid inconsistency the Agreement is copyrighted and may only be +modified in the following manner. The Agreement Steward reserves the right to +publish new versions (including revisions) of this Agreement from time to time. +No one other than the Agreement Steward has the right to modify this Agreement. +The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation +may assign the responsibility to serve as the Agreement Steward to a suitable +separate entity. Each new version of the Agreement will be given a +distinguishing version number. The Program (including Contributions) may always +be distributed subject to the version of the Agreement under which it was +received. In addition, after a new version of the Agreement is published, +Contributor may elect to distribute the Program (including its Contributions) +under the new version. Except as expressly stated in Sections 2(a) and 2(b) +above, Recipient receives no rights or licenses to the intellectual property of +any Contributor under this Agreement, whether expressly, by implication, +estoppel or otherwise. All rights in the Program not expressly granted under +this Agreement are reserved. + +This Agreement is governed by the laws of the State of New York and the +intellectual property laws of the United States of America. No party to this +Agreement will bring a legal action under this Agreement more than one year +after the cause of action arose. Each party waives its rights to a jury trial +in any resulting litigation. + diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..054d59d --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,51 @@ +include LICENSE.txt +include README.txt +include rtact +include rtact.bat +include rtcat +include rtcat.bat +include rtcheck +include rtcheck.bat +include rtcomp +include rtcomp.bat +include rtcon +include rtcon.bat +include rtconf +include rtconf.bat +include rtcryo +include rtcryo.bat +include rtcwd.bat +include rtdeact +include rtdeact.bat +include rtdel +include rtdel.bat +include rtdis +include rtdis.bat +include rtexit +include rtexit.bat +include rtfind +include rtfind.bat +include rtinject +include rtinject.bat +include rtlog +include rtlog.bat +include rtls +include rtls.bat +include rtmgr +include rtmgr.bat +include rtprint +include rtprint.bat +include rtpwd +include rtpwd.bat +include rtreset +include rtreset.bat +include rtresurrect +include rtresurrect.bat +include rtstart +include rtstart.bat +include rtstop +include rtstop.bat +include rtteardown +include rtteardown.bat +include bash_completion +include shell_support diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..9d097e1 --- /dev/null +++ b/README.txt @@ -0,0 +1,246 @@ +======= +rtshell +======= + +Introduction +============ + +rtshell provides commands used to manage individual RT components and +managers, as well as complete RT Systems. It can be used with the +OpenRTM-aist middleware or middlewares that use a compatible CORBA-based +introspection system. + +Many of the commands allow components and managers running on +nameservers to be treated like a file system. Directories can be +entered, components can be cat'd and activated/deactivated/reset, +connections made and removed, and so on. + +Other commands are used in conjunction with RtsProfile XML/YAML files to +manage complete RT Systems. These are rtresurrect, rtteardown, rtcryo, +rtstart and rtstop. + +The commands are aimed at users of OpenRTM-aist who wish to manage +components on low-resource systems, systems where a GUI is not available +(particularly where no network connection is available to manage +components from another computer), as well as those who face other +difficulties using RTSystemEditor. Being familiar with using a +command-line is a benefit when using these commands of rtshell. + +This software is developed at the National Institute of Advanced +Industrial Science and Technology. Approval number +H23PRO-1214. The development was financially supported by +the New Energy and Industrial Technology Development Organisation +Project for Strategic Development of Advanced Robotics Elemental +Technologies. This software is licensed under the Eclipse Public +License -v 1.0 (EPL). See LICENSE.txt. + + +Requirements +============ + +rtshell requires rtctree 3.0. It must be installed for the commands to +function. + +The commands that work with RtsProfile files require rtsprofile 2.0. It +must be installed for these commands to function/ + +rtshell uses the new string formatting operations that were introduced +in Python 2.6. It will not function with an earlier version of Python. +It has not been tested with Python 3 and it is likely that several +changes will be necessary to make it function using this version of +Python. + +rtprint, rtinject and rtlog require the Python version of OpenRTM-aist. + +For Ubuntu users, if you are using a version of Ubuntu prior to 9.04, +you will need to install a suitable Python version by hand. You may want +to consider upgrading to Ubuntu 9.04 or later (10.04 offers LTS). + + +Installation +============ + +There are several methods of installation available: + + 1. Download the source from either the repository (see "Repository," + below) or a source archive, extract it somewhere, and run the commands + from that directory. + + 2. Download the source from either the repository (see "Repository," + below) or a source archive, extract it somewhere, and install it into + your Python distribution: + + a) Extract the source, e.g. to a directory ~/rtshell:: + + $ cd /home/blurgle/src/ + $ tar -xvzf rtshell-3.0.0.tar.gz + + b) Run setup.py to install rtshell to your default Python + installation:: + + $ python setup.py install + + c) If necessary, set environment variables. These should be set by + default, but if not you will need to set them yourself. On Windows, + you will need to ensure that your Python site-packages directory is + in the PYTHONPATH variable and the Python scripts directory is in + the PATH variable. Typically, these will be something like + ``C:\Python26\Lib\site-packages\`` and ``C:\Python26\Scripts\``, + respectively (assuming Python 2.6 installed in ``C:\Python26\``). + + 3. Use the Windows installer. This will perform the same job as running + setup.py (see #2), but saves opening a command prompt. You may still need to + add paths to your environment variables (see step c, above). + + 4. In non-Windows operating systems, you must source the shell support + file to gain full functionaliy. Amongst other things, rtcwd will not + work without sourcing this file. You can find this file at + ``${prefix}/share/rtshell/shell_support`` (``${prefix}`` is the + directory where you installed rtshell). You can source it by running + the following command (assuming rtshell has been installed to + ``/usr/local``):: + + source /usr/local/share/rtshell/shell_support + + So that you don't have to run this command every time you open a + terminal, you can add it to your shell's startup file. For example, if + you are using a bash shell and installed rtshell to ``/usr/local``, add + the following line to the ``.bashrc`` file in your home directory:: + + source /usr/local/share/rtshell/shell_support + + +Repository +========== + +The latest source is stored in a Git repository at github, available at +``http://github.com/gbiggs/rtshell``. You can download it as a zip file +or tarball by clicking the "Download Source" link in the top right of +the page. Alternatively, use Git to clone the repository. This is +better if you wish to contribute patches:: + + $ git clone git://github.com/gbiggs/rtshell.git + + +Documentation +============= + +Documentation is available in the form of man pages (on Windows, these +are available as HTML files). These will be installed under +``${prefix}/share/man``. You must add this folder to your system's +``$MANPATH`` environment variable to be able to use them. For example, +if you installed rtshell into /usr/local, add the following line to your +``.bashrc``:: + + export MANPATH=/usr/local/share/man:${MANPATH} + + +Running the tests +================= + +The command tests can be run from the source directory using a command +like the following:: + +~/src/rtshell $ ./test/test_cmds.py ~/share/OpenRTM-aist/examples/rtcs/ + +The argument to the test_cmds.py command is a directory containing RTC +shared libraries that can be loaded into a manager. It must contain the +libraries for Motor, Controller and Sensor. + +An individual command's tests can be run by specifying those tests after +the command. For example:: + +$ ./test/test_cmds.py ~/share/OpenRTM-aist/examples/rtcs/ rtactTests + +This will run only the tests for the rtact command. + + +Changelog +========= + +4.0 +--- + +- Fixed saving and restoring connection properties. +- Fixed disabling output of colour codes on Windows +- Adapt to OpenRTM's new data type specification method. +- Changed all os.sep occurrences to '/' for consistency with URLs. +- New command: rtvlog (Display RT Component log events). +- rtact/rtdeact/rtreset: Allow changing multiple components at once. +- rtcomp: Support managing compositions of remote components. +- rtcon: Support making connections involving three or more ports. +- rtdis: Support removing connections involving three or more ports. +- rtlog: Added end pointer to simpkl log format to speed up searches. +- rtmgr: Support corbaloc:: direct connection to managers. +- rtmgr: Allow multiple occurrences of any commands. +- rtmgr: Execute commands in the order specified. + +3.0.1 +----- + +- Fixed #13: Error with unknown ports when saving systems using rtcryo. +- Fixed #14/#15: Properly handle data types that include versions and IDL + paths in rtprint. +- Fixed #16: Handle component instance names that include parantheses. + +3.0 +--- + +- Merged rtcshell and rtsshell into a single toolkit. +- Added complete documentation for every command (man pages, HTML, PDF). +- New command: rtdoc (Print component documentation - thanks to Yosuke + Matsusaka). +- New command: rtexit (Make a component exit). +- New command: rtlog (Log and replay data streams). +- New command: rtcheck (Check a system matches an RtsProfile file). +- New command: rtcomp (Create composite components). +- New command: rtstodot (Visualise RT Systems - thanks to Yosuke Matsusaka). +- New command: rtvis +- rtconf bash completion now completes set names, parameter names and values. +- Merged rtcwd and bash_completion bash files into a single file. +- Overhauled rtconf command line, added option to get a parameter value + directly. +- Handle zombies properly. +- Display zombies in rtls. +- Delete zombies in rtdel (including all zombies found). +- Support path filters in rtctree to speed up tree creation. +- rtcat: Option to print a single port's information. +- rtcat: Changes --ll to -ll. +- rtcat: Display information about composite components. +- rtcryo: Print RtsProfile to standard output by default. +- rtdis: Disconnect-by-ID allows removing only one connection. +- rtinject/rtprint: Added support for user data types. +- rtprint: Option to exit after receiving one round of data. +- rtprint: Added support for user-defined formatters. +- rtprint: Added ability to print raw Python code. +- rtinject: Accept raw Python input from stdin. +- rtresurrect: Don't recreate existing connections. +- rtteardown: Fail if the connector ID doesn't match. +- rtresurrect/rtstart/rtstop/rtteardown: Accept input from standard input. +- Refactored former rtsshell commands into rtshell-style libraries. +- Added tests. + + +rtcshell-2.0 +------------ + +- Fixes for Windows +- Fixed problems handling paths referencing parent directories +- New command: rtdel +- New command: rtinject +- New command: rtprint +- rtcat: Print the number of unknown connections +- Major refactoring: all commands can now be imported and called from Python + scripts easily +- New Bash completion script (thanks to Keisuke Suzuki) +- Support csh in rtcwd +- rtcat: Print new information available from rtctree for execution contexts +- rtls: Change recurse option from -r to -R to match ls +- rtls: Handle unknown objects; display them like dead files + +rtsshell-2.0 +------------ + +- Added bash-completion script. +- Added planning capability. + diff --git a/README_ja.txt b/README_ja.txt new file mode 100644 index 0000000..8125f00 --- /dev/null +++ b/README_ja.txt @@ -0,0 +1,217 @@ +======= +rtshell +======= + +イントロダクション +================== + +rtcshell は、ネームサーバ上に登録されているRTコンポーネントをシェルから +管理することができるツールです。コンポーネントを +activate/deactivate/resetしたり、ポートの接続を行うことができます。RTシ +ステムを管理することもできます。 + +このツールは、リソースの少ないシステム、GUIが利用できない環境(特に、コン +ポーネントを管理する他のPCとネットワークがつながっていない環境等)、ある +いはRTSystemEditorがどうしても利用できない場合等に有効です。コマンドライ +ンの利用に精通している人にとっては特に便利なツールです。 + +このソフトウエアはNEDO (独立行政法人 新エネルギー・産業技術総合開発機構) +の次世代ロボット知能化技術開発プロジェクトの支援により、独立行政法人産業 +技術総合研究所によって開発されています。管理番号H23PRO-1214. + +This software is licensed under the Eclipse Public License -v 1.0 (EPL). +See LICENSE.txt. + + +必要条件 +======== + +- rtctree 3.0以上が必要となります. + +- rtsprofile-2.0 が必要となります。 + +- Python 2.5以下では存在しない機能を使うので、Python 2.6以上が必要となり + ます。 + +- rtprint、rtinjectおよびrtlogはOpenRTM-Python-1.0.0以上が必要となります。 + +- Ubuntu 9.04を使っていたら、手動でPython 2.6をインストールすることが必 + 要となります。Ubuntu 9.04以上をおすすめします。 + + +インストール +============ + +インストールはいくつかの方法が利用可能です。 + + 1.リポジトリまたはソースアーカイブからダウンロード後、適当なディレクト + リで解凍し、そこでコマンドを実行する。 + + 2.リポジトリまたはソースアーカイブからダウンロード後、適当なディレクト + リで解凍し、インストールする。 + + a) ソースを展開する:: + + $ cd /home/blurgle/src/ + $ tar -xvzf rtshell-3.0.0.tar.gz + + b) setup.pyを実行する:: + + $ python setup.py install + + c) 必要に応じて、環境変数を設定します。これはデフォルトで設定されて + いますが、設定されていない場合は自分で設定する必要があります。 + Windows上では、Python の site-packages ディレクトリが ``PYTHONPATH`` + 環境変数に、Pythonスクリプトのディレクトリが PATH 環境変数に設定され + ていることを確認してください。通常、これらは + ``C:\Python26\Lib\site-packages\`` と ``C:\Python26\Scripts\`` + です(Pythonが``C:\Python26\``にインストールされた場合)。 + + 3. Windows ではインストーラの使用を推奨します。``setup.py`` を利用すれ + ば結果より容易に設定することができます。ただし、環境によってはさらに環 + 境変数の設定が必要な場合があります。 + + 4. Windows ではない場合、シェルスクリプトをインストールする必要です。 + ``${prefix}/share/rtshell/shell_support``(${prefix}はrtcshellをインス + トールされたディレクトリです。)というファイルを``source``コマンドに + よってロードしてください(例はrtshellが``/usr/local``にインストールさ + れた場合):: + + source /usr/local/share/rtshell/shell_support + + いつも新しいシェルを実効する時に以上のコマンドを実効することは必要な + いように以下の行を``.bashrc``などのファイルに追加してください + (rtshellが``/usr/local``にインストールsされた場合):: + + source /usr/local/share/rtshell/shell_support + + +リポジトリ +========== + +最新版のソースはgithubでGitのリポジトリにあります(URL: +``http://github.com/gbiggs/rtshell`` )。「Download +source」をクリックしてダウンロードをすることができます。「git +clone」を使うこともできます。パッチを送りたがったら、この方法がおすすめ +します:: + + $ git clone git://github.com/gbiggs/rtshell.git + + +ドキュメント +============ + +ドキュメントはマンページとして提供します(Windowsの場合はHTMLに提供しま +す)。``${prefix}/share/man``にインストールされます。このパスを +``$MANPATH``という環境変数に追加する必要です。例えば、rtshellは +``/usr/local``にインストールされた場合、以下の行を``.bashrc``に追加して +ください:: + + export MANPATH=/usr/local/share/man:${MANPATH} + + +テストの実効 +============ + +コマンドのテストはソースダイレクトリから実効することができます:: + +~/src/rtshell $ ./test/test_cmds.py ~/share/OpenRTM-aist/examples/rtcs/ + +変数はRTCのモジュールを持つダイレクトリです。``Motor``、``Controller`` +および``Sensor``のモジュールが必要です。 + +一つのコマンドのテストだけを実効するの場合、そのテストの名を変数に追加 +してください:: + +$ ./test/test_cmds.py ~/share/OpenRTM-aist/examples/rtcs/ rtactTests + + +Changelog +========= + +4.0 +--- + +- コネクタプロパティの保存と復活を直した。 +- Windowsで色字の出力を消した。 +- OpenRTMの新しいデー多型表地方に従う。 +- URLに合わせるために全部のos.sepを'/'に変更しました。 +- 新しいコマンド:rtvlog(コンポーネントのログメッセージの表示) +- rtact/rtdeact/rtreset:一つのコマンドで複数のコンポーネントを変更 + できるようにしました。 +- rtcomp: 分散コンポーネントの管理を可能にしました。 +- rtcon:三つ以上のポートを一つのコネクションで接続できるようにしました。 +- rtdis:三つ以上のポートを一つのコネクションを消せるようにしました。 +- rtlog:simpklログフォーマットに最後のレコードのポインタを追加しました。 +- rtmgr:「corbaloc::」アドレスによって直接マネージャにつながれるように + しました。 +- rtmgr:コマンドを複数回に使えるようにしました。 +- rtmgr:コマンドを指定された順番に実行するようにしました。 + +3.0.1 +----- + +- Fixed #13: Error with unknown ports when saving systems using rtcryo. +- Fixed #14/#15: Properly handle data types that include versions and IDL + paths in rtprint. +- Fixed #16: Handle component instance names that include parantheses. + + +3.0 +--- + +- rtcshellとrtsshellをマージしました。 +- コマンドのドキュメントを作成しました。 +- 新しいコマンド:rtdoc(コンポーネントのドキュメントを表示するー松坂様より) +- 新しいコマンド:rtexit(コンポーネントを終了する) +- 新しいコマンド:rtlog(ログの記録と再生を行う) +- 新しいコマンド:rtcheck(起動中のRTシステムと、保存されたRTSProfileとを比較する) +- 新しいコマンド:rtcomp(コンポジットコンポーネントを作る) +- 新しいコマンド:rtstodot(起動中のRTシステムをグラフで表示するー松坂様より) +- 新しいコマンド:rtvis(起動中のRTシステムをグラフで表示する) +- rtconfのセット名、パラメータ名及び値の変更の際にbash補間機能を使えるように対応しました。 +- シェルサポートファイルをマージしました。 +- rtconfのコマンドラインを作り直しました。 +- ゾンビオブジェクトに対応しました。 +- rtlsでゾンビを表示するようにしました。 +- rtdelで全てのゾンビを消せるようにしました。 +- rtctreeでの木構造を早く作成するために、パスフィルターをサポートしました。 +- rtcat:一個のポートの情報だけを表示するオプションを追加しました。 +- rtcat:--llを-llに変更しました。 +- rtcat:コンポジットコンポーネントの情報を表示します。 +- rtcryo:RtsProfileを標準出力に出します。 +- rtdis:IDによってコネクションを削除するオプションを追加しました。 +- rtinject/rtprint:ユーザ定義のデータ型に対応しました。 +- rtprint:データを一回もらって終了するオプションを追加しました。 +- rtprint:ユーザ定義のデータフォーマッタを対応しました。 +- rtprint:Pythonの生データを表示するオプションを追加しました。 +- rtinject:標準入力からPythonの生データを使えるようにしました。 +- rtresurrect:既に存在する接続を再作成しないようにしました。 +- rtteardown:コネクタIDが合わない場合エラーを出して終了します。 +- rtresurrect/rtstart/rtstop/rtteardown:標準入力で入力を受けとります。 +- rtsshellからのコマンドをライブラリとして使用できるようにしました。 +- テストを追加しました。 + + +rtcshell-2.0 +------------ + +- Windows対応のための調整。 +- 親ディレクトリを示すパスの扱い方を修正しました。 +- 新しいコマンド:rtdel +- 新しいコマンド:rtinject +- 新しいコマンド:rtprint +- rtcat:未知の接続の数を表示します。 +- リファクタリング:全てのコマンドをPythonのスクリプトからも簡単に使えるようにしました。 +- シェル補完機能の追加(鈴木圭介氏より提供) +- rtcwdをcsh系のシェルで使用できるようにしました。 +- rtcat:rtctreeから取得できるようになった実行コンテキストに関する新しい情報を表示します。 +- rtls:lsと一致するように再帰オプションを-rから-Rにの変更しました。 +- rtls:未知のオブジェクトを死んだファイルとして表示します。 + +rtsshell-2.0 +------------ + +- シェル補完機能の追加(鈴木圭介氏より提供) +- プランニングの機能の追加 + diff --git a/bash_completion b/bash_completion new file mode 100644 index 0000000..b2a57cb --- /dev/null +++ b/bash_completion @@ -0,0 +1,836 @@ +# rtshell Bash completion +# +# Copyright (C) 2009-2014 +# Keisuke Suzuki and Geoffrey Biggs +# RT-Synthesis Research Group +# Intelligent Systems Research Institute, +# National Institute of Advanced Industrial Science and Technology (AIST), +# Japan +# All rights reserved. +# Licensed under the Eclipse Public License -v 1.0 (EPL) +# http://www.opensource.org/licenses/eclipse-1.0.txt + + +# Overview +# +# Adds tab-completion functionality to rtshell. Can complete command options, +# directories, objects, ports and configuration parameter names. +# +# rtshellにbashの補完機能を追加するbash-completionスクリプト。 +# コマンドオプションやディレクトリ、オブジェクト、ポート、パラメータ名を補完。 +# +# Usage +# +# $ source ${prefix}/share/rtshell/bash_completion +# +# Example: Directory completion / ディレクトリ名補完 +# +# $ rtcwd [TAB] +# $ rtcwd localhost/ +# $ rtcwd localhost/[TAB] +# $ rtcwd localhost/foo.host_cxt/ +# $ rtcwd localhost/foo.host_cxt/[TAB][TAB] +# foo.rtc bar.rtc manager.mgr +# $ rtcwd localhost/foo.host_cxt/[ENTER] +# +# Example: Configuration parameter completion / パラメータ名補完 (rtconf) +# +# $ rtconf foo.rtc set [TAB] +# param1 param2 param3 +# +# Example: ポート名補完 (only rtcon rtdis) +# +# $ rtcon foo.rtc:[TAB] +# fooIn barIn fooOut barOut +# + + +# Command option completion +# Usage : _rtsbc_rtopts ${COMP_WORDS[COMP_CWORD]} +# _rtsbc_rtopts ${cur} +# Receives the currently-being-entered word. +_rtsbc_rtopts() +{ + local opts complist + + case ${COMP_WORDS[0]} in + *rtact) opts="--version -h --help -v --verbose -e --exec_context=" + ;; + *rtcat) opts="--version -h --help -v --verbose -l -ll" + ;; + *rtcheck) opts="--version -h --help -v --verbose --dry-run -s --state= -x --xml -y --yaml" + ;; + *rtcwd) opts="" + ;; + *rtcomp) opts="--version -h --help -v --verbose -c --comp= -n --name= -o --options= -p --port= -t --type=" + ;; + *rtcon) opts="--version -h --help -v --verbose -i --id= -n --name= -p --property=" + ;; + *rtconf) opts="--version -h --help -v --verbose -l -s --set= -a --all" + ;; + *rtcryo) opts="--version -h --help -v --verbose -a --abstract= -n --system-name= -o --output= -v --system-version= -e --vendor= --verbose" + ;; + *rtdeact) opts="--version -h --help -v --verbose -e --exec_context=" + ;; + *rtdel) opts="--version -h --help -v --verbose -z --zombies" + ;; + *rtdis) opts="--version -h --help -v --verbose -i --id" + ;; + *rtexit) opts="--version -h --help -v --verbose" + ;; + *rtfind) opts="--version -h --help -v --verbose --maxdepth= --iname= --name= --type=" + ;; + *rtinject) opts="--version -h --help -v --verbose -c --const= -m --mod= -n --number= -r --rate= -t --timeout=" + ;; + *rtlog) opts="--version -h --help -v --verbose -a --absolute-times -d --display-info -e --end= -f --filename= -i --index -l --logger= -m --mod= -n --ignore-times -p --play -r --rate= -s --start= -t --timeout= -x --exec-rate=" + ;; + *rtls) opts="--version -h --help -v --verbose -l -r --recurse" + ;; + *rtmgr) opts="--version -h --help -v --verbose -c --create= -d --delete= -l --load= -u --unload=" + ;; + *rtprint) opts="--version -h --help -v --verbose -m --mod= -n --number= -r --rate= -t --timeout=" + ;; + *rtreset) opts="--version -h --help -v --verbose -e --exec_context=" + ;; + *rtresurrect) opts="--version -h --help -v --verbose --dry-run" + ;; + *rtstart) opts="--version -h --help -v --verbose --dry-run" + ;; + *rtstop) opts="--version -h --help -v --verbose --dry-run" + ;; + *rtteardown)opts="--version -h --help -v --verbose --dry-run" + ;; + *) ;; + esac + + complist=$(compgen -W "${opts} ${nospaceopts}" -- $1) + + # If there is an = then don't add a space + if [[ ${complist} == *= ]] ; then + @COMPOPT_NOSPACE@ + fi + + COMPREPLY=(${complist}) + return 0 + +} + +# Complete object names +# Usage : _rtsbc_rtobj ${COMP_WORDS[COMP_CWORD]} +# _rtsbc_rtobj ${cur} +# _rtsbc_rtobj ${cur} port (when completing port names) +# Receives the currently-being-entered word. +_rtsbc_rtobj() +{ + local objs obj target_dir target_abs target_objs nospace + + target_objs="" + + target_dir=`echo $1 | sed -e 's/\/[^\/]*$/\//g'` + + if [[ ${target_dir} != */ ]] ; then + target_dir="" + fi + + # Use col to remove colour codes + objs=$(rtls ${target_dir} 2> /dev/null | col | sed 's/00m//g' | sed 's/*//g') + + target_objs="" + for obj in ${objs} ; do + target_objs="${target_objs} ${target_dir}${obj}" + done + + target_objs=($(compgen -o nospace -W "${target_objs}" -- $1)) + + if [[ ${#target_objs[@]} == 1 ]] ; then + # If the completion target is a directory or port, no space + if [[ ${target_objs[0]} == */ ]] || [[ ${target_objs[0]} == *: ]] ; then + @COMPOPT_NOSPACE@ + elif [[ $2 == port ]] ; then + target_objs[0]="${target_objs[0]}:" + @COMPOPT_NOSPACE@ + fi + fi + + COMPREPLY=(${target_objs[@]}) +} + +_rtsbc_rtls() +{ + local cur prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + _rtsbc_rtobj ${cur} + return 0 +} + +_rtsbc_rtcat() +{ + local cur prev preprev colonopt + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + # : is treated the same as a space for separating variables + # Port completion 1 + if [[ ${cur} == : ]] ; then + colonopt=$(rtcat ${prev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }') + COMPREPLY=(${colonopt}) + return 0 + fi + + # Port completion 2 + if [[ ${prev} == : ]] ; then + preprev="${COMP_WORDS[COMP_CWORD-2]}" + colonopt=`rtcat ${preprev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }'` + COMPREPLY=($(compgen -W "${colonopt}" -- ${cur})) + return 0 + fi + + _rtsbc_rtobj "${cur}" port + return 0 +} + +_rtsbc_rtcomp() +{ + local cur prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${prev} == *rtcomp ]] + then + _rtsbc_rtobj ${cur} + return 0 + fi + + if [[ ${cur} == -* ]] ; + then + _rtsbc_rtopts ${cur} + return 0 + fi + + if [[ ${cur} == : ]] ; then + colonopt=$(rtcat ${prev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }') + COMPREPLY=(${colonopt}) + return 0 + fi + + case "${prev}" in + --comp|-c) + # Component path + _rtsbc_rtobj "${cur}" + return 0 + ;; + --port|-p) + # Port path + _rtsbc_rtobj "${cur}" port + return 0 + ;; + :) + preprev="${COMP_WORDS[COMP_CWORD-2]}" + colonopt=`rtcat ${preprev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }'` + COMPREPLY=($(compgen -W "${colonopt}" -- ${cur})) + return 0 + ;; + *) + return 0 + ;; + esac + + return 0 +} + +_rtsbc_rtcon() +{ + local cur prev preprev colonopt + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + # : is treated the same as a space for separating variables + # Port completion 1 + if [[ ${cur} == : ]] ; then + colonopt=$(rtcat ${prev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }') + COMPREPLY=(${colonopt}) + return 0 + fi + + # Port completion 2 + if [[ ${prev} == : ]] ; then + preprev="${COMP_WORDS[COMP_CWORD-2]}" + colonopt=`rtcat ${preprev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }'` + COMPREPLY=($(compgen -W "${colonopt}" -- ${cur})) + return 0 + fi + + _rtsbc_rtobj "${cur}" port + return 0 +} + +_rtsbc_conid() +{ + # $1 = path + # $2 = current word + local cur=${2#=} + local ids=$(rtcat ConsoleIn0.rtc:out -ll | grep ID | awk '{print $2}') + COMPREPLY=($(compgen -W "${ids}" -- ${cur})) + return 0 +} + +_rtsbc_rtdis() +{ + local cur prev preprev colonopt + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + case "${prev}" in + -i|--id) + _rtsbc_conid "${COMP_WORDS[1]}" "${cur}" + return 0 + ;; + esac + + # : is treated the same as a space for separating variables + # Port completion 1 + if [[ ${cur} == : ]] ; then + colonopt=$(rtcat ${prev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }') + COMPREPLY=(${colonopt}) + return 0 + fi + + # Port completion 2 + if [[ ${prev} == : ]] ; then + preprev="${COMP_WORDS[COMP_CWORD-2]}" + colonopt=`rtcat ${preprev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }'` + COMPREPLY=($(compgen -W "${colonopt}" -- ${cur})) + return 0 + fi + + _rtsbc_rtobj "${cur}" port + return 0 +} + +_rtsbc_get_set_opt_val() +{ + SET_OPT_VAL="$(grep ' \-s \| \-\-set=' <<< ${COMP_WORDS[@]} | \ + sed 's/.* \(-s \|--set=\)\([a-zA-Z0-9_]\+\).*/\2/')" + return 0 +} + +_rtsbc_check_hidden() +{ + if $(grep -q ' \-a \| \-\-all ' <<< ${COMP_WORDS[@]}) + then + ALL_SETS="-a" + else + ALL_SETS="" + fi + return 0 +} + +_rtsbc_rtconf_set_name() +{ + # $1 = path + # $2 = current word + _rtsbc_check_hidden + local cur=${2#=} + local setnames=$(rtconf ${1} ${ALL_SETS} 2> /dev/null | sed 's/^+//' | sed 's/*$//') + COMPREPLY=($(compgen -W "${setnames}" -- ${cur})) + return 0 +} + +_rtsbc_rtconf_param_name() +{ + # $1 = path + # $2 = current word + local params + _rtsbc_get_set_opt_val + _rtsbc_check_hidden + if [[ "${SET_OPT_VAL}" == "" ]]; then + # Param in active set + params=$(rtconf ${1} ${ALL_SETS} -l 2> /dev/null | \ + sed -n '/^-/{:1;p;n;/^-/q;b1};p' | grep '^ ' | awk '{print $1}') + COMPREPLY=($(compgen -W "${params}" -- ${2})) + else + # Param in specific set + params=$(rtconf ${1} ${ALL_SETS} -s ${SET_OPT_VAL} -l 2> /dev/null | \ + sed -n '/^-/{:1;p;n;/^-/q;b1};p' | grep '^ ' | awk '{print $1}') + COMPREPLY=($(compgen -W "${params}" -- ${2})) + fi + return 0 +} + +_rtsbc_rtconf_param_val() +{ + # $1 = path + # $2 = param + # $3 = current word + local val + _rtsbc_get_set_opt_val + _rtsbc_check_hidden + if [[ "${SET_OPT_VAL}" == "" ]]; then + # Param in active set + val="\"$(rtconf ${1} ${ALL_SETS} get ${2} 2> /dev/null)\"" + COMPREPLY=($(compgen -W "${val}" -- ${3})) + else + # Param in specific set + val="\"$(rtconf ${1} ${ALL_SETS} -s ${SET_OPT_VAL} get ${2} 2> /dev/null)\"" + COMPREPLY=($(compgen -W "${val}" -- ${3})) + fi + return 0 +} + +_rtsbc_rtconf_set() +{ + local cur set_name + cur="${COMP_WORDS[COMP_CWORD]}" + + case ${COMP_WORDS[COMP_CWORD - 1]} in + set) # No param yet - complete parameter names + _rtsbc_rtconf_param_name "${COMP_WORDS[1]}" "${cur}" + ;; + *) # Have a param name - complete value + _rtsbc_rtconf_param_val "${COMP_WORDS[1]}" \ + "${COMP_WORDS[COMP_CWORD - 1]}" "${cur}" + ;; + esac + return 0 +} + +_rtsbc_rtconf() +{ + local cur prev confopts setopt + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD - 1]}" + + confopts="set get list act" + + if [[ ${prev} == *rtconf ]] + then + _rtsbc_rtobj ${cur} + return 0 + fi + + if [[ ${cur} == -* ]] + then + _rtsbc_rtopts ${cur} + return 0 + fi + + case "${prev}" in + --set|-s) + _rtsbc_rtconf_set_name "${COMP_WORDS[1]}" "${cur}" + return 0 + ;; + set) + _rtsbc_rtconf_set + return 0 + ;; + get) + _rtsbc_rtconf_param_name "${COMP_WORDS[1]}" "${cur}" + return 0 + ;; + list) + return 0 + ;; + act) + return 0 + ;; + =) + if [[ "${COMP_WORDS[COMP_CWORD - 2]}" == "--set" ]] + then + _rtsbc_rtconf_set_name "${COMP_WORDS[1]}" "${cur}" + return 0 + fi + ;; + *) + if (( ${#COMP_WORDS[@]} >= 4 )) + then + if [[ "${COMP_WORDS[COMP_CWORD - 2]}" == "set" ]] + then + _rtsbc_rtconf_set + return 0 + else + COMPREPLY=($(compgen -W "${confopts}" -- ${cur})) + return 0 + fi + else + COMPREPLY=($(compgen -W "${confopts}" -- ${cur})) + return 0 + fi + ;; + esac + + return 0 +} + +_rtsbc_rtlog_get_logfile() +{ + # $@ = COMP_WORDS + local words + words=($@) + for ii in $(seq 0 ${#words[*]}) ; + do + if [[ ${words[ii]} == '-f' || ${words[ii]} == '--filename' ]] + then + logfilename=${words[ii + 1]} + return 0 + fi + done + + return 1 +} + +_rtsbc_opt_in_opts() +{ + # $1 = short opt + # $2 = long opt + # $@ = COMP_WORDS + local short long words + short="${1}" + long="${2}" + shift 2 + words=($@) + for ii in $(seq 0 ${#words[*]}) ; + do + if [[ ${words[ii]} == "${short}" || ${words[ii]} == "${long}" ]] + then + opt_found=1 + return 0 + fi + done + + opt_found= + return 1 +} + +_rtsbc_rtlog_times() +{ + # $1 = File name + # $2 = Current word + times=$(rtlog -d -f ${1} | sed -n 's/.*(\([0-9.]*\))/\1/p') + COMPREPLY=($(compgen -W "${times}" -- ${2})) + return 0 +} + +_rtsbc_rtlog() +{ + local cur prev preprev colonopt logfilename opt_found + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + case "${prev}" in + --filename|-f) + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + return 0 + ;; + --start|-s) + _rtsbc_rtlog_get_logfile ${COMP_WORDS[*]} + if [[ "${logfilename}" ]] + then + # Check if -i has been issued + _rtsbc_opt_in_opts '-i' '--index' ${COMP_WORDS[*]} + if [[ ! "${opt_found}" ]] + then + _rtsbc_rtlog_times "${logfilename}" "${cur}" + fi + fi + return 0 + ;; + --end|-e) + _rtsbc_rtlog_get_logfile ${COMP_WORDS[*]} + if [[ "${logfilename}" ]] + then + # Check if -i has been issued + _rtsbc_opt_in_opts '-i' '--index' ${COMP_WORDS[*]} + if [[ ! "${opt_found}" ]] + then + _rtsbc_rtlog_times "${logfilename}" "${cur}" + fi + fi + return 0 + ;; + --logger|-l) + COMPREPLY=($(compgen -W "simpkl text" -- ${cur})) + return 0 + ;; + --mod|-m) + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + return 0 + ;; + --path|-p) + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + return 0 + ;; + esac + + # : is treated the same as a space for separating variables + # Port completion 1 + if [[ ${cur} == : ]] ; then + colonopt=$(rtcat ${prev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }') + COMPREPLY=(${colonopt}) + return 0 + fi + + # Port completion 2 + if [[ ${prev} == : ]] ; then + preprev="${COMP_WORDS[COMP_CWORD-2]}" + colonopt=`rtcat ${preprev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }'` + COMPREPLY=($(compgen -W "${colonopt}" -- ${cur})) + return 0 + fi + + _rtsbc_rtobj "${cur}" port + return 0 +} + +_rtsbc_mgr_comp_load_cmd() +{ + # $1 = Current word + path_done=$(echo ${1} | grep :) + if [[ -z "${path_done}" ]] + then + # No path yet; complete the file name + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + fi + return 0 +} + +_rtsbc_rtmgr() +{ + local cur prev modules name basenames rtcs inst_names module_path + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + case "${prev}" in + --create|-c) + # Loaded module name + if [[ ${COMP_WORDS[1]} != -* ]] ; + then + modules="$(rtcat ${COMP_WORDS[1]} | \ + sed -n '/Loaded modules/,/Loadable modules/p' | \ + grep Filepath | awk '{print $2;}')" + for mod in ${modules} ; + do + name=$(basename ${mod#.//}) + basenames="${basenames} ${name%.*}" + done + else + basenames= + fi + COMPREPLY=($(compgen -W "${basenames}" -- ${cur})) + return 0 + ;; + --delete|-d) + # Component instance name + if [[ ${COMP_WORDS[1]} != -* ]] ; + then + rtcs=$(rtls ${COMP_WORDS[1]}) + else + rtcs= + fi + for rtc in ${rtcs} ; + do + inst_names="${inst_names} ${rtc%.rtc}" + done + COMPREPLY=($(compgen -W "${inst_names}" -- ${cur})) + return 0 + ;; + --load|-l) + # File name + _rtsbc_mgr_comp_load_cmd ${cur} + return 0 + ;; + --unload|-u) + # Loaded module path + if [[ ${COMP_WORDS[1]} != -* ]] ; + then + modules="$(rtcat ${COMP_WORDS[1]} | \ + sed -n '/Loaded modules/,/Loadable modules/p' | \ + grep Filepath | awk '{print $2;}')" + else + modules= + fi + COMPREPLY=($(compgen -W "${modules}" -- ${cur})) + return 0 + ;; + esac + + # If the word before last was -l or --load then complete a module function + if [[ "${cur}" == ":" ]] && (( ${#COMP_WORDS[@]} > 2)) + then + if [[ "${COMP_WORDS[COMP_CWORD-2]}" == "-l" ]] || \ + [[ "${COMP_WORDS[COMP_CWORD-2]}" == "--load" ]] + then + funcs="$(nm -C ${prev} | grep ' T ' | grep -v '::' | \ + awk '{print $3;}')" + COMPREPLY=($(compgen -W "${funcs}")) + return 0 + fi + elif (( ${#COMP_WORDS[@]} > 3)) + then + case "${COMP_WORDS[COMP_CWORD-3]}" in + --load|-l) + mod_path="${COMP_WORDS[COMP_CWORD-2]}" + funcs="$(nm -C ${mod_path} | grep ' T ' | grep -v '::' | \ + awk '{print $3;}')" + COMPREPLY=($(compgen -W "${funcs}" -- "${cur}")) + return 0 + ;; + esac + fi + + # Anything else is probably a tree object + _rtsbc_rtobj ${cur} + return 0 +} + +_rtsbc_rtcheck(){ + local cur prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + case "${prev}" in + --state|-s) + COMPREPLY=($(compgen -W "inactive Inactive active Active error Error" -- ${cur})) + return 0 + ;; + esac + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + + return 0 +} + +_rtsbc_rtmod() +{ + local cur prev preprev colonopt + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + case "${prev}" in + --mod|-m) + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + return 0 + ;; + --path|-p) + COMPREPLY=($(compgen -f ${cur})) + @COMPOPT_FILENAMES@ + return 0 + ;; + esac + + # : is treated the same as a space for separating variables + # Port completion 1 + if [[ ${cur} == : ]] ; then + colonopt=$(rtcat ${prev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }') + COMPREPLY=(${colonopt}) + return 0 + fi + + # Port completion 2 + if [[ ${prev} == : ]] ; then + preprev="${COMP_WORDS[COMP_CWORD-2]}" + colonopt=`rtcat ${preprev} 2> /dev/null | grep Port: | col | sed 's/00m//g' | awk '{ print $2 }'` + COMPREPLY=($(compgen -W "${colonopt}" -- ${cur})) + return 0 + fi + + _rtsbc_rtobj "${cur}" port + return 0 +} + +_rtsbc_optsonly(){ + local cur prev + COMPREPLY=() + cur="${COMP_WORDS[COMP_CWORD]}" + prev="${COMP_WORDS[COMP_CWORD-1]}" + + if [[ ${cur} == -* ]] ; then + _rtsbc_rtopts ${cur} + return 0 + fi + + return 0 +} + +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtact +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtcheck rtcheck +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtcomp rtcomp +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtcon rtcon +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtconf rtconf +complete @COMPLETE_NOSPACE@ -F _rtsbc_optsonly -A file rtcryo +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtcat rtcat +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtcwd +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtdeact +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtdel +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtdis rtdis +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtdoc +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtexit +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtfind +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtmod rtinject +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtlog rtlog +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtls +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtmgr rtmgr +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtmod rtprint +complete @COMPLETE_NOSPACE@ -F _rtsbc_rtls rtreset +complete @COMPLETE_NOSPACE@ -F _rtsbc_optsonly -A file rtresurrect +complete @COMPLETE_NOSPACE@ -F _rtsbc_optsonly -A file rtstart +complete @COMPLETE_NOSPACE@ -F _rtsbc_optsonly -A file rtstop +complete @COMPLETE_NOSPACE@ -F _rtsbc_optsonly -A file rtteardown + diff --git a/doc/cheatsheet/cheatsheet.pdf b/doc/cheatsheet/cheatsheet.pdf new file mode 100644 index 0000000000000000000000000000000000000000..d8570434a577c2eac759e1a9f2d5e4256b19d528 GIT binary patch literal 31392 zcmeFZbx>W)w?Bxx2AANP00%g@6P)1g?(S~E-92dV;7)K0?(QzZ-R%d-z3<+6?@i6O zrfU8hs&>=8R`g8sC``*h#{@?{HuZB34oE~#WUXgL#Ki>%kTA3|b}%7g z00LQwe*eJ%giS3R4DE;j!WOy?hJuFr)&_=fJUnpr4t9pRmT)c$!z%rDi^3=^7awgP ziocy5hFOQaQ~sGmg=rm%L=PJxS}_J06{%Yo~L2RM>IA$=x*J(yXfnJ z{fs)QBh3&>b}`exv4iQ3=khq;C5p4ntpp$^C_pHybZ)t|KN~bVTaUX&V2l;FcHG7J z5NFF~HB!RQcgFq6tJ!>wj%jK85xCG0>JO9UlL^;8052tB2UU5~MyQmG_(B&~2J7_zx#DvUB6~5R!vRKLB|17XT=7r?Ot~cB zX*DmYm7+z75oN|wZVM#Ena&+b3)7fyQp}iL#K@QJL%#lnWvf?3h@B13ARcwd1UJ04MON|PeN@5|DRLLMTNUgw$q=7E zySqAuQdXy$V?cGr6E^XReoWU(bXS4CtVjT-negy~H3lo;O)Y^*2SZO{uK<2WZSiSmX$2832=em#M-t(CQr_{CZt7T1t0xV4B>JHikK|(OCe(ao@|gW2o?QvONXbBWVG5P+GT}qZODmov5AYL4+MLGebc&V znQ|Cze=6e`J8uiWiQVDJ6Sb_7DWYSx%J)vY_-AL?Pg*EE+8}NBt-9vB&Fto?McMir zDReu;UqKF-svd$^&NIzNW3X}J;Vs*fJsQZk_Kpn9BbNXR9X>MjfhC3( zf;I_?tGc<6Xn~%(nH?3vp`blEWD*$vu z|0Rmi%|gw+9Hj>j2D!tFli-Atpj~(`ge?DR&Q2ZWQBeFitRTL#<(i9*)lC^`L-Gf* zo?x7NvzUA+4rmK5-Ds2u!C0rf7Z3?DLJ~MbD}%q*(AU`O`U}VSuXR|#)y9wrAfsz+ z2nP_bwsJ7Ea2Bx~7tX+uI>0b%V?96nGtSm%q zObm2v?3!?|TI^oMiCBJT=HVgwtGGAezn6XC*CJlm|JOyHjfm+j-)oG4iHP}k^mVZZ z$k)WxXxd+D0 zcCGXSCJd`+9848ixQ2cE(k22bDDb4JZtf}w2Oc*XdB;Y!1_u#Izh0PWGH_^(?B@J5 zSbm}RSbT7ud#I-b^1qOY!m7h;SDiKAJp1)g)I77G1t9S>bt+$!D5QEB&o`}Pw#=?k z8nnX9Bo0aGCX8Cp2h>EW#y)*Pa~&rX6)3raZXIIv0rJ^=B7>Gg?||URX#^q}bB#23 zAUwj|`e!M`ND!&QCfa^IMYYl5g>Hptg_80&*gHqNm*vRZ%>VG5ZKG=%2gEgY;1c*q z_$3OI*SQ8^e1X`{D|jhmH2w(Z<3LhvXn_wrU+fBd#bL=HbQXKC-rRkvc{_$q zy!7HD2OhMbHIDx|GJL?)<` z57u}IIgA-37APv#MkMJ0Q2%o~>KcSczYNx)dz5LS{mU%-RpvgeAOE{ zdmkBkh0>-2j*6XjWglRPf@EPgIHd$@?Pf#v%7o$_XMpoB8_4rVo0W7uL+}R#C!D_3bPJXFubVETNV|xm2hE_cC9t+LFI2EM zq1KI~TqwCH$ANU@bnkrn$jzkr)Y*K2aJEPN{LY1eMg5VuO&IDqu$V|`zjiu>R;^N& zEFRGK$6YZ32&Yin?1(UGufR{*Cs8UhZn$ILCuimT>X7;*6fuG2W8O}VU=ONc^QGZI z`23VQO{Y>DcAt;D8^%>!%i6qGUd>woqFwNP92Ep;c-=uYgp$gx%Fo*MMTISSjJ@5f zIDc}Jr+!D9&sXm0dCk1f`@Z|mSPB&SNQ#A1(JN#V*2deavDHmW8iPksTXxFl?39Oq|bWaIgm(BJSEF(>{4D{P*1P~)u^PZ)40ooZR>^o6#94# zo@uik<*}Vxnz>?)V;4X51JV28J*$~^suyDD?Sh;@@gy^ESn8J+T)SRdq19MhBKeyw zTybzb{}*tTS^(&O;{2a5 z(aC1L-{!9-PWr(p`n`Gw!Q3+<)R%k9YM9N`OE@gK1B?$1rCLFD`h>bPi3^bS*fK)o z;Wp?V&dgUs@GKtUk8m%LCbwa z_`_YYc;f-F%UxXE%`z(?=3d6inq5ROYF{yLnOsFQNg{?Pm{=rZC!uad+A)-b`vvT$ zjBEy7d#8Z-wc3`~-WGOA6amF}Az6E5Bcx)=Xki$#cw5}&$on8x5#)|CkgBI+m0Q=U z@|cD)Q3R&@a#%_S;3BCvh$W486bHH2)jRAm_Ps!kriRrctmp`ACT;P5@$nE`}S}Fa&rC>|6wPqq{=5%v=flU%vpkL!r z!VuSAv|yGv(?|1_Y__IJYc9!z>4El}=!FBqk6zqf-e3>{OD?u`;(`7$VbVjqgmUX) zG^HiN_p-cE$v@tokHtD;QEL6LA`7p}B!B5*gyJzkT%j+y17DNC;I3*EUWT?!!D7Ozn2!kH5& zRC!<)>QUo;OoYouAu*sp?}?Y}C<5Fgla->^|4$Rg_Ae{(znZu=GxC2iajbs`|L;uP zoACcMaSW_P3~z?=w~=EfV)$)E|7H6ABYVg2m$imdXJ%w3`v0H*&-+00Z8p7alNkQ; zSK-uI*%;}Vh}c+|=-zfa>~zepW68q!SM(2og^l%<3}j$@4Vl>({*JM{rT;xVz% zu@kYp4JAGOpZ^R%Iv^2{2}s9E#QZz|8}~1nKUDTN-X97(@U5KR^8b~W`8S`5`K@A1 zuM)3YtABF+=CS>$*YEi6-2XK4Z5Q^|T6G{B+iT5!hyQTjHfF!M%*@QMjsFv}0pDu; zCuC%0eJu}2|C{^TqPJH4`(b6Kf2|YKYxliTSs5AW7>QVa%e zABBIyw=92(`6u>A_^)FBsq!E7zZL(*`(4R@^t@^KPo6&#{|^6@$i(_q^*`Ys%3IS| z>DgYp;;&}0ytRUbjsCTxSeV}$#>&R@I&g3KfGiAj3`ETTYUkS!vNN#!#s8!6kL+LC zfh=zlzq|b}{cq*HJ`D7XZ+-r|_}3&0!<*`V8v5U3|D^vY`)f3QEB+Jz*XaGG{*m~L z`n#+@l)r}J&rEph&Ofo=Ie_d8Z*!FWZKVIqq2RbWt^$D|>mvIAN2)7pfFF|; zMxw6>5?sXyF?MYSW?%>s>>HZa45yGGhVFy9{3OaoY0OB36nC4F3uDrxE5^nY3eqlX zU|fP%3xyj1U4}BwMl+8LVX}D!vQf~9#;3zwNoGw0)eZ3l1RFmUflVjf27=;LT0|H^ zge2?M7<+U3c{YwUaZ8LDGFV!oXoH|)TD{VboV zK6Be!a!>n&iWPt5qzy-q)fvE;2+8VEcBOF{f=y19~A1KUMj}2r}~nfwiux^>o$q*^NnH9mc?(_vR(x zDdj1Q*c<4`L6!!vk%S^61<$6CYioP9cpjIC@}bbPf!OEg!vH}K@juu9rUjLd#Rme> zj!Lhh4RY|=5djJ{*x)-vRwNmW4OwimSDCyR0m#=EgeQ{y!1ls6F&vPb7ZDU39FXuk zL}C!^2Ru1=_Lo3~(#2JnY%|z4V#Uvoh(&4>)-aIm8Ex5MAQZ36C@t?Cn%ekPz~jw3 z2Z!KR&<`=VphATbV=rQY?lGb&V0W{g^2&EuoEwE+`32^^iOqW7QI*|Ul_`_-6)od!?(m-)#$xKsSFS8oQQ<-p?^9e16bwp}(@=a#yKCUj$V9sVi)+=Z^Uvn;f_raS@0}pE` zP@}7SbpV&GjaaDF>t-EzbAt?hjG=a-rN>69ZG@s<(ia-$IUz^o&m|Y9LXLT!Z%fiP zKfkizpq^Er6FfTKy;ecIpzV04&mBO!-fvIjCxlJnbPund;F9RymtC1Aw)N{MTeRhA z;6AzuEF*;3;)3p8NO3%}6n}R}5X#s}98Z!ZoTjA}_#JJfKR4@GBl%ahc}L}U7R%AX zUYvskHRb%IPF->C?K1TqD9-S%4y;*lbSn$qg+hAqG5NLS?dXR38wmMuH&4%hee(dCO(#hN|r1{b~_y$UhC4;d<-%U}$WatZvP zh6CuriY15oe7J)q1L#eKfgW2nRjZ$@o*3i(uJ#!}V?OFN;To$b6%77DDh2kUCc^a4 ziTDP*m^J10&1w{3agQB&}0E{pC<$34k`Dq0Lm z?3c-`dziUMA6Cd#bshG8(sl$vzn_#X;}6**q4m>g=wBY)2T1b>RBaVFJbek9k8apf zSoBz0_@?pbdEQuYecB+N5GgJ0>?ww%n&aCQHaM z;b64k+$;KS6+HXAc%un)vQ}H@0EI6r{ZjBAe1aSWhEZ*^&TMiGGNM+&9IA3A$KHG}q7fcQnhganyTZMJ`U9f@^9)Nsc2HTa>VF zKEOCwQuya8JV3@mcHTxq-*{3_ z%~M1}!vyYBgW5IR$tS7KcHNkZk{No17O0Qai#R&6sarU4i=|CzHoq8ynd_-{HwQ}( zRKxZUe0Zzf;Thf`J#dA0V-j%(C~?$_?O%Y45|R%%FsOI8ZzxjEOPiMBFr$i;X-Pkx z-mlkPE7%r5<9x+Y>)R-ytD7Y|<(A5PjF4^-5wlexR<`k)<89yqC%3e>IrRw?6JT#7 zbZsM1Y~>8joYC{fDWW#8N)E0;k&4Pd;Jns>6{GMmYNsW^*ILl-uRD@`=%rktP(ZjQQply zZp93);b^#hjGcz3T%n91OQXTCmk}_!>`D*0EHM!RMDEJ=ld_@YBSO@+A1p2eJOFu$ z=%q)e*!t|9X$v=O+$w37jGXSI83pV5)x2d`{Ri1~@*WS3LhTC;%@Po+SV}!_HO6Ll zJ3NN9a^nlTAZioBr^ZST&$M?{amxJwiIv%_ahfX36n2c$drR?(J3ScC797oqIvZc3 zBo75X$L8xVHa%Y(>_4ODH0zOzZJ_gQ{R9)D9{mftqLxi24$Kx+-!s<6**2clDeD za*sgUu#cQqyIYr!An|4Gtis8Mn>w7_6umyy{)n8^Q1@u0| z&A3@C!&Etq?vdW)D|WUJETO#M<{oAoYidCatSoQvD7dM=uP+gqoa#haes{ZYP2S8# z{bl~=3z+~|j;*PoN0T{({&G}V#mN_Z!rjd@Xn8s>85L8iwX^zLfr3;F@0KP3`^>7O zA8FSbuGi#A5}6mJRB9OnDf)_mB$MmIZZHp@ZY#DK`sc<-Rb$Ho*F7DN(&xc>+(o1A zLXH?7f$VUhvIau}rCb7nrEAaW9GO&+4Ph}AsZzAvmCFqq(f~01E<3|_VxLIYyVR{e zStmd9cRdSX3=Au+0tZjVf*R-5lMW$2K{Fp*#C!N3XWn&pyX_t|>uRNxN621kAvk@< z;!Y*euS$J(dl+l(y4lRGlu?Xw*{74Q;wCh=OZ!4A!OOXuo3fniO#F-Ip(Tj$XVb@M zTCpO}AP%{l`2q*UaOa-_bmvsPOQ>O|0w-N^kqNsi)Xc5M5|p-fsLk|l7f+D#w)Jp+ zlcwafjohg}W^2rjyGjQvS9b@I&ybs`ajw-%#5}ZY)8!eW1E-FMI^%#G+i}s}0V1f2 znHN=_A1H7Aj10EZT0-MiZ1y$?<$Oub<>I>RTM`9U)R;~7Me1@=7p?gm1^p*RzY;)suk)o< z9Y3yc9-zP~l;YwzPvdTc2D)fkf&8FAT-A z*L$6)PM+t|I9a61L7Gut)o`cOobu5gB>p>%W|k#a&r-O_^t6r?R|}}G4w;<}mn-Rq zf@8BUq8vOW#P8hfsVECZkJk52UBrXx%6jbW^EBZ3o%*}Cam`JlWS^6^Wc-5ZBH&iP zSE66XeCFg=IzA%Iit=xSMoZmTDpgWnz%p|2{S}I`y1G58q?HINnTgGNZL-?RiW!;= zuq$^e9ei?&=?!^*ZPHLP`ao>CQxwJgypq{q#Q?VpO{69$WH)$jUg{mbD2G|cS{BZ0 zA$Rx8_e?Mlb#i=-nm#=p(6U{jwNukSC2uTkT%`O-C&Sz#gEx)PJ^si0AssP0=Q0#) zEm_P68GX#c)62^-xwd74n9eR`oAR~&d9;(SNEFxtD-iczBMWp#TJi1X5O^AK&r|D5 zf&SzI#TAzkcJ>Dko6I;j2`+)ySbkN?fZ{nDptTjG(EV=gUf8#!kp~}I;^i9fu%exM z3OeBvRrzvvk3GW#dmD}Dh!5itN~Fbj}$+E}ET>ZKyrqsO-hFg;I0xmvaZKjPcvRw?2 z)d>a9z%eX)|L4WeckhOu3{N6?_Oh8((4tTgNpl*K(oiZTjJeSn56i9bJsLeO+OK&} z2i89S&y&E{L%4rD%0EYeZ3zd;Q<{UhJKuqHFhd z2Sx=@0O$hr0R{j=fC<17Uki z;YNsDyqI_?Skqj*T*%gWckj`e8`l@lDEG*RhS87S2WsYsv^6(G|sxlk&3rKWCz{hrc3qx>z{g=B)*gBh?Cc+-2HzhZf}ug`+^SQM zf>6AJ2$*vR<@yG#9}qkkm_t|)_fClF zYW}RU3Um+)3NMh)g}?=Eyn#V*9juqZOXM@qIdX3_ULVbU?Tt-e+Fe#ykU7N{axWy1 zrUmN_hzj#Z3YCl<>kX(1^QX@hXdPD9Uv-{_ywOmEM~pC?bd=pI@(!#yXWOp5k!IVF zlF7onL!gz0z|4?2b6+ZL>|YFRZElxQ`amZU@44NBPq`&Yb%O&xmB%Zlna#gI95sdLJ z(QjLM6G{AdAcT?MJnKc#ozHkn&aU3JSts~IOiczQ#6iROw6Hxd@PYb(l>4l{1lQQu zJ3$F(ygX0(YL2{Ai7fWDSdrR9W}RCOrv1k!}q9xGzj*e1;ad6O>Ofdr&h$%oTD<= z3w9ok@9li1XV@+-qM@}M%?ul8#M&wV4>d1qez<<|Gf3y}Ff{73-94R+r~sK65`isF zw~J~VbRQ58nF^|4j!zAd4|8vV2RDhI>(;4;hgL_kj;tD-A*ozLqJ(E5Y}qi6;x%yb zByMpzzXjz5tk0=rX1GBY|6~MJN*(dB%oRe9Aij&nZ?4$4uzqJc*)QM8um@v!gO-@+ z#QhywO=~k@gD_uXD1RmZ?m`H^-~>J^f#I^AY9;EyCm!$1qtnlBkks0CH0=_>S!4zd z;czHX1#H^7DSs$WoD{U%6~3WN)djMRXOnV#p|}i>rEbRXpHHEhV-_rxCl=(`-gm{R zIr>-E@I^=4C_79tRMgjIC>+)D-J$8FpS#^E70YpO3MEC%*Qj1n^qhl`d#F_2$5K1W9K4Q znTsLs?hIV4(?C^bwcB_~Ig3*sqeYf=L&rU&e(|pqIS80=58%3J>^$a zy*Qr(o}SJ6Mggs}&zR*w3`Zk3bP_Yo!RjhqfR}_^TwO_L$9F9|qcJR1BrlP24ei5? z+6`!lhre_wYR=Ms1;l*_r^PE~>)D*O7tiWDjO;N6xf&TV>_9qABZwWQaL(2OJv}B-jy#Co_uCA+!NL{z15P(@Y^v<&S{kf2NZGJXZ7f_#J-Qe4O zR&QS9lv3`NOu?`{9E1V;H=3i_A3J^?Yq*bsk;l3eRc!rv1ZHbB`xM{vi(!Y|AHu;q zVumG|h79anHo{9T$B_2+;~&^2ca`Np(9&EF2|#~xJS~cr+vl*l;+mK%@q}$2+i(NN zcMqMZde!h$#tkg<(N0L+J_&ExALQZsRg5=(Y^*{;%L|;VS~KfLgCIQc{zXD6V?Qm2 zk|^oN6R|;yA<<^JBSlEWmNtpZ>Kw}!_hZt72;D1SO(L*9<2umQn*U>W5H+}5TK;Hv|jffH>Wc->po#)UJJ1P^Z@vD7A&4iEN>Of!F1P0NruHEcQfxTT2ZU| zt94Q8gS}_{9uG3f<|6G$Ii3C8fK)t(u4&Jen}JiP&n_Qe=x{LwsCLx3mpXQpnRzA9 zSy?@hSxw)0AWnE=j!mjx91;dqBs}0OFw;m#s!k!S@zhC4=;{ZRNjm|-sij2BK?H{O ziD)qCT0VE&+HaVC;x_sqR6YgYC85sY|5=h|DVb#0Ex>_#_}uk`Xr#JTWjxYhq@AGn z*^MpI9Qw-Fb`mzrknTW7%y7r}JuE0Qaz@5uW)e~cikC13fPKnj-IK_V`utt?OZVdF zT2rs@W_b)mTsI6eblbjVpX7??xd=~HKj#N!eLxZ@>gOz=a|&Kk5QlK1D-K}qTANbDcF%u9tDc56zP@UD_@&mdEMW>ySs zU5YIv_Zo!a4WDUAul8?f!Z;71V)kua!zoDoiWnRlHk&3~r5%{xvt2%4>h*81YH4`E z)RLN_vfmxG)hq-LW9PTMpKmQ>Qi=5N=Vi{s=u4avBPF(d=Fg`|#*X(H8;@qEuqIBj z{oD_lNJM9LFz9&7-x2BcDXQBHPt#u;&+v%O<)Jf;uAnpcn+6CCk&f*uyS4H6L&l@g z``eaAzYYl4pvtKI#b7>0y4jC(=ykvul5wWfzC^CV7RAc?dEZ~_gWKX+YofDhNqB23 z_qoTVkUf$2+|iRRULgkQ9(Fgfy+RpwTA6io@A|StVhS2% z%$A{M`$lg)Q+5*d%1;;MQ>SjKO7$Ju&8yXH(PB~!LQc*sEy8m+csxc-M>IY|G_#4n zEO1MGq-#L8F`4B{?cF~`FAAbB5^~?e-d``#@TGZ>6lv^K#Z4A@{y;u*ts2{8aJ411RMeIx8a$YUU%g2qJ1xu@gvco=O8AKR@cRbNY=9bEDq2%;-v)o-Z4aZR&gi90bQ=J3XiP7ek6L!ix8;+wn8eKbyUU-%dR`v<4^zRwr zz}HnDRy-p>JOiu1bl1STz+^p{W&=4=gP91dw*IQi2Po^dowpB$e5whk!Eirgx&M zH5PG~`xP;5rgsS@qO$?gDELyk>2uVowTHb(hnt#^3Ly>Jr<4K2tL|hc}XN?`3ddSgQ;=L6QHEe1xmNF&{m;4Kr>X=_<&0uLKSm zv+qDZqHzp<>o-nu&2S@}q)nfT6Y)9l#)8$7V~1OGVYPP4{1NvnjnMOzT<&)Z#nY6h z9(3w17IJOh_2VGD+}3ZgE2qZD;KO!;aRLn6rQLpyM2}8landk^MQsj9r1`CI-|5zl zYw4dIz%YcL;`w&vtqHE<$ccWTYIq7`7>BSdI9I=K73^@=j z5~PTdK5ZwiuwNE7#rfsrzy!|>=^(yeZNTi6WQ9FW%vkZ}O`VMpgxYCR0%6Ti7%?Fr zJd8lR$kw=5PjYX#QoV|>2^yy85GS)zf6XPX6#}~~zaqAdph!za_h-Fqo38sWGZQOX zwY{PWsV%6v=pK7yuKpvEq8O%~uqs>}hnI5#dmKNQsM3kb}Z_1bn)o-L)!UtX)2A+XL6LU=1p2~b9z z4-NCp8mhtGQDu(?hwO5BN^4b@Bla=qQqFPQ$&AMwZ-cXhjVEGN42-8`7C#p*oJ5Cw zG|Tq0z(PywbxN5J6TY#-EU@MabQ2)3I@b>l_Dk1y0!gTrUXGKxERuNM^K(y?RhFEu zt9Qr77mzFu3(l-rZ+UKX5yTpC^g|MnweLpec57wkiT_S1eM~DpOhkeJ5d6WggF71Y z)p~5;W*ZNsrs138^JH-W`8g}=%4Pr!|J>3~VzJz=TBZV`eTyBW29q7Exng#7MXs;r z!OGXfkYxL=x+d`lE)Pg5Lm!S7w9Kv=ghN)N&G(R3#nv3{FD2eXoZxwOsOiw$vNaJ4 zp-K{GyL!!}P;||!s&0sVs-N~gIc>e!SvJu9sG=3~KnXKi-MK4|^*v<{JTZ}A9&o%~ z^lOK8DsFmpC?XR#vMG|anHd3GGT^xE>3D(AU-cs@Ax%gHC%yB%kpxw-tH_E`s=OGM zp+-=jZJ=Nu88GRByX92ga_%Z}us?rdIbPbNt2L^>T_RVL1Zn@Ps+|`Gw>5D&2$h6s z@m?Dew^o{MM<n(2owRxIS>S_@)r|oH@FO1)y>?u()cYIM`k>n`7>Ky3!+_i8)0 z%n~NUTUcgw3L#Jiw2Xw=&vt$eq?JiCC*GKUsw5Px&a=S(Tuf>{5fxYuz#Aw0TETnY z2myhaBrQCHTA;6VD4_@p;VZ?X6$wTHps@z?ztmZ-p8WgO+mM|k`d{JvPHfY+Q?q)Y(?RBwqizApRJUlhX?)<@1m=@QQ z*5&c9njNE@RJo$Pgb$TGpf8ihJy+~g+PTQJ2fdnSBtX5A=RFr|sfDKA^D63m)Z7nF z7||ttb1O4N#PmNou|k{{W$~(4QJLw4xSp!p*n^I!6!)YF`e_dJv&20-3_}8?<41uO z@!>(JTuKn%Iqu-9$H=!xBDAOC7$6lKY^X_UHx`U1f0ETd`sDZ?EH*@d>WYa=&l_wg zyNK&rTBfovs=q4_={Q(7qC+wszHY#@(^oh4XE9yojomgqA_H4IgGj(~fJn+K^De6Q zU|YfydU7mqvLFj)NE$ERrO8$Hq)#WrFk`iNvM=Cy`Fs$z&{OKB5xK@PTOv?IgwMzu zm#Gl{1A#U${er=)M1ReQ&D^LU&@IO`Xi?msM7{(+Xj+<=>Xx!GBKc}>J1MMlu$FyJ z!}zjCKs0A(3MKohbBXpABOAipeMU92!j>Rgyl37$ykIC`SR@t#2uciRbqTd-h@-k{ z5Ow8^nnPuPbv!ps3vbOjD63I(WM}b#w{SntltOzT__QWKX7Cz;C`(r{#Xl0b+-yJFNqmplodu2FD_42(n;nqnxbiQ%KHA7Q3e=2bW`( z1v7_JDWVxpRN*stOmGEWea`C?dbmjlsix(Wss5`{1+Wg_84i#5%85g6FYAM|acnd= z2?SNv1K&r;WgFq9sIg-F_&G1vYlIOY^Ae9$OJp^i5^C-#a zm#Vqu;!31Q%C}u-kl~o{b5D7F`WhZAt&)0*P{dFRHt={@k~sCMh8n$Zzt0Cut`~Wl zRBwGU#_VDfAG{^cLKhM179`IRPN6O4L0KA0?u6hW=nR7AS!?dWw>uq>vS_Tx8intU z-onXLzSQTOB@IGrxSwHsVsX3JL>8y9h0o^M&K764<(Z)6{BhX~kfxdQ1QRjCiCp=q zkY7XKKHj-w&Sudb);va%hm*<%aG=~fjL~H79dSc#_mZ1Sm2(2e=Y8H~7V!*A z%$SpTYV->;`kQw9I+i#H#l*_fv$es9D?ckC0ju2=;TppLwvO&0Ggl8-*>dm7NJ`=TALG@3L@@5;U?JsO7|! z=@&pp=u$S1Y)&{?wNhn`Po2KFRfASBjCM&LQenhEZf-_g|FZmy&C|757>>2#NA`f6 z8{Rl6&28`q2yESeY@E`&Y@t#R+mdub)5k@nUAxF@vuF1!?D2;C8j}i*N8r7s%$Gs z@qx5TH8AdBaegSwZof_~m?T2^;4{LP_MMc7J}lclF3P~6sN%v=AV&j%f^{H8Rc?kQ zaN3JPQ|b1bCXV$fj_If+Z0ap4XQd%c*|1z?#nKbVu>=M{VpPa!KR!-yM4fB#UA-%u&cK`MPZ<#V~Qw7DCpogOkS>|0h`GT$_JxiQ7vk#c~N4<)%d&;DhFBtVh- zgx6K(&RQeaq;EOM=1BNm)*e3ra4J}rC9y`&3aop*;hWyTcO9%|Wo0`#3nd>ka2az` zPE-tIv>hSL7sVR>$pbZi5h37KIQ8v1i3^1X7fp=4#s}<|%}lpjFrU;%HGdbiL0DzX zZT3oHv`FxBaGJ~{`w2XhMERqVxPs)-yL2E$XQ_^|`VSAY6gFQ` z*;|_u956M}25>gFh1Rz`(lmlJgvuIj<-JQ*n($PZ~S_koN zoDDje<%te)w*t&R53IAWgwosSEH*J3arDyiXKBQxiOJ;{t($&vjLqzBEegp`l>|y_%Cl<^vmmbK#>3T2Cibp) zGVdfg%;wy0J2AyAkhxn}qKJCR}H33{i)z{#GavO2kN@TGi zBq{&&CK=twkAdh9@MMyMEjY)o=%l6t2bDzWrB9TyEdZ*mkMZt^S2*XNjAgr+SAW4}(ph{S9AsTxvG*h@GrZ1v;FT_{dTC336P`h2fezcCTHZ%6EhzkEj zwUfedOvv z?Q%vCDxTvdskcIIUOg9D97IA9tC7T9&D>LhQq+WPs#fv@s2~-T{=#27g@~aSJ ze%iMs&0(`#RgaP#hFyYICi9xFa2@&6@Bk6mmM4b>S8+SrGOZc>A z_R-3q@*6_u$#;GCOd+{scV(wV8@g&Wed(xZH{!|LM~X{WM3cgKp9llnIQ^0l4XT6- zdBv}=@B&7Q(G`ARMVE%aR>Z?fPfjOs;x67#)OuZ4#s&+tYsn5Cm%MB=zR%DVVB50? zfq%Y{kE?Zz)qR)dqRlBfiehb)GC($PM^DrWCq(hfp-*#TE; z>Ae+u$7MA-_fxO^QDYO-*@-SuUMoERQq<_*5MFS4;*6Dbcfj#P?zW7Wv(jmv~9z_7kI+C!|TM@5QUu7S(C6UPxw zaoyA~Fpabb7U$$3B}AVg54QqP3q%*tf0AN@wDiJEh(d8*$J|2YR*zZk5@A~hsA*8G zb=SY6`M7=7U|L8rkl{USpS{pysq-;c)_-gy5~ATw@5i^nLZd5%?e*qQH)EgUPJKWO zrdbXqRg|rR`EP8@A`oz9N@K8O=19L?vyS(%1GqYX-r8Xct^VL5m>qSIH~n-G_yV^q zt~o*1clXXw<*0#_lqPG>q(=K<;sT>(#Ap@-9|LB)YeEfyJZ8IB`y^z77oMY@st7Iy z?Ko%r8MhXIe&yi&!Ad+AaF$6&#(a#8!F=Fwui7J(N+o? zGuJR?1iWjl{X&`-Z-YN8@)^p~DPVBhloT|TRbl|QEbNAgg z$VkvgQG?w|%wrk*gy+fSlzcW-VLCjO~F*JKDcNd^Z`}yNmuJPuLaSf>3$Q|bFu^2U1@$a@d!Z{GVmE|a7gps z#?$w%8mql~9-DS$i1?Mf#GAUtuV`s^E$hAsdWk&Jr$>AACA`4?CrpVwt9gxu@102( zJU{M|2u2PbHQ>z!zNz>}tMp4U&I)PSqP2`jTYnH1T!H$SkhR(>n8F)yD-`Rv%(Mu_ zz)TTM8DdnP0@8HCjj5FQSb5EcR4pdD7gXXIw&%nXyw@7@`2F>8J6w3aQItN}$EzY} z5q_fGKJ?s^rT=6olaLGp&4P>P2SCJoER6-cfHJBVvAmpAZ4buHN-z!&B??MT>hODd zn5XCH#$eL{J;tQAbdUC!5(5kWR%0nDRnA4@u1#3m4NphH*BXE7%hGwp>AkY()|dXx zYa0FO%IK{ouX64sM@~m>Xw9jNe6;2`w|$5103qtsa)ckbcu2o=?jv3Hx=QbS#2U)q z@6v2)bm;f)a)O&$WMdiW}uV8}ydNo8JoB#C(ZLwuedgQ#* zF;RtmOo*|^jk%Yajsijt0W8bS5B^f_>zbO_3L_>Dj0}}>V#hSu+G2a3l#L`V&H32| zq@xfv(8Qv`rOCqC4!fsw3i&}N6#ZvC!>ndx@G-p4sGL6c)PEm>y=r}LDHU2)ZuLQ? z8&;m;mlgL7M5QktC|lCF{-rV?p&T|!YWwFe5(`qT8U0dZFt4<*&(?%Uva~|nlV0AN z5@Xe3j%KZJQhH&PV+~||6wj!1@vMyJRFB~tt~rHa#D||AxDG_?gIq)ho*kkAX^bKA z-3Kt2@i*{3-$g~Mhpip62%5OKTf&aqTqE?RZ*NPzsR%SKt=2 z*)CQg01;nm!aUMT@m#6peJQ%;hfvnm8wON(X`5~FT5P~$lH2fUt3>QQjtDZ^$w?XV zxAdbP_h9%>M$?Mmip4=^Pp*L-kZ$3nl1>{A2~VwG2qjk&{0s6u5GRp9r$1oi-O}T8 z0g~@az$|Sa_{37Y+i$9ZI1}^ad4oR%7nvuMgNHI2(<@!uCDn&JL_?Lh*IVj`8;f`H zrK2kuntKa{g1%zg}24&$C8D_!`0f$>R0IiQJho@6Ke zAnf2?k1X}x3u{~b9ZqmKmH6v-G9+LcfLbgxh*HsCgMXGli}GlbC+~3D3-O&T?fm?S z?A%4kX)8bDthj$1(bg!)m?3&slZm5B!J!AV!_8>W%0J4qNK=NMq&vZ=$O2DpBeo?o z>brd6T03y=FEEHykaed^B3#+k;0O7MBZ#KgSlva^42U@m4GFAfxx`VLO*-aG&iiQ> z-Z-0mV)Gb?g{XptG@>m>HKL0*Vt?Y))|hrO0D0Uxcu+NhA0zKRKPxF&T#wC!H_#W} zxI)c^{raVn*(2?MIFW3DpWvbx$7WS%6T1x?8@yyA=gH_X%p}-5X5n6<(!pZDDQo8d_TF{)So^S{mrun*fXeMy3GcSKyV2tBr}F6~Gi=1~3O$ z{Ds4^wlW0R0Bj8HOsx(60%bWkTfYLcoB+-Mm;VOOdP8H${p%YBjBjs+{`a?>SlRyT zy{6Y!JT zup~urj#G5=aR!Ffcr19S|EIFEfQqtf`#l1pAdNJ_&>`I;og&>S&CuQ5jdTl$G(&fX zbhmUj2uOFG(dT)eSAE}ezVFO}wPs)Jx%YMNx`uWC_VxEK#1dg4`HEF74*o1^2I`b3 zikCA-6B(t!5+ZGv?Ud-!8}O!5KY+70KejS@+;>{KbYHexvV%6H$cK%_iHFXjjzI$m zk|FlS7Z?a5qGlvvpaSxU`&V9q`EhaJqDEz5g+Eq7MMIUd(uxsKMB74pr!uP=zc1AP zVt!3f`woHRJgR$=3O`VAq9j+ccXV%mcBypV8l{aMNt5oLhet^u*t_p*$iZ3dcZ>T6fbN0C#F!2LC z*9nWFIoMLr!&BPC%VlXrRY`A~A2is^RbPU08B@Rd0{Yy&$5~BR%NT--$pA1@I~xojaFe_;|wv)U^s9Odt1YaOZD=D3N}uwM}_hN*1paDcd!YP8CT*f z9^Z}Dro+DZ^!v_;+ywW>obzH0HRdixt1y%z^ON49cTS=#k?SY|0(*4cNYd56vx^uXUlfg9$g_qd#Z)+2|YR}H9 zW@0nvz>dqMpcCZz9lXwca(ib+ZIKOld)&CoZ^cCUmS}W5;Yen_k(zb9OG>jUTatD~ zav|xocrKr0R$$KQD!6fL4kJiH8tD}tua%Y`?6go2N!+A)to%!Q$=udB#U&5;S%jv( zGJC!JN?+w@N=hSDA5h=S0(<+d;?!?L~;V_Lgh58 zu4W>)<%y-;jj#2!XG_k6U;6kmzUe*7_SrId&!Mm?yCkpc+bY1`_yfU1m|MF`Z+K9m zV3V^leiAk#%T~LSrvCC`rLle&XJJRp-C)Mdr9&jo6p@MQw$%#ZV_S-INh{k}}XKeW` z*!-IA=N}dra{TyT0p`a+cGiDNzlIygVRPpHb-1wysm8fovWX#}j}Jvb%L_Tx+B=~P zAtDMnkuD;Q(~U3EiAjh(7o#GUCmG_}4$0cS_VOsbW;W}YGwZq6|13AH7h4sm>bn8Z z!NHGuMFktBJT`>|3pER5!okVT0K7=zfu+@d0t5fV+t-)hJG+t2I}8JA17mF!V{NTX z2TDxneN)CojUyveEbFPZz#Y^(Bh;@;{m_WA<=(SCsjCFaSkh2*!SOuLw}z0T>}{cq zAL3WxMq%rHJ`)1W91#JiIu=$>VN`w1587}Dyx`?w=lP-T9@#Y-8}Ft!pZGSki9AVK zAxVB>9WsSl7R&Jk&%m!O1Hoq+x-I_h5%s)v!}hzhbOF||*VrRl_Tzeub&b=>gA7#X zY}YF|UuZ?Z6oBf=OX!^caVi(OqQ=STLA#V>u)S|d9Nl~m7TWq@-r$hJ= z>=PYXr_t6yK-u}DsdwaoHUg)?d3F^WNc+Jp?ePSxG2^E@w?yw1`+#}JfOr?a+TkV>=kmmtLg2P(deFu#t+_;jm8#Oua~- z&_e}nS-~2O-GnEQEG>;S%17c2g*<8{?+m*`By#<5(%8^Z zdgg@Cq?xizeMD%!&-1WyHGpLESP947d4ckL+T>D$tx1i`3Y!b{D)M>V&;!bImCd7P z{!R~h1Xrr5UP6GT&1J==BOkwmw$FTbM}dIW!j4$tN9&Hs#yiK3zW21B0Y`jToiKNi z=jperJ_GhXhlnR`YrfX8goG6dTIHD@=`J9Gt zRSI?7tJM)x;o#iNV6yDz{jaKVYOk=e4XV?GR)4GB&SO@=35^;n*^C?1enx zAZkgmtiE7f_DP~f-Ya3!%GvxR9|c1SGSZtZC_jv49>yzrHEZz4tYU*T(rCB&v1E=N z+|v?90i+s0Sh%mC*UanCENS+2jUCCDtYRBScFaR+eb-s?*rwomdA!!@MT(?Z>*K@; zU2&~%c3Si=2e~`yUsT-9E8fVUVcB0lRGLCi+}spHy*be93vb zIlm)F(H{X*%Ol$Z%NAX<6=bxm;mVQiT(iCJ#oxQnmcZ)?BW9<>2!%!4f(_Or9hi=%`u)9`fc&-ThSl&o
!g*e1oSqsO6_p>Jj+BWmTx0xnyn=R)EUT^}J1-Gt+L-^xk z?;|XWe4ps!&bsf>4Q(osU+$hs=&Ut}lhWCpIi9|>u^~;g zU=%U)vaWLvv}Gj+u=1&XzNa-eDt*S89KT{H>@xILe{D2P#qY0-HJg^jr!j>z*`$_Lj%fa+s&w z1^?2-I#GjmL&8c{>=;RIGO+?tQ{7V{H_sWNFKC)$7`Q?myJAzC0^GK3-nEh=Ar__Q zL&zDSYxruI+`v*jz$YcA_gqj3O|F#QVuqyH zpt5}@61%+SEU|HGNSPCl0B`9i+=s&)UB!anGi{vgFZL zNV#nTmB>GQTnUm7v&&9HD9>Bt(T;A=J1xR;`W{(zkn6)ek`;kE65ZcKJW3+_GB>Ek zIS(4$U1stdP0eik!yN8Pi}-SjgtumD6bbmvJDzYe63||t$jcg)u`iSH?S|10q8eO# zIuaTiwuLA`p$Lg?6Ysz0pB(#>LF;_&E&2T@r#J=|s+xvRs=rQhB zysi{71+s+S=-#f6S7)u+U*J(zC%qn`f44>W`DwAP#GL9wBIuCWZugP=Q=xMNXPI7Xb-@{9%y)r*u zxUZ;swgM_qZ$oj)8W;{pW+Fj(IUQ|;HCmrG5*w^_fdd64A{sT!vHY^GSvBc$Tpa5& zn-YC|*v;EFuZxp=`?$%9)rK9ROS6@mm&toYt%TQI+eW!v57&iNFNG z&JCy3_JN#+Jf@ir*xjx7Oj(3rF5>NU>@L=%Vrs+>x_mP|iQuJ-u*OCFyll(g`POZ4ahcx0s9~J4t0iUmZw~uI@5=L?x`UdMnRT zxSH1>Gw*sHHl&Ps(E5O?8Q{1?jxMB1r^lKLsi3p%kvZ<`3b%HKXVpO}S_P}uj+P9^T{j&Yk+Eqr0ce|#JW3-n{1!0$5nbtGxdhEvh@ZsC5 zhSlB%o_i%Zdp^`YjkkEB#}z6eU8(WNpwmnv8T|m2g=eVweR&bjCBctk$67^&-@15C zJZ{T2!Tv9dK6QM-mp0=bsI3lpBfq{WCA{eyW@aG3@ER|4y;h%EKKaAiM?UdAi4nV0 zEV56bTe)APX2Wi7YXV&iLVs^1wnk zr6t^I3se2?3jF`*?v=7P!liJo7_aCoEgmsAr&QF~!L^AeAuRUG$ z-k>NQeOxE?4a;LfaMi_&Jc2&oQV2>DLEMH;>LXy&h$mCGb@Ti>H=EH1|R&y*0oY{(XfC^k2wtBtQ{2Q6^tX>ka76bWiaKzDz zud~*vl;pdabtCqb2yZ<0XPKX;@VskBjuV?EjvI&{u79=PId!MTAV7#^H#67gaW3V@B~}hO%EDzw3)8ht(ibXMvK4 z>Ag0=Eem{lfYy7HrOl!66f0Zk@(uC*nCK1@YnOc*RxAQh$Fj<#>7#g9Gl4XQR&1Ai zeAi*A+jxbGf&nieE5^%v*K4w1W>l+Jv0KkPdx1)kZ_PQW>B|HI(#H$iP3{BsBg^KV zS9JE4x7netJusY8_cmYbNQ|xFOj4&0_4MH{<#vr0=I82JS>uWbFrariRy<1F6?xAH41zadIN;Uv^WnB<9qj7g%k0Z#;8( zzTC1dP%I4(JS%8vd+j8B<1$`2DxtXb6v%ow57k0-Pn9PkQk^uSG?l-)@VS&*F}tJF zS8=W*L(|}%bhs;MfWhjvl9_Xu+y248(&vI$x~cgg?z1d?XN1J0@>Zydu8Lc~J-uYu z`mAx-OwwDs2!3D??36k;=9b?6R60bqbxmfqdrF!Xl<$LM zr6=gFjtm8@pGQ=`xSI2IW{ye6^uD&sHbV&RcRb@bf$H?C4CKE7aX*}`*<>muE01ct&UR#U+*iJ&qrW-EACu$P$Q}O6yAxgZsM)jhIkKd z$zUx1i$>}B;MNOF-Ee2QsC`peOOK<%`#@f4h2~Rv#Nwvr>d#WlE3fqu^Ux4;GFb$J z?%=EQWBQ-J62GogXcfx_$);oL+33Czxyq_2cE5Ti2}m&sij% z{XMrE2LUtX;h0=$kdysmQZ=idKg-l@*PcW&I>GZoT@02i=(et!^R@4XwKCjeqBAew zN*dOH&%bMO_YFz%yshNPGVb1iX5ah(Gw>cxt33KL!%Ku)l#5@6)@rOzNt8l!oJEXd zr*0=+l~?ilOzmc(CU)B`_49RrVX;d41`>x%$6k=&Ekn2Grs6^Di3$2q*qW;eGI8o4bkQi*|@B!!^UdJgULuulU^ zneKOYQ&VDZzu<#|H$O1ws>Hxsolt&9N5n{usj|-t8}xCR>(<#P=nI`SN^QdqQdA^6 zc+akeX|$02<&0I4B*=z={>pInn0}T&*i&glz9yMnOif0a>8_~M+{U1(BxV91j9!~~ zr9LA1FeYrx^ksGfb&Xpt%TiBEPE?_@55cj7gEo-WuHfs}dM3BxHNIlzN>}n@3YI1^ zO6{~d^AB=lQHsU2h1D9XGv2EmMqjlkM!#RSNXfM$zZ2gGYlG(@2=p(r$ej)~wkkAP zv-Y?R;nRNA8l6@BPIm3l-)kfDRZwfrYP0({vG1J%A0N=LiRGP!VkT{F_)!bxeeS+3 z8Ruu_<5fOg^hfMdrDa_wEq zb#^+5OX!{pbOpKHmNQk6St1l9s$Qb?mpG#D!E$A8tnnqsEG7}3Ds3J#_JeloXU_Gy<1UVh%}$9ov$OE_Yr&)(YHirSs3;HON7Q!bogx#O1eMcozF3FW^oeDSHYf)qaXp{3Q7)1*-;#Zyv|@xld}&3vg_jLx zuW~w$&1#oxaiNASRU5e2VswpTE_-TsmohpH8-{PM!J)CKrvcv9Fy_kciL4 zZuE1<1dp0fyzf~ufrh`3Yjh>w$Hw{IQANK$#HREP_qzAhh>SH|ONJaM`9{F^NJy3p>!*U3vkl8E2ioB;RnS_cy0H z#JdP*X{(WUG|UJ%l%`&rt}aBLLRzZ~;{oon1xlVK08!QV4;yFi#Il(Z(aagl5LLE2XD@B*P3J4d~-)2`)7@X8sPu|(tcJ1V}6rW|c+ zkL)ueT%+3Nxp~*-l8x*fed{Kd=H%z#c#^8+IQ_H;`t>ATq>(RZQQ_-xhJ8o(E^E4Q0G@0KF{1;Si(epU22O)FVpc>-d+ zm`M~zyjmdBiZ9+JycZIRMQ&Efo`9XBX#B$CiFdV?T+gtJ#uc ztw?)X@Z5nxq>QX=^ZL1u@7{E5ZT9B;WGAhQla|P6gUCMKrhx2AGNZNW>PT0fSwe2H zaK`W@u4WJIw_v$T#qgMoF+VNoTn~RK_rk9EUwjSjw?VN{UUPHX&TotsUYin*`AKcFi=nKu{nTNqhgG0<({6x69p?3ZtmcgoS zNuCey2z}Hm9;8UP;M@&~al>~TRP3CuRbLXymYr3BeZ&+i#A3@bwdsP+{Wlr(l--RV zD=4)R=g1H5(KbRPI(JZ}x$Z}c>nag-_9l`j9^D2A`QQYoEC^>!r4I11kd~+Yc9HcN zpXx;1!I=klcp&EVyhl&hu+~;AIpqvL6H)>f*c3lCYOckO?YrKg!K#dohP#HPZwqs` zl+M#-%c{ioaUM=KZ2xLzPL-J>G-_Xg!CP$)JE7wfk-U3`wjN*CpEj9m>uX@+)xKmk)hU2~$Jr9p?@T21GOR_1-}yE^^FqyPrL*U;F}?X2`NN zzs3(fR|&xt9DJ!Z5ADm+P2>_%%NPUx^eypGHDZguRHM~FsYG>NSqt*ZD_=FT^b)8Z$-nKc4wD1n5LfN zTrfEFXF5K^YV6lek9nkFpSRv6Hr9L5Mze~6r?sX*Fo0d^7%?$>+^bS!37cnVr})Bu z<_4=@(#Zd0-z6B z2tgrT8|C%*F!9z2EjIIINfFe?kOb}WHp3Rd&kd7o#(s}%D$UK>M6S05b>IjOHsVcO z;1_cattEPR35I%BwF2|>!Wo^~n`&;l;ZHPyu~b{qv~T-TjhK>9{f?&zkesUIC^-VK zFOU-VLh#Rh06x)HCK|Wqgf?q*RnWS&=>yN@9-?ldPn`J~4CtKiY#U;EW_kF4NvGch z$1#sYzKv$=g;Qpx{fbK#Sd|34bx98t1VAkMTrQ z~k65<0#x+|$m zQy5kbT2E&Y*bv>mw-{zSBtf_>G_-ISuJ@xVpvULnv%~NADiO{sgZhft^J3mOBN!j^ zlw-Q4^LcWArkJ(t&LZ`zI<8O>IMj8Vm0PBoD044*it)s%N7PdsdoxvREC}erGiw#O zZM3INN49ca(`=#LpPGT(yctEzV)m3NKS5lyWw+j;{3-B8C$8g(KW0Z1vc(qFzP*-esAMTItvq z9`DfUs5FqeV_9I9I`T*-=667w?5{O?D%JvUuhE87v!> zRjOB?rUi&&`9h!uG>#SC-n0)kXQ3wE6CiBO^@MY^aEJ zLwR!1Qpe+9aCoAkgyh7UI~ogN`H@aEDl+p#cc)uJ~|vR8!NmSIaKJPz3(6=X@M z9d-v$hAdq=MPdT_%wq}9dyh06bWf-w1XxJU^QU#S1Iw}ZJ3#?!^0WoU=ixJ2glr3u zm^d4cqtyj$uHu9NqpcyzJxnXq=VChHO*nl*-e!mc9_oRYNvl- zp{0==^I1-7$r8TckN6HMwtXqkKe0>7+uW7S--3+e|FIy?OpY4oeS*lpT*Fk z9v+=W<}P@14PXtMmY)~eHj_DU^$DdS>o&IshOQc_UkF)2pSiq7~$wLyWMXyN8!w5|;0$kT0N-pfIL!2Z$YTw;rMZBJg6?A}$%%vAil zB$VZ@p(o8lbD73$Pu=hqdvs=~*!z7Dyoyx5!Tdl|JA;F&hzDm+B#kF)F%sP~Ww%Z8 zk(r&;ib1yloTa`|$L}Xt!B)9dBolOypcT7z?CjIjdUVfa=tZqJ)a2{2$6w5 z>yCzFz6FHZ$9`^;^rBXWk)ASg+bwZnU&H@!uhAwD=19Rx%gsIL!~%h#nlK34PxH-UB$o(agk`HBPdwqC0pY%6V%f`{;~sf>H3Mq}S|DpaX=R}(fV z1qNvN4_Um`7>vG^b!0}iT9pAIhmk+|xam3{=^Ej2c|zuV=z_06K@O!0OM;I);$TcY`Vl!E1B2_FdH)apZEIu3XciP8*sO&l*Khh??#3UgvgxN88N|b@7m! zt39;MWXF<(r8EmaA6J&BjBUOtfP8N+5XSX!bQd=|?l7tMk9(bQL)_G$h-c*Y+YbK~6AY0tTIc^zTx>T}wi3$_Yl%AucD*TPT?G*jBcJ0QLA`jcuF#N z&~x<4kRzb3uh?9NTTXgtLVm)gU*Ve$LqBF0g3odmXAkZb64DPGST%yHyzb!N)y zpVeE_&6ew2+&>woAy50nUKk`o;v$hbeSzQY&OKD>z1&XDW*_=TWzw^B6;#&RY0Y`e-C zIR%^WjEYVfQ<1j7d9}^b`CFpq!?Yz2PhHW&69yW`K5m6?r`<7Rp`<3Ze%~p+Iw6jf z=o`Fn;dFJzZ^TU=mq%hnj#C?W2~*^jH@igm!cte9i1FHEq8IzMN=QX!c72ESsz6Zr zW`L;4wJU?7ffu-u+fxe#JJ@fCP znK%L8M$2V7xCM73S8=tu0LC=G8bw&KtWHq82*nb?Tz&V5S)mr6!x0q>xJBZ}+VvZ= z)9c*CSL!Bnm*d)Ta_R4JfvL3^Vu*Jn&5B=iN25wYL4Qw`y0pf+Zg^=W{yFbRCBNsO zAQ;8*Fl7ewsdTwcUn6hfdzpqh?!&SNuk>9>_y59zK_I7p_}l-91rt#bRFoHiuwaUc z5a{^7;mzz2xS53oz{bi9U z6M}Hfk_=K1w)r2j8NxM#{-K&7IP!mEnhmVX&2?=dStNgErepxwIOv-H0i-}tkQgO&YXKKy+5*WZ35slAq`w7q?La?8=l&zN=Wj_s0YB4(%0tH2#MaLK2TTru z;vj&W?%xF_X2`WvObqOeA!2wxX3wwA{4JsKQ`hu==gS|+{2#9TtxfcASAOIo{lyiC zWB+pHr*PgcWclBEE&m^`{E0gL?#oYV^0#hbV*IUN7$M-`znu9g==X~=KLwBe{|4!g z#rB6Ye|7vXW5fbUvHDBL{Nl@>6XsW4k-x_1hvuOjWPMsWK=QLfI#|NQzz(4C^K*co zz`o`$x5E6NV=SZ#$>wTh^h5R#a-siFJ%q@+{Ckgqs2UnL=tIP9sjLkQ6+x;$L~$AE zfsiRK1QEA|B%uXRL9G8Onpjy1LnLqkRKjnV86o00OpsqT2%^dMnh{9J$VdsPCuL>u zKUGn*)wQ+;89?-=bj|G`>W;FCBC7PF4(8^1x|WtdTv0SOu>(MU{&I;HpbS}qkfs4F z^h~TwY(QrAzrCdUA$&un0@7m^0zkxv=sBnXX4blpl>pKOIR5jQANF55%-I%Xh`881?lb|FM#DgHdYo0sQbH(5pw%~*qDJpW=LY+-|De2 zGO|O4`41Zl>!0-)Ss>Cjf7D}Sfh6et(+1Iaf*jQN?Rv~W4$l8b;iLbt+1u(uauwSm{80Z?FmVO_m>Uf8 zR#uS3_hWHEHko&phE{-|>*hy67@)z;DJm+;$jmAL=_OHiNKXNU*aVrGI0czlIhi?y j*jac1|8o^hz)ulrU0eH~bCQLTgNY4+oLodk6yg5>9c9@Y literal 0 HcmV?d00001 diff --git a/doc/cheatsheet/cheatsheet.tex b/doc/cheatsheet/cheatsheet.tex new file mode 100644 index 0000000..ba34c2a --- /dev/null +++ b/doc/cheatsheet/cheatsheet.tex @@ -0,0 +1,127 @@ +\documentclass[a4paper,10pt]{article} + +\usepackage{CJKutf8} +% \usepackage[UKenglish]{babel} +\usepackage[overlap, CJK]{ruby} +\usepackage{CJKulem} + +\renewcommand{\rubysep}{-0.2ex} +\newenvironment{Japanese}{% + \CJKfamily{min}% + \CJKtilde + \CJKnospace}{} + +\usepackage{pdfsync} +\usepackage{a4wide} +\usepackage{url} +\usepackage{graphicx} +\usepackage{booktabs} +\usepackage{tabularx} +\usepackage{listings} + +\lstloadlanguages{Bash} +\lstset{basicstyle=\small\ttfamily, escapeinside={(*@}{@*)}, showstringspaces=false, numbers=none, +breaklines=true, breakatwhitespace=true, tabsize=4, language=Bash, numberfirstline=true} + +\begin{document} +% \begin{CJK}{UTF8}{} +% \begin{Japanese} + +\begin{table} + \centering + \begin{tabularx}{\columnwidth}{ll} + \toprule + Command & Purpose \\ + \midrule + rtact $\langle$component$\rangle$ & Activate a component. \\ + rtcat & Display component meta-data. \\ + rtcon $\langle$component 1$\rangle$:$\langle$port 1$\rangle$ & Connect two ports. \\ + \qquad$\langle$component 2$\rangle$:$\langle$port 2$\rangle$ & \\ + rtconf $\langle$component$\rangle$ & Display, select and edit configuration sets and parameters. \\ + rtcwd [path] & Change the current working directory in the RTC Tree. \\ + rtdeact $\langle$component$\rangle$ & Deactivate a component. \\ + rtdel $\langle$path$\rangle$ & Delete an object from a naming context. \\ + rtdis $\langle$component 1$\rangle$[:port 1] & Disconnect two ports, or all connections from a port or \\ + \qquad[component 2[:port 2]] & component. \\ + rtexit $\langle$component$\rangle$ & Shut down a component. \\ + rtfind $\langle$path$\rangle$ $\langle$options$\rangle$ & Search for components and other objects in the RTC Tree. \\ + rtinject $\langle$component$\rangle$:$\langle$port$\rangle$ $\langle$data$\rangle$ & Send data to an InPort on a component. \\ + rtls [path] & Display the contents of a directory in the RTC Tree. \\ + rtmgr $\langle$manager$\rangle$ & Control a manager. \\ + rtprint $\langle$component$\rangle$:$\langle$port$\rangle$ & Print the data being sent by an OutPort in the console. \\ + rtpwd & Print the current working directory in the RTC Tree. \\ + rtreset $\langle$component$\rangle$ & Reset a component. \\ + \bottomrule + \end{tabularx} +\end{table} + +\begin{table} + \centering + \begin{tabularx}{\columnwidth}{ll} + \toprule + Command & Purpose \\ + \midrule + rtresurrect $\langle$xml|yaml file$\rangle$ & Restore a complete RT System. \\ + rtstart $\langle$xml|yaml file$\rangle$ & Start an RT System. \\ + rtstop $\langle$xml|yaml file$\rangle$ & Stop an RT System. \\ + rtcryo $\langle$xml|yaml file$\rangle$ & Save an RT System to a file. \\ + rtteardown $\langle$xml|yaml file$\rangle$ & Delete all connections in an RT System. \\ + \bottomrule + \end{tabularx} +\end{table} + +\newpage + +\section*{Try out these commands} + +\begin{lstlisting}[frame=tb] +1.rtls +2.rtcwd localhost/me.host_cxt/ +3.rtls +4.rtfind . --type=m +5.rtfind . --type=c +6.rtls -l +7.rtmgr manager.mgr load /usr/local/share/OpenRTM-aist/examples/rtcs/Sensor.so SensorInit +8.rtcat manager.mgr +9.rtmgr manager.mgr create Sensor +10.rtls / -R +11.rtcon Motor0.rtc:out ../Sensor0.rtc:in +12.rtcon ../Sensor0.rtc:out Controller0.rtc:in +13.rtcon Motor0.rtc:in Controller0.rtc:out +14.rtls -l +15.rtcon ConsoleIn0.rtc:out ConsoleOut0.rtc:in +16.for c in `rtfind . --type=c`; do rtact ${c}; done +17.rtls -l +18.rtinject ConsoleOut0.rtc:in 'RTC.TimedLong({time}, 42)' +19.rtprint ConsoleIn0.rtc:out +20.rtcat ConsoleOut0.rtc +21.rtcat ConsoleOut0.rtc -l +22.rtcat ConsoleOut0.rtc --ll +23.rtconf ConfigSample0.rtc +24.rtconf ConfigSample0.rtc -l +25.rtconf ConfigSample0.rtc set default int_param0 42 +26.rtconf ConfigSample0.rtc -l +27.watch -n 1 rtls -l +\end{lstlisting} + +\vspace{1cm} + +\begin{lstlisting}[frame=tb] +1.rtls -l +2.rtresurrect --dry-run rtsystem.xml +3.rtresurrect rtsystem.xml +4.rtls -l +5.rtstart --dry-run rtsystem.xml +6.rtstart rtsystem.xml +7.rtls -l +8.rtls -l ../ +9.rtstop rtsystem.xml +10.rtls -l +11.rtcryo localhost -o sys.xml +12.rtteardown sys.xml +13.rtls -l +\end{lstlisting} + +% \end{Japanese} +% \end{CJK} +\end{document} diff --git a/doc/common/common_body.txt b/doc/common/common_body.txt new file mode 100644 index 0000000..8730c75 --- /dev/null +++ b/doc/common/common_body.txt @@ -0,0 +1,84 @@ +Paths +===== + +``rtshell`` uses *paths* to indicate objects in the RTC Tree. A path is +the address of object. Name servers and naming contexts on name servers +are considered directories. Managers and RT-Components are considered +'files'. As with the POSIX ``cat`` command, the path specified as an +argument to commands is appended to the current rtshell working +directory, which is stored in the ``RTCSH_CWD`` environment variable and +changeable using the ``rtcwd`` command. + +The available paths depend on the known name servers at the time the +command is executed. This is a combination of the servers listed in the +``RTCSH_NAMESERVERS`` environment variable and the servers used in given +paths. + +For example, ``/localhost/comp0.rtc`` refers to the component named +``comp0.rtc`` registered on the name server at ``localhost``. +``/localhost/manager/comp0.rtc`` refers to the component ``comp0.rtc`` +in the directory ``manager`` on the ``localhost`` name server. +``./comp0.rtc`` refers to that component in the current directory. + +When specifying a port on an RT-Component, it should be placed after the +path, separated by a colon. For example, ``/localhost/comp0.rtc:data`` +refers to the port ``data`` on the component ``comp0.rtc``. + +Some commands that create new ports accept extra options in the paths, +such as a name for the automatically generated port, or a formatter. The +format for specifying these paths is:: + + path:port.name#formatter + +For example:: + + /localhost/blurg.host_cxt/comp0.rtc:input.stuff#a_printer + +This specifies that the automatically generated port should be named +``stuff``, and the data type it handles should be printed using the +``a_printer`` function (which must be available, usually it is provided +by the user in a loadable module). The port will be connected to the +``input`` port of the ``comp0.rtc`` component. + +The name component is optional. If it is not present, neither +should the ``.`` character be. For example:: + + /localhost/blurg.host_cxt/comp0.rtc:input#a_printer + +The formatter component is optional. If it is not present, neither +should the ``#`` character be. For example:: + + /localhost/blurg.host_cxt/comp0.rtc:input.stuff + +Environment +=========== + + RTCTREE_ORB_ARGS + A list of arguments, separated by semi-colons, to pass to the ORB + when creating it. Optional. + + RTCTREE_NAMESERVERS + A list of name server addresses, separated by semi-colons, to parse + when creating the RTCTree. Each server in the list will be added to + the tree, making it available for browsing with rtshell. Optional. + + RTSH_CWD + The current working directory in the tree. Do not set this variable; + it is set automatically by rtshell. + +The only variable that should normally be set by the user is +``RTCTREE_NAMESERVERS``. Set this to a list of name server addresses, +separated by semi-colons, that rtshell should interact with. For +example, in a Bash shell, the following command will set the known name +serves to ``localhost``, ``192.168.0.1:65346`` and ``example.com``:: + + $ export RTCTREE_NAMESERVERS=localhost;192.168.0.1:65346;example.com + + +Diagnostics +=========== + +Returns ``zero`` on success and ``non-zero`` on failure. + +Verbose output and error messages are printed to ``stderr``. + diff --git a/doc/common/common_opts.txt b/doc/common/common_opts.txt new file mode 100644 index 0000000..d380067 --- /dev/null +++ b/doc/common/common_opts.txt @@ -0,0 +1,9 @@ +--version + Show program's version number and exit + +-h, --help + Show a help message and exit + +-v, --verbose + Output verbose information. [Default: ``False``] + diff --git a/doc/common/docinfo_block.txt b/doc/common/docinfo_block.txt new file mode 100644 index 0000000..0039d42 --- /dev/null +++ b/doc/common/docinfo_block.txt @@ -0,0 +1,7 @@ +:Author: Geoffrey Biggs and contributors +:Date: 2010-03-02 +:Copyright: EPL-1.0 +:Version: 4.0 +:Manual section: 1 +:Manual group: User commands + diff --git a/doc/common/ja/common_body.txt b/doc/common/ja/common_body.txt new file mode 100755 index 0000000..77e8820 --- /dev/null +++ b/doc/common/ja/common_body.txt @@ -0,0 +1,81 @@ +パス +==== + +``rtshell`` は *パス* でRTCツリーのオブジェクトを示します。パスは +オブジェクトのアドレスです。ネームサーバとネームコンテクストは +ダイレクトリで、マネージャとRTコンポーネントはファイルです。POSIXの +``cat`` 等のコマンドと同じように、コマンドに渡したパスはrtshellの +ワーキングディレクトリに追加されます。rtshellの現在のワーキングディレクトリは +``RTCSH_CWD`` という環境変数に保存されて、 ``rtcwd`` というコマンドで +変更することができます。 + +利用できるパスはコマンド実行時のネームサーバによって変わります。 +``RTCSH_NAMESERVERS`` という環境変数の値に記録されたネームサーバとパスに +指定された ネームサーバを組み合わせて提供します。 + +例えば、 ``/localhost/comp0.rtc`` は ``localhost`` にあるネームサーバに登録 +された ``comp0.rtc`` というRTコンポーネントを示します。 +``/localhost/manager/comp0.rtc`` は ``localhost`` にあるネームサーバの下の +``manager`` というディレクトリに登録された ``comp0.rtc`` というRT +コンポーネントを示します。 ``./comp0.rtc`` は現在のワーキングディレクトリ +の中にある ``comp0.rtc`` というRTコンポーネントを示します。 + +RTコンポーネントのポートを示す場合、パスの後にコロン(「:」)で区切って +示します。例えば、 ``/localhost/comp0.rtc:data`` は +``comp0.rtc`` というRTコンポーネントの ``data`` というポートを示します。 + +新しいポートを作るコマンドもあります。この場合、オプションをパスに追加 +することができます。使えるオプションは作られるポートの名前とフォーマッタ +です。指定方法は以下の通りです:: + + path:port.name#formatter + +例:: + + /localhost/blurg.host_cxt/comp0.rtc:input.stuff#a_printer + +作られるポートの名前は ``stuff`` で、データは ``a_printer`` という関数で +ターミナルに表示するように指定してます。( ``a_printer`` の関数はPythonが利 +用可能な場所に存在する必要があります。普通はユーザがモジュールで提供します。) +作られたポートは ``comp0.rtc`` の ``input`` というポートに接続します。 + +「name」という部分は必須ではありません。書いていない場合は「.」文字も +書かないでください。例:: + + /localhost/blurg.host_cxt/comp0.rtc:input#a_printer + +「formatter」という部分は必須ではありません。書いていない場合は「.」文字も +書かないでください。例:: + + /localhost/blurg.host_cxt/comp0.rtc:input.stuff + +環境変数 +======== + + RTCTREE_ORB_ARGS + ORBを作る時に渡す変数です。セミコロンで区切ります。必須ではありません。 + + RTCTREE_NAMESERVERS + RTCツリーを作る時に参照するネームサーバのアドレスです。アドレスをセミ + コロンで区切ります。リストされたアドレスはすべてRTCツリーに追加して + rtshellで見ることができるようになります。必須ではありません。 + + RTSH_CWD + rtshellの現在のワーキングディレクトリ。rtshellが自動的に設定します。 + 設定しないでください。 + +普通、ユーザが設定する変数は ``RTCTREE_NAMESERVERS`` のみです。よく使うネ +ームサーバを設定しておくと便利です。例えば、Bashシェルの場合、以下のコマンド +は ``localhost`` 、 ``192.168.0.1:65346`` および ``example.com`` にあるネーム +サーバをいつもrtshellで利用できるようにします。 + + $ export RTCTREE_NAMESERVERS=localhost;192.168.0.1:65346;example.com + + +返り値 +====== + +成功の場合はゼロを返します。失敗の場合はゼロではない値を返します。 + +デバグ情報とエラーは ``stderr`` に出します。 + diff --git a/doc/common/ja/common_opts.txt b/doc/common/ja/common_opts.txt new file mode 100755 index 0000000..c5a43ec --- /dev/null +++ b/doc/common/ja/common_opts.txt @@ -0,0 +1,9 @@ +--version + プログラムのバージョン番号を表示して終了する + +-h, --help + ヘルプを表示して終了する + +-v, --verbose + 冗長な情報を出力する [デフォルト: ``False``] + diff --git a/doc/common/ja/docinfo_block.txt b/doc/common/ja/docinfo_block.txt new file mode 100644 index 0000000..0039d42 --- /dev/null +++ b/doc/common/ja/docinfo_block.txt @@ -0,0 +1,7 @@ +:Author: Geoffrey Biggs and contributors +:Date: 2010-03-02 +:Copyright: EPL-1.0 +:Version: 4.0 +:Manual section: 1 +:Manual group: User commands + diff --git a/doc/common/ja/start_stop_plans.txt b/doc/common/ja/start_stop_plans.txt new file mode 100755 index 0000000..7309e3d --- /dev/null +++ b/doc/common/ja/start_stop_plans.txt @@ -0,0 +1,45 @@ +RTSProfileには、RTシステムのコンポーネントの開始/停止の指示も指定できる +ことが定義されています。コンポーネントを開始/停止の順番を指示するこが可 +能です。コンポーネント間で依存関係がある場合(例えば、あるコンポーネント +の開始後に、もう一方のコンポーネントを開始する必要がある場合)に、その順 +番を指定することが可能です。 + +``rtstart(1)`` と ``rtstop(1)`` はこの情報を利用します。 ``rtstart`` は +``Activation`` ブロックに含まれていた情報を利用して、 ``rtstop`` は +``Deactivation`` ブロックに含まれていた情報を利用します。実行された時、そ +れらは全システムの状態の変更のために計画を構築し実行します。エラーが出る +か計画が完成まで止まりません。 + +``--dry-run`` というオプションを追加すると計画は表示されますが実行はしません。 +計画の出力は以下のようです:: + + {1} Activate /localhost/ConfigSample0.rtc in execution context 0 (Required) + {2} [Order 1] Activate /localhost/Motor0.rtc in execution context 0 (Required) + {4} [Order 3/Wait 5000ms] Activate /localhost/Controller0.rtc in execution context 0 (Required) + {3} [Order 2/Sync to Motor0, Order 5/Sync to Controller0] Activate /localhost/Sensor0.rtc in execution context 0 (Required) + {5} [Order 4/After ConfigSample0's action] Activate /localhost/ConsoleIn0.rtc in execution context 0 (Required) + +各ラインの初めの括弧の中の数は*アクションID*です。これらは実行の時にも表 +示され、アクションの簡単な識別は可能です。 + +続いて、角括弧中の値が出る可能性はあります。これは、実行されているアク +ションに関するどんな*前条件*を示します: + + Order + 順番を管理します。RTSProfile の condition の rts:sequence 値で設定可 + 能です。他の前条件がない場合、アクションはこの順番によって実行します。 + + Wait + 指定された時間が経過した後にアクションが実行されます。 + + Sync + 指定されたコンポーネントが目的状態に達するまで、アクションを実行しません。 + + After + ``Sync`` と似てます。違いは、指定されたアクションが別のコンポーネント + 上で最初に行なわれるのを待つということです。言いかえれば、そのアクシ + ョンは、コンポーネントが目標状態に達する前でも、別のコンポーネントの + アクションが行われれば実行されます。 + +ラインの残りはアクションの説明です。 + diff --git a/doc/common/start_stop_plans.txt b/doc/common/start_stop_plans.txt new file mode 100644 index 0000000..2f68f99 --- /dev/null +++ b/doc/common/start_stop_plans.txt @@ -0,0 +1,58 @@ + + +The RTSProfile describing an RT-System can also specify the ordering of +starting and stopping components of that system. It is possible to +change the order in which components are started and stopped and +specify dependencies between components, for example to ensure one +component will not start before another that it requires has started. + +``rtstart(1)`` and ``rtstop(1)`` use this information when they start +and stop systems. ``rtstart`` uses the information contained in an +``Activation`` block. ``rtstop`` uses the information contained in a +``Deactivation`` block. When executed, they will build and execute a +plan for changing the state of the entire system. They will not exit +until the plan completes or an error occurs. + +When displayed using the ``--dry-run`` or ``--verbose`` options, the +plan looks similar to that shown below:: + + {1} Activate /localhost/ConfigSample0.rtc in execution context 0 + (Required) + {2} [Order 1] Activate /localhost/Motor0.rtc in execution context 0 + (Required) + {4} [Order 3/Wait 5000ms] Activate /localhost/Controller0.rtc in + execution context 0 (Required) + {3} [Order 2/Sync to Motor0, Order 5/Sync to Controller0] Activate + /localhost/Sensor0.rtc in execution context 0 (Required) + {5} [Order 4/After ConfigSample0's action] Activate + /localhost/ConsoleIn0.rtc in execution context 0 (Required) + +The number in braces at the beginning of each line is the *action ID*. +These are also displayed during execution and allow easy identification +of individual actions. + +Following this there may be a value in square brackets. This indicates +any *pre-conditions* on the action being executed: + + Order + pre-conditions are simple sequencing. When no other conditions are + present, actions will be executed in order of their sequence number. + + Wait + pre-conditions indicate that the specified time must pass before the + action will be executed. + + Sync + pre-conditions prevent the action executing until the specified + component has reached the target state. A timeout can be set on this + occurring, to account for errors. + + After + pre-conditions are similar to ``Sync`` pre-conditions. The + difference is that they wait for the specified action to be + performed on the other component first; in other words, the action + will be executed after the other component's action, but before + confirmation that it has reached the target state. + +The remainder of the line is a description of the action to perform. + diff --git a/doc/make_docs b/doc/make_docs new file mode 100755 index 0000000..1b5cbb6 --- /dev/null +++ b/doc/make_docs @@ -0,0 +1,214 @@ +#!/usr/bin/env python + + +import optparse +import os +import os.path +import subprocess +import sys +import traceback + + +def vprint(verb, msg): + if verb: + print >>sys.stderr, msg + + +def call_process(args): + p = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + output = p.communicate() + output = (output[0].strip(), output[1].strip()) + return_code = p.returncode + return output[0], output[1], return_code + + +def compile_docs(src_dir, dest_dir, cmd, ext, verb=False): + vprint(verb, 'Compiling from {0} to {1}'.format(src_dir, dest_dir)) + if os.path.exists(dest_dir): + if not os.path.isdir(dest_dir): + raise RuntimeError('File exists at destination directory ' + '{0}'.format(dest_dir)) + else: + os.makedirs(dest_dir) + suffix = '.py' + for f in os.listdir(src_dir): + src = os.path.join(src_dir, f) + if not os.path.isfile(src): + continue + dest = os.path.join(dest_dir, os.path.splitext(f)[0] + ext) + if os.path.exists(dest) and not os.path.isfile(dest): + # check_timestamps will have printed a warning earlier + continue + vprint(verb, 'Compiling {0} to {1}'.format(src, dest)) + try: + stdout, stderr, ret = call_process([cmd + suffix, src, dest]) + except OSError, e: + if e.errno == 13: + # The .py version of the command was not found; try without it + suffix = '' + # Repeat the previous command + stdout, stderr, ret = call_process([cmd + suffix, src, dest]) + else: + raise + if ret != 0: + raise RuntimeError('Failed to compile {0} to {1}:\n{2}'.format(src, + dest, stderr)) + + +def compile_tex(src_dir, dest_dir, verb=False): + vprint(verb, 'Compiling from {0} to {1}'.format(src_dir, dest_dir)) + if os.path.exists(dest_dir): + if not os.path.isdir(dest_dir): + raise RuntimeError('File exists at destination directory ' + '{0}'.format(dest_dir)) + else: + os.makedirs(dest_dir) + tex_files = [os.path.join(src_dir, f) for f in os.listdir(src_dir) \ + if os.path.splitext(f)[1] == '.tex'] + for f in tex_files: + dest = os.path.join(dest_dir, os.path.splitext(f)[0] + '.pdf') + vprint(verb, 'Compiling {0} to {1}'.format(f, dest)) + stdout, stderr, ret = call_process(['rubber', '-d', '--into', + dest_dir, f]) + + +def lang_dir(lang='en'): + if lang == 'en': + return '' + elif lang == 'ja': + return 'ja' + + +def common_dir(): + return 'common' + + +def rest_dir(): + return 'rest' + + +def man_dir(): + return 'man' + + +def html_dir(): + return 'html' + + +def tex_dir(): + return 'tex' + + +def pdf_dir(): + return 'pdf' + + +def generate_man(lang='en', verb=False): + src = os.path.join(rest_dir(), lang_dir(lang)) + dest = os.path.join(man_dir(), lang_dir(lang), 'man1') + vprint(verb, 'Generating man pages for language {0}'.format(lang)) + compile_docs(src, dest, 'rst2man', '.1', verb=verb) + + +def generate_html(lang='en', verb=False): + src = os.path.join(rest_dir(), lang_dir(lang)) + dest = os.path.join(html_dir(), lang_dir(lang)) + vprint(verb, 'Generating HTML pages for language {0}'.format(lang)) + compile_docs(src, dest, 'rst2html', '.html', verb=verb) + + +def generate_pdf(lang='en', verb=False): + src = os.path.join(rest_dir(), lang_dir(lang)) + tex = os.path.join(tex_dir(), lang_dir(lang)) + dest = os.path.join(pdf_dir(), lang_dir(lang)) + vprint(verb, 'Generating PDF documents for language {0}'.format(lang)) + compile_docs(src, tex, 'rst2latex', '.tex', verb=verb) + compile_tex(tex, dest, verb=verb) + + +def generate_docs(doctype='man', lang='en', verb=False): + if doctype == 'man': + generate_man(lang=lang, verb=verb) + elif doctype == 'html': + generate_html(lang=lang, verb=verb) + elif doctype == 'pdf': + generate_pdf(lang=lang, verb=verb) + else: + raise ValueError('Unknown documentation type: {0}'.format(doctype)) + + +def check_timestamps_in_dir(lang, src_dir, check_dir, verb=False): + vprint(verb, 'Checking timestamps for directory {0}'.format(check_dir)) + for f in os.listdir(src_dir): + src = os.path.join(src_dir, f) + if not os.path.isfile(src): + continue + check = os.path.join(check_dir, f) + if not os.path.isfile(check): + print >>sys.stderr, 'File {0} missing for language {1}.'.format(f, + lang) + continue + src_time = os.path.getmtime(src) + check_time = os.path.getmtime(check) + if src_time > check_time: + print >>sys.stderr, ('File {0} for language {1} is out of ' + 'date.'.format(f, lang)) + + +def check_timestamps(lang='en', verb=False): + vprint(verb, 'Checking timestamps for language {0}'.format(lang)) + src_dir = os.path.join(rest_dir(), lang_dir('en')) + check_dir = os.path.join(rest_dir(), lang_dir(lang)) + check_timestamps_in_dir(lang, src_dir, check_dir) + common_src_dir = os.path.join(common_dir(), lang_dir('en')) + common_check_dir = os.path.join(common_dir(), lang_dir(lang)) + check_timestamps_in_dir(lang, common_src_dir, common_check_dir) + + +def main(argv): + usage = ('Usage:: %prog [options] [type]\n' + 'Generate documentation from the reStructuredText source files.\n' + 'All languages will be generated if none are specified.') + parser = optparse.OptionParser(usage=usage) + parser.add_option('-e', dest='en', action='store_true', default=False, + help='Generate the English documentation.') + parser.add_option('-j', dest='ja', action='store_true', default=False, + help='Generate the Japanese documentation.') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, help='Output verbose information.') + + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + if not args: + args = ['man', 'html', 'pdf'] + + if not options.en and not options.ja: + langs = ['en', 'ja'] + else: + langs = [] + if options.en: + langs.append('en') + if options.ja: + langs.append('ja') + print 'Languages: {0}'.format(langs) + + try: + for l in langs: + check_timestamps(l, verb=options.verbose) + for doctype in args: + generate_docs(doctype=doctype, lang=l, verb=options.verbose) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +if __name__ == '__main__': + main(sys.argv) + diff --git a/doc/rest/ja/rtact.txt b/doc/rest/ja/rtact.txt new file mode 100644 index 0000000..bec7951 --- /dev/null +++ b/doc/rest/ja/rtact.txt @@ -0,0 +1,59 @@ +===== +rtact +===== + +------------------------------ +コンポーネントを activate する +------------------------------ + +.. include: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtact [options] [ ...] + +概要 +==== + +Inactive 状態のRTコンポーネントを activate します。 + +オプション +========== + +-e EC_INDEX, --exec_context=EC_INDEX + 状態を変更したいexecution contextのインデックス。ディフォルトは0。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtact /localhost/local.host_cxt/ConsoleOut0.rtc + +すべての owned EC と participanting EC 内の ``ConsoleOut0.rtc`` を activate する。 + +:: + + $ rtact ConsoleOut0.rtc ConsoleIn0.rtc + +すべての owned EC と participanting EC 内の ``ConsoleOut0.rtc`` +と `` ConsoleIn0.rtc`` を activate する。 + +:: + + $ rtact -e 2 /localhost/local.host_cxt/Motor0.rtc + +``Motor0.rtc`` を「2」というIDで示されるECのみに対して activate する。 + +参照 +==== + +``rtdeact`` (1), +``rtreset`` (1), +``rtcat`` (1) + diff --git a/doc/rest/ja/rtcat.txt b/doc/rest/ja/rtcat.txt new file mode 100644 index 0000000..1a7a088 --- /dev/null +++ b/doc/rest/ja/rtcat.txt @@ -0,0 +1,74 @@ +===== +rtcat +===== + +-------------------------------------- +RTコンポーネントのメタデータを表示する +-------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtcat [options] + +概要 +==== + +POSIXの ``cat`` コマンドと同じです。RTコンポーネント、ポート及びマネージャ +のメタデータを読んでターミナルに表示します。 + +オプション +========== + +-l + 詳しい情報を示します。複数指定するともっと詳しい情報が表示 + されます。[デフォルト:``False``] + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc + +``Motor0.rtc`` の簡単な情報を示します。 + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc -l + +ポートとExecution Contextを含めて ``Motor0.rtc`` の詳しい情報を表示 +します。 + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc -ll + +ポートの接続を含めて ``Motor0.rtc`` の詳しい情報を表示します。 + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc:in -l + +``Motor0.rtc`` の ``in`` ポートのみの情報を表示します。 + +:: + + $ rtcat /localhost/local.host_cxt/manager.mgr + +``manager.mgr`` というマネージャの簡単な情報を示します。 + +参照 +==== + +``rtcon`` (1), +``rtconf`` (1), +``rtprint`` (1), +``rtstodot`` (1) + diff --git a/doc/rest/ja/rtcheck.txt b/doc/rest/ja/rtcheck.txt new file mode 100644 index 0000000..d9b706a --- /dev/null +++ b/doc/rest/ja/rtcheck.txt @@ -0,0 +1,72 @@ +======= +rtcheck +======= + +------------------------ +RTシステムをチェックする +------------------------ + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtcheck [options] + +概要 +==== + +実行中のRTシステムとRTSProfileとで矛盾がないかをチェックします。 +正しくない状態にあるコンポーネントや間違った接続などのようなエラーを報告します。 + +デフォルトでRTSProfileファイルをXMLとしてロードします。YAMLを使う場合 +は ``--yaml`` を使ってください。 + +オプション +========== + +--dry-run + 何をするかを表示し、実行しない + +-s STATE, --state=STATE + 全コンポーネントの期待される状態。デフォルトは``Active``です。 + +-x, --xml + XMLフォーマットを使う + +-y, --yaml + YAMLフォーマットを使う + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtcheck sys.rtsys + +``sys.rtsys`` というRTSProfileファイルに保存されたシステムはエラーなしに +起動中ですべてのコンポーネントは active 状態だと確認します。 + +:: + + $ rtcheck sys.rtsys -s Inactive + +全コンポーネントは inactive の状態にある以外は上記と同じです。 + +:: + + $ rtcheck sys.rtsys --dry-run + +システムチェックのために何をするかを表示します。 + +参照 +==== + +``rtcat`` (1), +``rtresurrect`` (1), +``rtstart`` (1) + diff --git a/doc/rest/ja/rtcomp.txt b/doc/rest/ja/rtcomp.txt new file mode 100644 index 0000000..a33f16c --- /dev/null +++ b/doc/rest/ja/rtcomp.txt @@ -0,0 +1,120 @@ +====== +rtcomp +====== + +-------------------------------- +コンポジットコンポーネントの管理 +-------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtcomp [options] + +概要 +==== + +実行している複数のコンポーネントを一つのコンポジットコンポーネントとして +構成し、選択されたポートを外部に公開します。Execution contextも選択する +ことが可能です。また、新しいコンポジットコンポーネントを作成したり、既存 +のコンポジットコンポーネントを編集することが可能です。 +さらに、既存のコンポジットコンポーネントに新しいメンバーを追加、またはメ +ンバーを削除することができます。 +公開されているポートの変更も可能です。 + +オプションには既存のコンポジットコンポーネントのパスまたはマネージャのパ +スが必要です。マネージャを指定した場合、新しいコンポジットコンポーネント +を作成します。コンポジットコンポーネントの名前を指定する場合はマネージャ +のパスにコロンと名前を追加することで指定可能です。名前が指定されていない +場合はデフォルトが選択されます。 +`例`_ を参照してください。 + +コンポーネントを追加(-a)または削除(-r)する場合、公開または非公開する +ポートはコンポーネントのパスにカンマで区切ったリストとして指定してくださ +い。 `例`_ を参照してください。 + +オプション +========== + +-a ADD, --add=ADD + コンポジットコンポーネントに含むコンポーネントとポートを指定する。 + ポート名はカンマで区切ったリストとしてパスに追加する。 + このオプションは複数指定可能。 + +-o OPTIONS, --options=OPTIONS + コンポーネント作成時の追加オプション。 + +-r REMOVE, --remove=REMOVE + コンポジットコンポーネントから削除するコンポーネントやポートを指定する。 + ポート名はカンマで区切ったリストとしてパスに追加する。 + このオプションは複数指定可能。 + +-t TYPE, --type=TYPE + Execution contextのタイプ。[デフォルト: PeriodicECSharedComposite] + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtcomp /localhost/manager.mgr:MotorUnit -a + /localhost/Motor0.rtc:out -a /localhost/Controller0.rtc:in,out + +``Controller0.rtc`` の ``in`` というポートと ``Motor0.rtc`` の ``out`` という +ポートを公開して ``Motor0.rtc`` と ``Controller0.rtc`` によってコンポジットコ +ンポーネントを作成します。コンポジットコンポーネントのインスタンス名は +``MotorUnit`` になります。 + +:: + + $ rtcomp /localhost/MotorUnit.rtc -a /localhost/Sensor0.rtc:out + +既存の ``MotorUnit.rtc`` コンポジットコンポーネントを編集し、 +``Sensor0.rtc`` の ``out`` ポートを公開して ``Sensor0.rtc`` を +コンポジットコンポーネントに追加します。 + +:: + + $ rtcomp /localhost/MotorUnit.rtc -a /localhost/Sensor0.rtc:in + +すでに ``Sensor0.rtc`` がメンバーとして登録されている既存の ``MotorUnit.rtc`` +コンポジットコンポーネントを編集し、 ``Sensor0.rtc`` の ``in`` ポートを公開 +します。 + +:: + + $ rtcomp /localhost/MotorUnit.rtc -r /localhost/Sensor0.rtc:out + +すでに ``Sensor0.rtc`` がメンバーとして登録されている既存の ``MotorUnit.rtc`` +コンポジットコンポーネントを編集し、 ``Sensor0.rtc`` の ``out`` ポートを非公 +開にします。 + +:: + + $ rtcomp /localhost/MotorUnit.rtc -r /localhost/Controller0.rtc:in,out + +すでに ``Controller0.rtc`` がメンバーとして登録されている既存の ``MotorUnit.rtc`` +コンポジットコンポーネントを編集し、 ``Controller0.rtc`` の ``in`` と ``out`` +ポートを非公開にします。 + +:: + + $ rtcomp /localhost/MotorUnit.rtc -r /localhost/Controller0.rtc -r + /localhost/Motor0.rtc + +すでに ``Controller0.rtc`` と ``Motor0.rtc`` がメンバーとして登録されている +既存の ``MotorUnit.rtc`` コンポジットコンポーネントを編集し、 ``Controller0.rtc`` +と ``Motor0.rtc`` を削除します。 + + +参照 +==== + +``rtmgr`` (1) + diff --git a/doc/rest/ja/rtcon.txt b/doc/rest/ja/rtcon.txt new file mode 100644 index 0000000..31d1c7a --- /dev/null +++ b/doc/rest/ja/rtcon.txt @@ -0,0 +1,110 @@ +===== +rtcon +===== + +---------------- +ポートを接続する +---------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtcon [options] [ ...] + +概要 +==== + +二つ以上のデータポートやサービスポートを接続します。 + +データポートの場合に有効なプロパティは:: + + - dataport.data_type (ポートのデータ型) + - dataport.dataflow_type (データの流れ方法) + - dataport.interface_type (ポートのプロトコル) + - dateport.serializer.cdr.endian + +サービスポートの場合に有効なプロパティは:: + + - port.port_type + +データポートの場合、以下のプロパティも使えます。プロパティの間に依存が +ありますので、プロパティによって他のプロパティは影響がない時もあります。 + +========================================= ============================ ==== +プロパティ 値 依存 +========================================= ============================ ==== +dataport.inport.buffer.length +dataport.inport.buffer.read.timeout in seconds +dataport.inport.buffer.read.empty_policy readback, do_nothing, block +dataport.inport.buffer.write.timeout in seconds +dataport.inport.buffer.write.full_policy overwrite, do_nothing, block +dataport.outport.buffer.length +dataport.outport.buffer.read.timeout in seconds +dataport.outport.buffer.read.empty_policy readback, do_nothing, block +dataport.outport.buffer.write.timeout in seconds +dataport.outport.buffer.write.full_policy overwrite, do_nothing, block +dataport.subscription_type flush, new, periodic dataport.dataflow_typeがpush +dataport.publisher.push_policy all, fifo, skip, new dataport.subscription_typeがflushではない +dataport.push_rate in Hz dataport.subscription_typeがperiodic +dataport.publisher.skip_count dataport.publisher.push_policyがskip +========================================= ============================ ==== + +OpenRTMのバージョンによっては、ほかのプロパティも有効な場合があります。 + +オプション +========== + +-i ID, --id=ID + コネクションのID + +-n NAME, --name=NAME + コネクションの名 + +-p PROPERTIES, --property=PROPERTIES + コネクションのプロパティ + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtcon /localhost/ConsoleIn0.rtc:out /localhost/ConsoleOut0.rtc:in + +デフォルトプロパティを使って ``ConsoleIn0.rtc`` の ``out`` ポートを +``ConsoleOut0.rtc`` の ``in`` ポートに接続します。 + +:: + + $ rtcon Motor0.rtc:out Sensor0.rtc:in --property + dataport.dataflow_type=pull + +``Pull`` 型のコネクションによって ``Motor0.rtc`` の ``out`` ポートを +``Sensor0.rtc`` の ``in`` ポートに接続します。 + +:: + + $ rtcon Motor0.rtc:out Sensor0.rtc:in -i con1 -n motor_data + +``Motor0.rtc`` の ``out`` ポートを ``Sensor0.rtc`` の ``in`` ポートに接続しま +す。コネクション名は ``motor_data`` でIDは ``con1`` になります。 + +:: + + $ rtcon ConsoleIn0.rtc:out ConsoleOut0.rtc:in ConsoleOut1.rtc:in + +デフォルトプロパティを使って ``ConsoleIn0.rtc`` の ``out`` ポートを +``ConsoleOut0.rtc`` の ``in`` ポートと ``ConsoleOut1.rtc`` の ``in`` +ポートに接続します。 + +参照 +==== + + ``rtcat`` (1), + ``rtdis`` (1) + diff --git a/doc/rest/ja/rtconf.txt b/doc/rest/ja/rtconf.txt new file mode 100644 index 0000000..35860f0 --- /dev/null +++ b/doc/rest/ja/rtconf.txt @@ -0,0 +1,161 @@ +====== +rtconf +====== + +------------------------------------ +コンフィグレーションパラメータの管理 +------------------------------------ + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtconf [options] [command] [args] + +概要 +==== + +コンフィグレーションパラメータとセットを表示、編集します。 + +「command」は以下のいずれかを使ってください。 + + - list + - set + - get + - act + +「command」が指定されていない場合、 ``list`` コマンドを実行します。 + +:: + + list + +``list`` コマンドはコンフィグレーションセットとパラメータを表示します。 +隠されたセット(セット名は ``__`` で始まる)は表示しません。 + +:: + + set + +コンフィグレーションパラメータの値を編集します。パラメータ名と新しい値 +を指定してください。 ``--set`` オプションが指定されていない場合、現在の +アクティブセットのパラメータを編集します。 + +:: + + get + +一つのパラメータの値を表示します。パラメータ名を指定してください。 +``--set`` オプションが指定されていない場合、現在のアクティブセットの値を +表示します。 + +:: + + act + +アクティブセットを変更します。セット名は ``--set`` で指定してください。 + +オプション +========== + +-a, --all + 隠されたセットを無視しない。隠されたセットを編集したい方はこのオプ + ションを指定してください。 + +-l + 詳しい情報を表示する。 + +-s SET_NAME, --set=SET_NAME + セットを選択する。指定されていない場合、現在のアクティブセットを使う。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtconf /localhost/ConfigSample0.rtc list + +default* + +mode0 + +mode1 + +``ConfigSample0.rtc`` のセットを表示します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc -l list + -default* + double_param0 0.99 + double_param1 -0.99 + ... + +``ConfigSample0.rtc`` のセットとパラメータを表示します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc -a list + +__constraints__ + +__widget__ + +default* + +mode0 + +mode1 + +隠されたセットを含めて ``ConfigSample0.rtc`` のセットを表示します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc -l -s default list + -__constraints__ + double_param0 0<=x<=100 + double_param1 + ... + +``ConfigSample0.rtc`` の ``default`` セットのパラメータを表示します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc set int_param0 42 + +現在のアクティブセットの ``int_param0`` パラメータの値を42に編集します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc -s mode0 set int_param0 42 + +``mode0`` というセットの ``int_param0`` を42に編集します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc get int_param0 + 0 + +現在のアクティブセットの ``int_param0`` パラメータの値を取得します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc -s mode0 get int_param0 + 12345 + +``mode0`` というセットの ``int_param0`` パラメータの値を取得します。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc act mode1 + +現在のアクティブセットを ``mode1`` というセットにします。 + +:: + + $ rtconf /localhost/ConfigSample0.rtc -a act __widget__ + +現在のアクティブセットを ``__widget__`` というセットにします。 + +参照 +==== + + ``rtcat`` (1) + diff --git a/doc/rest/ja/rtcryo.txt b/doc/rest/ja/rtcryo.txt new file mode 100644 index 0000000..e1cbccf --- /dev/null +++ b/doc/rest/ja/rtcryo.txt @@ -0,0 +1,92 @@ +====== +rtcryo +====== + +---------------------------------------- +RTシステムをRTSProfileファイルに保存する +---------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtcryo [options] [name servers] + +概要 +==== + +実行中のRTシステムをRTSProfileに保存します。コンポーネント間の接続と +コンポーネントの現在のコンフィグレーションパラメータを保存します。接続 +されていないコンポーネントは保存しません。 + +ファイル名を指定しない場合、RTSProfileを ``stdout`` に出力します。デフォ +ルトはXMLで保存します。 + +オプション +========== + +-a ABSTRACT, --abstract=ABSTRACT + RTシステムの概要 + +-n SYSNAME, --system-name=SYSNAME + RTシステムの名前。 + +-o OUTPUT, --output=OUTPUT + 出力ファイル名。指定しない場合は ``stdout`` に出力します。 + +-v VERSION, --system-version=VERSION + RTシステムのバージョン。 + +-e VENDOR, --vendor=VENDOR + RTシステムのベンダー。 + +-x, --xml + XMLで出力する。 + +-y, --yaml + YAMLで出力する。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtcryo + +すべての分かるネームサーバのすべての接続されているコンポーネントを一つ +のRTシステムとしてRTSProfileい保存してstdoutに出します。 + +:: + + $ rtcryo -o sys.rtsys + +全ての既知のネームサーバ上の全コンポーネントを一つのRTシステムとして +RTSProfileを ``sys.rtsys`` というファイルに保存します。 + +:: + + $ rtcryo localhost + +``localhost`` というネームサーバのすべての接続されているコンポーネントを一つ +のRTシステムとしてRTSProfileに保存してstdoutに出します。 + +:: + + $ rtcryo -n 'mysystem' -v 1.0 + +RTシステムの名前を ``mysystem`` 、バージョンを ``1.0`` としてRTSProfileを +保存します。 + +参照 +==== + + ``rtcheck`` (1), + ``rtcon`` (1), + ``rtconf`` (1), + ``rtstart`` (1) + diff --git a/doc/rest/ja/rtcwd.txt b/doc/rest/ja/rtcwd.txt new file mode 100644 index 0000000..1eb164b --- /dev/null +++ b/doc/rest/ja/rtcwd.txt @@ -0,0 +1,61 @@ +===== +rtcwd +===== + +---------------------------------- +現在のワーキングディレクトリの変更 +---------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtcwd [path] + +概要 +==== + +RTCツリーの中の現在のワーキングディレクトリを変更します。 + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtcwd + +ルートディレクトリに移動します。 + +:: + + $ rtcwd / + +ルートディレクトリに移動します。 + +:: + + $ rtcwd /localhost/local.host_cxt + +``/localhost/local.host_cxt`` というディレクトリに移動します。 + +:: + + $ rtcwd .. + +親ディレクトリに移動します。 + +:: + + $ rtcwd ../.. + +親ディレクトリの親ディレクトリに移動します。 + +参照 +==== + + ``rtls`` (1), + ``rtpwd`` (1) + diff --git a/doc/rest/ja/rtdeact.txt b/doc/rest/ja/rtdeact.txt new file mode 100644 index 0000000..d226ccc --- /dev/null +++ b/doc/rest/ja/rtdeact.txt @@ -0,0 +1,59 @@ +======= +rtdeact +======= + +-------------------------------- +コンポーネントを deactivate する +-------------------------------- + +.. include: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtdeact [options] [ ...] + +概要 +==== + +Active 状態のRTコンポーネントを deactivate します。 + +オプション +========== + +-e EC_INDEX, --exec_context=EC_INDEX + 状態を変更するexecution contextのID。デフォルトは0。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtdeact /localhost/local.host_cxt/ConsoleOut0.rtc + +``ConsoleOut0.rtc`` のすべてのEC上で deactivate する。 + +:: + + $ rtdeact ConsoleOut0.rtc ConsoleIn0.rtc + +``ConsoleOut0.rtc`` と ``ConsoleIn0.rtc`` のすべてのEC上で +deactivate する。 + +:: + + $ rtdeact -e 2 /localhost/local.host_cxt/Motor0.rtc + +``Motor0.rtc`` を「2」というIDで示されるECのみで deactivate する。 + +参照 +==== + +``rtact`` (1), +``rtreset`` (1), +``rtcat`` (1) + diff --git a/doc/rest/ja/rtdel.txt b/doc/rest/ja/rtdel.txt new file mode 100644 index 0000000..167d715 --- /dev/null +++ b/doc/rest/ja/rtdel.txt @@ -0,0 +1,75 @@ +===== +rtdel +===== + +---------------------------------- +ネームサーバからオブジェクトを消す +---------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtdel [options] + +概要 +==== + +ネームサーバから登録済みオブジェクトを消します。このコマンドでオブジェク +ト自身を終了することはできません。オブジェクトは他のところに登録されてい +ない場合、そのオブジェクトに接続できない状態になるので注意してくだ +さい。コンテキストやマネージャを消す時、他のオブジェクトも消す可能性が +あるので注意してください。 + +このコマンドはゾンビを消すのに便利です。一つのコマンドですべてのゾン +ビを消すことが可能です。 + +オプション +========== + +-z, --zombies + ゾンビのみを消す。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtdel /localhost/Motor0.rtc + +``localhost`` というネームサーバから ``Motor0.rtc`` を消します。コンポーネ +ントは終了しません。 + +:: + + $ rtdel -z /localhost/Motor0.rtc + +``localhost`` というネームサーバから ``Motor0.rtc`` というゾンビを消しま +す。 ``Motor0.rtc`` はゾンビではない場合は消しません。 + +:: + + $ rtdel /localhost/local.host_cxt + +``localhost`` というネームサーバから ``local.host_cxt`` というコンテキス +トを消します。そのコンテキストの中のコンポーネントやマネージャはすべて消 +します。 + +:: + + $ rtdel -z + +すべてのネームサーバからすべてのゾンビを消します。 + + +参照 +==== + + ``rtls`` (1), + ``rtmgr`` (1) + diff --git a/doc/rest/ja/rtdis.txt b/doc/rest/ja/rtdis.txt new file mode 100644 index 0000000..d64193e --- /dev/null +++ b/doc/rest/ja/rtdis.txt @@ -0,0 +1,73 @@ +===== +rtdis +===== + +---------- +接続を消す +---------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtdis [options] [ ...] + +概要 +==== + +ポートの間の接続を消します。一つのポートから全ての接続を消すこともコンポーネン +トから全ての接続を消すことも可能です。 + +オプション +========== + +-i ID, --id=ID + 接続のID。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtdis /localhost/ConsoleIn0.rtc:out /localhost/ConsoleOut0.rtc:in + +``ConsoleIn0.rtc`` の ``out`` ポートと ``ConsoleOut0.rtc`` の ``in`` ポートの +間の全ての接続を消します。 + +:: + + $ rtdis /localhost/ConsoleIn0.rtc:out + +``ConsoleIn0.rtc`` の ``out`` ポートに接続されている全ての接続を消します。 + +:: + + $ rtdis /localhost/ConsoleIn0.rtc + +``ConsoleIn0.rtc`` の全てのポートから全ての接続を消します。 + +:: + + $ rtdis -i con1 /localhost/ConsoleIn0.rtc:out + +``ConsoleIn0.rtc`` の ``out`` ポートから ``con1`` というIDを持つ接続のみを消 +します。 + +:: + + $ rtdis -i con1 /localhost/ConsoleIn0.rtc + +``ConsoleIn0.rtc`` のポートのうち ``con1`` というIDの接続のみを消 +します。 + +参照 +==== + + ``rtcat`` (1), + ``rtcon`` (1) + diff --git a/doc/rest/ja/rtdoc.txt b/doc/rest/ja/rtdoc.txt new file mode 100644 index 0000000..446de1e --- /dev/null +++ b/doc/rest/ja/rtdoc.txt @@ -0,0 +1,167 @@ +===== +rtdoc +===== + +------------------------------------------------ +RTコンポーネントのドキュメンテーションを表示する +------------------------------------------------ + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtdoc [options] + +概要 +==== + +RTコンポーネントのドキュメンテーションを表示します。 + +あるRTコンポーネントは内部的にドキュメントを含んでおり、それは、隠され +たコンフィグレーションセットに保存されています。 +このツールでそのドキュメンテーションを複数のフォーマットで表示できます。 +対応フォーマットは reStructuredText、HTML、およびPDFへのコンパイルに +適しているLaTeXです。 + +オプション +========== + +-f FORMAT, --format=FORMAT + フォーマットを選択します。 ``rst`` 、 ``html`` および ``latex`` から選択し + てください。 + +-g, --graph + コンポーネントのグラフを表示させます。 + +.. include:: ../../common/ja/common_opts.txt + +RTコンポーネントのドキュメンテーション +====================================== + +このツールに対応するためにRTコンポーネントは ``__doc__`` というセットに +ドキュメンテーションを保存しないとなりません。このセットでの隠されていな +いパラメータはすべてセクションとしてドキュメンテーションに追加されます。 +隠されたセットは名が ``__`` で囲まれています。 + +一般のセクションは以下の通りです:: + + intro + コンポーネントの紹介です。目的を短く説明します。(Title: + ``Introduction``.) + + reqs + ほかの必要なソフトなどのコンポーネントを使うための要件です。 + (Title: ``Pre-requisites``.) + + install + コンポーネントのインストール手続きです。 + (Title: ``Installation``.) + + usage + コンポーネントの使い方です。(Title: ``Usage``.) + + misc + ほかの必要な情報です。(Title: ``Miscellaneous``.) + + changelog + コンポーネントのバージョン間の変更を説明します。 + (Title: ``Changelog``.) + +上記に加え、コンポーネントにポートがある場合、 ``ports`` というセクションが +自動的に作られて、 ``default`` というセットにコンフィグレーションパラメー +タがある場合、 ``config`` というセクションが自動的に作られます。 +``__doc__`` セットにほかのセクションがある場合、それも自動的に作られます。 + +拡張情報をドキュメンテーション前文に追加するため、3つパラメータをセッ +トすることもできます。 +``__doc__`` セットにパラメータを設定してください。 + + __license__ + コンポーネントのライセンス。LGPL、BSD等。 + + __contact__ + 開発者の連絡先。メールアドレス等。 + + __url__ + コンポーネントのウェブサイト。 + +ドキュメンテーションのパラメータはソースまたはコンフィグレーションファイ +ルに設定することも可能です。ソースに設定した場合コンポーネントを使う時に必 +要なメモリーが大きくなることがあるので、ファイルの方がおすすめです。 + +ソースに設定する場合は以下のようにできます:: + + 'conf.__doc__.__license__', 'LGPL', + 'conf.__doc__.__contact__', 'a@example.com', + 'conf.__doc__.__url__', 'http://www.openrtm.org', + 'conf.__doc__.intro', 'This is the introduction.', + 'conf.__doc__.reqs', 'This component requires nothing.', + 'conf.__doc__.install', 'Type "make install"', + 'conf.__doc__.usage', 'Run comp_standalone.', + 'conf.__doc__.misc', 'Extra information.', + 'conf.__doc__.changelog', 'No changes.', + 'conf.__doc__.Another', 'A non-standard section.', + +デフォルトでセクションは以下の順番に表示します。 + + intro, reqs, usage, ports, config, misc, changelog, [他のセクション] + +``__doc__`` セットの ``__order__`` というパラメータを設定することによって +変更することが可能です。パラメータ名のリストにコンマ区切りで設定してください。 +パラメータ名はセクションを示します:: + + 'conf.__doc__.__order__', 'intro,ports,config,reqs,Another' + +このパラメータに入っていないセクションはその後に表示します。 + +ポートのドキュメンテーションは ``description`` というプロパティをポートに +追加します:: + + self._inport.addProperty('description', 'This port receives stuff.') + +コンフィグレーションパラメータのドキュメンテーションは +``__description__`` というセットに設定します:: + + 'conf.default.param', '0', + 'conf.__description__.param', 'A test parameter.', + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc + +``ConsoleOut0.rtc`` のドキュメンテーションを標準出力に表示します。 + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc > doc.html + +``ConsoleOut0.rtc`` のドキュメンテーションを ``doc.html`` というファイルに +保存します。 + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc -f rst + +``ConsoleOut0.rtc`` のドキュメンテーションをreStructuredTextフォーマット +に表示します。 + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc -f latex > doc.tex && + rubber -d doc.tex + +``ConsoleOut0.rtc`` のドキュメンテーションを ``rubber`` ツールによってPDF +に保存します。 + +参照 +==== + + ``rtconf`` (1), + ``rubber`` (1) + diff --git a/doc/rest/ja/rtexit.txt b/doc/rest/ja/rtexit.txt new file mode 100644 index 0000000..cffb4dd --- /dev/null +++ b/doc/rest/ja/rtexit.txt @@ -0,0 +1,42 @@ +====== +rtexit +====== + +-------------------------- +RTコンポーネントを終了する +-------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtexit [options] + +概要 +==== + +実行中のRTコンポーネントを終了させます。コンポーネントは終了手続きをし +て終了します。 + +オプション +========== + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtexit /localhost/ConsoleOut0.rtc + +``ConsoleOut0.rtc`` コンポーネントを終了します。 + +参照 +==== + + ``rtdel`` (1) + diff --git a/doc/rest/ja/rtfind.txt b/doc/rest/ja/rtfind.txt new file mode 100644 index 0000000..54970a1 --- /dev/null +++ b/doc/rest/ja/rtfind.txt @@ -0,0 +1,86 @@ +====== +rtfind +====== + +--------------- +RTCツリーを探索 +--------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtfind [options] + +概要 +==== + +RTCツリーのネームサーバ上でコンポーネントやマネジャーなどを探索します。探す +条件を設定することは可能です。 + +オプション +========== + +-i INAME, --iname=INAME + 小文字と大文字を区別なしで名前で探す。複数回指定可能。 + +-m MAX_DEPTH, --maxdepth=MAX_DEPTH + 探す時の深さ制限。デフォルトはすべてのツリーを探査します。 + +-n NAME, --name=NAME + 小文字と大文字を区別して名前で探す。複数回指定可能。 + +-t TYPE, --type=TYPE + オブジェクトの種類。文字で指定してください。 + ``c`` (コンポーネント), ``d`` (ダイレクトリ), ``m`` (マネージャ), + ``n`` (ネームサーバ), ``z`` (ゾンビ). + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtfind / -t c + +RTCツリーの中のすべてのコンポーネントを探します。ルートディレクトリか +ら探し始めます。 + +:: + + $ rtfind . -t cm + +現在のワーキングディレクトリの下のすべてのコンポーネントとマネージャを +探します。 + +:: + + $ rtfind . -n 'Conso*' -type c + +現在のワーキングダイレクトリの下に名が ``Conso`` で始まるコンポーネントを +探します。 + +:: + + $ rtfind . -i 'console?.rtc' -type c + +現在のワーキングディレクトリの下の名前が ``console`` で始まり ``.rtc`` で終 +わって、その間に一字のみあるコンポーネントを探します。小文字と大文字を区別しま +せん。 + +:: + + $ for c in `rtfind . -type c -m 1`; do rtact ${c}; done + +(POSIXのみ)現在のワーキングディレクトリのすべてのコンポーネントを +activate します。 + +参照 +==== + + ``rtls`` (1) + diff --git a/doc/rest/ja/rtinject.txt b/doc/rest/ja/rtinject.txt new file mode 100644 index 0000000..47f34a1 --- /dev/null +++ b/doc/rest/ja/rtinject.txt @@ -0,0 +1,132 @@ +======== +rtinject +======== + +-------------------- +ポートにデータを送る +-------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtinject [options] [path2:port2...] + +概要 +==== + +値を一つ以上のポートに送ります。デフォルトは一回のみ送ります。複数回や +定期的に送ることもできます。 + +目的のポートにデフォルトの接続を作ります。 + +オプション +========== + +-c CONST, --const=CONST + Pythonフォーマットとして送る一定値。指定されていない場合、標準入力 + から値を読む。 ``{time}`` が存在する場合、現在の時刻に置き換えられる。 + +-m MODULES, --mod=MODULES + Import する必要な Python モジュール。値の必要なモジュールが自動的に + ロードされていない場合、このオプションで指定してください。モジュール + とそのモジュールの ``__POA`` のモジュールも import します。 + +-n MAX, --number=MAX + 値を何回送るかを指定する。 ``-1`` に設定した場合、永遠に送り続けます。 + +-p PATHS, --path=PATHS + モジュールのサーチパス。Pythonの ``PYTHONPATH`` 変数に追加する。 + +-r RATE, --rate=RATE + 周期を指定する。単位はヘルツ。 + +-t TIMEOUT, --timeout=TIMEOUT + タイムアウト時間を指定する。単位は秒。このオプションは ``--number`` + と一緒に使用で来ません。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in + +stdinからの値を ``ConsoleOut0.rtc`` の ``in`` ポートに送ります。 + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -c + 'RTC.TimedLong({time}, 42)' + +``42`` と現在の時刻を ``consoleout0.rtc`` の ``in`` ポートに送ります。「'」を +使ってpythonのステートメントを守ります。(Windowsでは「"」を使ってくださ +い。) + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -c + 'RTC.TimedLong(RTC.Time(1, 0), 42)' + +``42`` とタイムスタンプを1秒として ``ConsoleOut0.rtc`` の ``in`` ポートに送ります。 + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -n 5 + +stdinからの値を五回 ``ConsoleOut0.rtc`` の ``in`` ポートに送ります。 + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -n 5 -c + 'RTC.TimedLong({time}, 42)' + +``42`` と現在の時刻を ``consoleout0.rtc`` の ``in`` ポートに5回送ります。 + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -t 5 -r 10 -c + 'RTC.TimedLong({time}, 42)' + +``42`` と現在の時刻を10Hzで ``consoleout0.rtc`` の ``in`` ポートに5秒間送 +ります。 + +:: + + $ rtinject /localhost/MyComp0.rtc:in -c 'MyData.MyVal(84)' + +``MyData.MyVal(84)`` を ``MyComp0.rtc`` の ``in`` ポートに送ります。クラスは +Pythonのサーチパス(``PYTHONPATH``)に存在するモジュールに指定されていま +す。そのモジュールはOMG IDLファイルからジェネレートされました。 + +:: + + $ rtinject /localhost/MyComp0.rtc:in -p /usr/local/mods + -c 'MyData.MyVal(84)' + +``MyData.MyVal(84)`` を ``MyComp0.rtc`` の ``in`` ポートに送ります。クラスは +Pythonのサーチパス(``PYTHONPATH``)に存在しないモジュールに指定されていま +す。モジュールのパスは``-p``で指定されます。 + +:: + + $ rtinject /localhost/MyComp0.rtc:in -p /usr/local/mods -m mymod + -c 'MyData.MyVal(84)' + +``MyData.MyVal(84)`` を ``MyComp0.rtc`` の ``in`` ポートに送ります。クラスは +Pythonのサーチパス(``PYTHONPATH``)に存在する ``mymod`` というモジュール +を指定します。 + + +参照 +==== + + ``rtcat`` (1), + ``rtlog`` (1), + ``rtprint`` (1) + diff --git a/doc/rest/ja/rtlog.txt b/doc/rest/ja/rtlog.txt new file mode 100644 index 0000000..afd039c --- /dev/null +++ b/doc/rest/ja/rtlog.txt @@ -0,0 +1,256 @@ +===== +rtlog +===== + +------------------------------------------ +ポートのデータをログに保存、再生する +------------------------------------------ + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtlog [options] : [:...] + +概要 +==== + +コンポーネントがデータポートで送るデータをログファイルに保存したり、再 +生したりします。複数のポートでもログが可能です。ログされたコンポーネント +を再現するためにログファイルを再生することが加能です。 + +ログの複数データストリームから再生されたストリームを選択することができま +す。例えばログに複数のレーザからのデータが保存されたら一つのみのレーザ +データを再生することが加能です。再生はログの始まりだけではなくて途中から +途中までを再生して、再生レートを変えたり出力されたデータのタイムスタン +プを編集することも可能です。 + +デフォルトでログを保存します。コマンドに渡したすべてのポートはアウトポ +ートにする必要があります。再生モードの場合、すべてのポートはインポートに +してログのデータ型に合わせる必要があります。 + +ログで記録されるそれぞれのポートは一つのデータストリームを作ります。 +再生の時、このデータストリームは複数のインポートに送ることができます。 +データストリームは名前で区別されます。名前はコマンドラインに与えられな +かった場合、デフォルトの名前を自動的に作ります。 + +ログツールから目的のポートまでの接続はデフォルトのプロパティで作られま +す。 + +オプション +========== + +-a, --absolute-times + ログデータからのタイムスタンプは記録されたままの値を送ります。 + 指定しない場合、タイムスタンプは現在の時刻でオフセットされます。 + +-d, --display-info + ログの情報を表示して終了します。 + +-e END, --end=END + 記録や再生を止めるタイムスタンプまたはインデクスを指定します。ログの + 最初と最後のデータの間を指定してください。 ``-1`` を指定すると永遠に記 + 録またはログの最後まで再生します。インデクスで指定したい場合、 + ``--index`` も指定してください。 + +-f FILENAME, --filename=FILENAME + ログファイルの名前を指定します。指定しない場合、現在の時刻がファイル + 名になります。 + 再生の時は必須です。 + +--path=PATHS + モジュールのサーチパスを指定します。Pythonの ``PYTHONPATH`` 変数に追加 + されます。 + + +-i, --index + ``--start`` と ``--end`` の値をタイムスタンプではなくてインデクスとして + 指定します。 + +-l LOGGER, --logger=LOGGER + ログ種類を選択します。デフォルトはSimplePickle( ``simpkl`` )です。テ + キストログ( ``text`` )を使うこともできます。テキストログは再生できま + せん。 + +-m MODULES, --mod=MODULES + Import する必要な Python モジュールを指定します。値に必要なモジュー + ルが自動的にロードされていない場合、このオプションで指定してください。 + モジュールとそのモジュールの ``__POA`` のモジュールも import します。 + +-n, --ignore-times + (再生のみ)ログに記録されたタイムスタンプを無視して定期的にログデー + タを再生します。周期を変える場合、 ``--exec-rate`` を使ってください。 + +-p, --play + 再生モード。 + +-r RATE, --rate=RATE + (再生のみ)再生レートをスケールします。 + +-s START, --start=START + (再生のみ)再生を始めるタイムスタンプまたはインデクスを指定します。 + ログの最初と最後のデータの間にすることは必須です。インデクスで指定す + る場合、 ``--index`` も指定してください。 + +-t TIMEOUT, --timeout=TIMEOUT + 記録または再生のタイムアウト時間を指定します。このオプションを使う場 + 合、 ``--start`` と ``--end`` を使うことはできません。 + +-x EXEC_RATE, --exec-rate=EXEC_RATE + コンポーネントの実行レートを指定します。単位はヘルツです。 + + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtlog -f log.rtlog /localhost/ConsoleIn0.rtc:out.numbers + +``ConsoleIn0.rtc`` コンポーネントは ``out`` ポートで送るデータをログします。 +データストリームは ``numbers`` という名前で区別されます。ログファイル名は +``log.rtlog`` です。 + +:: + + $ rtlog -f log.rtlog -p /localhost/ConsoleOut0.rtc:in.numbers + +ログファイルから ``numbers`` というデータストリームを ``ConsoleOut0.rtc`` の +``in`` ポートに再生します。 + +:: + + $ rtlog -f log.rtlog -d + +ログの情報を表示します。ログの開始時間、終了時間、データストリーム等が +含まれています。 + + +:: + + $ rtlog -f log.rtlog -e 1292489690 + /localhost/ConsoleIn0.rtc:out.numbers + +コンピュータの時計が「1292489690」になるまでログし、終了します。 + +:: + + $ rtlog -f log.rtlog -e 10 -i /localhost/ConsoleIn0.rtc:out.numbers + +10個のデータをログして終了します。 + +:: + + $ rtlog -f log.rtlog -t 10 /localhost/ConsoleIn0.rtc:out.numbers + +10秒間ログして終了します。 + +:: + + $ rtlog -f log.rtlog -p -s 1292489690 + /localhost/ConsoleOut0.rtc:in.numbers + +「1292489690」のタイムスタンプから再生を始めます。 + +:: + + $ rtlog -f log.rtlog -p -e 1292489700 + /localhost/ConsoleOut0.rtc:in.numbers + +最初のデータから「1292489700」のタイムスタンプまで再生します。 + +:: + + $ rtlog -f log.rtlog -p -s 1292489690 -e 1292489700 + /localhost/ConsoleOut0.rtc:in.numbers + +「1292489690」のタイムスタンプから「1292489700」のタイムスタンプまで再 +生します.(大体10秒のデータ。) + +:: + + $ rtlog -f log.rtlog -p -s 5 -i + /localhost/ConsoleOut0.rtc:in.numbers + +5個目のデータから再生を始めます。 + +:: + + $ rtlog -f log.rtlog -p -e 10 /localhost/ConsoleOut0.rtc:in.numbers + +最初のデータから10個目のデータまで再生します。 + +:: + + $ rtlog -f log.rtlog -p -s 5 -e 10 + /localhost/ConsoleOut0.rtc:in.numbers + +5個目のデータから10個目のデータまで再生します。(5個のデータ。) + +:: + + $ rtlog -f log.rtlog -p -t 10 /localhost/ConsoleOut0.rtc:in.numbers + +最初の10秒間のデータを再生します。 + +:: + + $ rtlog -f log.rtlog -p -r 5 /localhost/ConsoleOut0.rtc:in.numbers + +ログの記録の早さを5倍で再生します。 + +:: + + $ rtlog -f log.rtlog -p -r 0.2 /localhost/ConsoleOut0.rtc:in.numbers + +ログの記録の早さを0.2倍で再生します。 + +:: + + $ rtlog -f log.rtlog -p -n 5 -x 1 /localhost/ConsoleOut0.rtc:in.numbers + +1秒に1回実行して、1回の実行で5個のデータを再生します。 + +:: + + $ rtlog -f log.rtlog /localhost/Sensor0.rtc:out.sensor + /localhost/Controller0.rtc:out.ctrl /localhost/Motor0.rtc:out.motor + +一つのファイルに三つのデータストリームを記録します。ストリームの名前は +``sensor`` と ``ctrl`` と ``motor`` です。 + +:: + + $ rtlog -f log.rtlog /localhost/Sensor0.rtc:in.motor + /localhost/Motor0.rtc:in.ctrl + +一つのログから二つのデータストリームを別々のポートに再生します。 + +:: + + $ rtlog -f log.rtlog -p /localhost/Controller0.rtc:in.sensor + /localhost/Controller0.rtc:in.motor + +一つのログから二つのデータストリームを同じポートに再生します。 + +:: + + $ rtlog -f log.rtlog -p /localhost/Sensor0.rtc:in.motor + /localhost/Controller0.rtc:in.motor + +ログから一つのデータストリームを複数のポートに再生します。 + +``--mod`` と ``--path`` の例は ``rtinject(1)`` を参照してください。 + +参照 +==== + + ``rtcat`` (1), + ``rtinject`` (1), + ``rtprint`` (1) + diff --git a/doc/rest/ja/rtls.txt b/doc/rest/ja/rtls.txt new file mode 100644 index 0000000..82a8523 --- /dev/null +++ b/doc/rest/ja/rtls.txt @@ -0,0 +1,106 @@ +==== +rtls +==== + +-------------------------------------- +ディレクトリのオブジェクトをリストする +-------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtls [options] [path] + +概要 +==== + +RTCツリーのディレクトリにあるオブジェクトをリストします。デフォルトは +現在のワーキングディレクトリをリストします。 + +ロング形式の表示では、以下の列も表示します。 + + - ステート + + - ポートの数 / 接続されたポートの数 + + - インポートの数 / 接続されたインポートの数 + + - アウトポートの数 / 接続されたアウトポートの数 + + - サービスポートの数 / 接続されたサービスポートの数 + + - 名前 + +オプション +========== + +-l + 詳細な情報を表示する + +-R, --recurse + 再帰的に表示する + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtls + +現在のワーキングディレクトリをリストします。 + +:: + + $ rtls / + +RTCツリーのルートディレクトリをリストします。このコマンドはネームサーバ +を表示します。 + +:: + + $ rtls /localhost + +``localhost`` というネームサーバに直接登録されているオブジェクトをリス +トします。 + +:: + + $ rtls -R /localhost + +``localhost`` というネームサーバのすべての登録されたオブジェクトをリスト +します。 + +:: + + $ rtls -l /localhost + +``localhost`` というネームサーバの登録されたオブジェクトの詳細な情報を +リストします。コンポーネントのステートなどを見ることが可能です。 + +:: + + $ rtls -lR /localhost + +すべての ``localhost`` に登録されたオブジェクトの詳細な情報をリストします。 + +:: + + $ watch -n 1 rtls -l + +(POSIXのみ)現在のワーキングディレクトリのコンポーネントのステートを +表示して、1秒ずつ表示されたデータをアップデートします。 + + +参照 +==== + + ``rtcat`` (1), + ``rtcwd`` (1), + ``rtpwd`` (1) + diff --git a/doc/rest/ja/rtmgr.txt b/doc/rest/ja/rtmgr.txt new file mode 100644 index 0000000..5b3cd15 --- /dev/null +++ b/doc/rest/ja/rtmgr.txt @@ -0,0 +1,92 @@ +===== +rtmgr +===== + +-------------------------------------- +マネジャーでRTコンポーネントを管理する +-------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtmgr [options] + +概要 +==== + +マネジャーの扱いによってコンポーネントと共有モジュールの管理をします。 +マネジャーにロードされた共有モジュールからコンポーネントをインスタンス +化します。 + +マネジャーのコンフィグレーションは ``rtconf(1)`` を使用してください。 +マネジャーの情報は ``rtcat(1)`` によって表示してください。 + +複数のコマンドを指定する場合、コマンドラインと同じ順番に実行されます。 + + +オプション +========== + +-c MOD_NAME, --create=MOD_NAME + ロードされたモジュールからコンポーネントのインスタンスを作る。プロパ + ティはモジュール名に追加することが可能。プロパティは「?」で始まる。 + +-d INSTANCE_NAME, --delete=INSTANCE_NAME + コンポーネントのインスタンスを終了して消す。 + +-l MOD_PATH, --load=MOD_PATH + マネジャーにモジュールをロードする。Initialisation関数を ``:`` で + 分かれて指定することが必要。 + +-u MOD_PATH_U, --unload=MOD_PATH_U + マネジャーからモジュールを消す。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtmgr /localhost/manager.mgr -l /usr/local/lib/mycomp.so:mycomp_init + +マネジャーに ``mycomp.so`` というモジュールをロードします。 + +:: + + $ rtmgr /localhost/manager.mgr -c mycomp + +``mycomp`` というモジュールからコンポーネントのインスタンスを作ります。 + +:: + + $ rtmgr /localhost/manager.mgr -d MyComp0 + +マネジャーに実行中の ``MyComp0`` というコンポーネントを終了して消します。 + +:: + + $ rtmgr /localhost/manager.mgr -u /usr/local/lib/mycomp.so + +マネジャーから ``mycomp.so`` というモジュールを消します。 + +:: + + $ rtmgr /localhost/manager.mgr -l /usr/local/lib/mycomp.so:mycomp_init + -c mycomp + +マネジャーに ``mycomp.so`` というモジュールをロードしてそしてコンポーネン +トのインスタンスを作ります。 + + +参照 +==== + + ``rtcat`` (1), + ``rtconf`` (1), + ``rtexit`` (1) + diff --git a/doc/rest/ja/rtprint.txt b/doc/rest/ja/rtprint.txt new file mode 100644 index 0000000..8a4e129 --- /dev/null +++ b/doc/rest/ja/rtprint.txt @@ -0,0 +1,105 @@ +======= +rtprint +======= + +---------------------------------------- +ポートからのデータをターミナルに表示する +---------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtprint [options] : [:...] + +概要 +==== + +複数のアウトポートが送るデータを標準出力に表示します。 + +デフォルトは最初の値のみを表示します。複数の値を表示すことや定期的に表 +示することも可能です。一回の実行ループで一つだけのポートにデータがあっ +た場合、一定の回数プリントする目的のためのプリントとしてカウントされま +す。 + +Pythonは表示できないデータを表示するためにフォーマッタ関数を使うことが +必要です。ユーザもこの関数を提供することは可能です。フォーマッタ関数は +一つの変数(表示するべきデータ)をもらいます:: + + def rawpy(data): + return data.__repr__() + +ログツールから目的のポートまでの接続はデフォルトのプロパティで作られま +す。 + + +オプション +========== + +-m MODULES, --mod=MODULES + Import する必要がある Python モジュール。値が必要としているモジュー + ルが自動的にロードされていない場合、このオプションで指定してください。 + モジュールとそのモジュールの ``__POA`` のモジュールも import します。 + +-n MAX, --number=MAX + 読み込む回数の制限。 + +-p PATHS, --path=PATHS + モジュールのサーチパス。Pythonの ``PYTHONPATH`` 変数に追加する。 + +-r RATE, --rate=RATE + 実行レート。 + +-t TIMEOUT, --timeout=TIMEOUT + 読み込む時間の制限。このオプションを使う場合、 ``--number`` を使うことは + できません。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out + +``ConsoleIn0.rtc`` の ``out`` ポートから最初の値を表示します。 + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out -n 5 + +``ConsoleIn0.rtc`` の ``out`` ポートから最初の5個の値を表示します。 + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out -t 5 + +``ConsoleIn0.rtc`` の ``out`` ポートからの値を5秒間表示します。 + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out -t 5 -r 10 + +``ConsoleIn0.rtc`` の ``out`` ポートからの値を5秒間、1秒で10回表示しま +す。 + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out#printers.my_formatter + +``ConsoleIn0.rtc`` の ``out`` ポートの最初の値を ``printers`` モジュールの +``my_formatter`` 関数に送って結果を表示します。 + +``--mod`` と ``--path`` の例はrtinject(1)を参照してください。 + +参照 +==== + + ``rtcat`` (1), + ``rtinject`` (1), + ``rtlog`` (1) + diff --git a/doc/rest/ja/rtpwd.txt b/doc/rest/ja/rtpwd.txt new file mode 100644 index 0000000..7f1bc2a --- /dev/null +++ b/doc/rest/ja/rtpwd.txt @@ -0,0 +1,29 @@ +===== +rtpwd +===== + +---------------------------- +現在のディレクトリを表示する +---------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtpwd + +概要 +==== + +現在のディレクトリを表示します。 + +.. include:: ../../common/ja/common_body.txt + + +参照 +==== + + ``rtcwd`` (1), + ``rtls`` (1) + diff --git a/doc/rest/ja/rtreset.txt b/doc/rest/ja/rtreset.txt new file mode 100644 index 0000000..4498a1a --- /dev/null +++ b/doc/rest/ja/rtreset.txt @@ -0,0 +1,58 @@ +======= +rtreset +======= + +---------------------------- +コンポーネントをリセットする +---------------------------- + +.. include: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtreset [options] [ ...] + +概要 +==== + +エラーステートにあるRTコンポーネントをリセットします。 + +オプション +========== + +-e EC_INDEX, --exec_context=EC_INDEX + このexecution contextの中のみでリセットする。ディフォルトは0。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtreset /localhost/local.host_cxt/ConsoleOut0.rtc + +``ConsoleOut0.rtc`` のすべてのECにリセットにする。 + +:: + + $ rtreset ConsoleOut0.rtc ConsoleIn0.rtc + +``ConsoleOut0.rtc`` と ``ConsoleIn0.rtc のすべてのECにリセットにする。 + +:: + + $ rtreset -e 2 /localhost/local.host_cxt/Motor0.rtc + +``Motor0.rtc`` を「2」というIDで示されるECのみにリセットにする。 + +参照 +==== + +``rtact`` (1), +``rtdeact`` (1), +``rtcat`` (1) + diff --git a/doc/rest/ja/rtresurrect.txt b/doc/rest/ja/rtresurrect.txt new file mode 100644 index 0000000..06da8ca --- /dev/null +++ b/doc/rest/ja/rtresurrect.txt @@ -0,0 +1,66 @@ +=========== +rtresurrect +=========== + +-------------------------------------------------- +RTSProfileファイルに保存されたRTシステムを復元する +-------------------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtresurrect [options] [RTSProfile file] + +概要 +==== + +RTSProfileファイルをロードして実行中のコンポーネントを使ってRTシステム +を復元します。コンポーネントの間の接続とコンポーネントのコンフィグレー +ションパラメータはRTSProfileのものがを反映されます。 +RTSProfileに「必要」と指定されておらず実行中ではないコンポーネントは +無視します。 + +ファイル名を指定しない場合、RTSProfileをstdinから読みます。 + +オプション +========== + +--dry-run + 復元するために何をするかを表示して終了する(実際には復元しない) + +-x, --xml + XMLフォーマットを使う + +-y, --yaml + YAMLフォーマットを使う + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtresurrect sys.rtsys + +``sys.rtsys`` というファイルに保存されたRTシステムを復元します。 + +:: + + $ rtresurrect sys.rtsys --dry-run + +``sys.rtsys`` というファイルに保存されたRTシステムを復元するために何を +するかを表示します。(実際には復元されません。) + +参照 +==== + + ``rtcheck`` (1), + ``rtcon`` (1), + ``rtconf`` (1), + ``rtstart`` (1) + diff --git a/doc/rest/ja/rtshell.txt b/doc/rest/ja/rtshell.txt new file mode 100644 index 0000000..441147f --- /dev/null +++ b/doc/rest/ja/rtshell.txt @@ -0,0 +1,210 @@ +======= +rtshell +======= + +-------------------------------------- +RTミドルウェア用のコマンドラインツール +-------------------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +概要 +==== + +rtshellはRTコンポーネント、マネージャ及び全RTシステムを管理するツール +を提供します。OpenRTM-aistとそれに準じているインタフェースを提供する +他のミドルウェアに対応しています。 + +コマンドの多くは、ネームサーバで動作しているコンポーネントとマネージャ +ーをファイルシステムのように扱えるようにしてあります。 +ディレクトリに入ったり、コンポーネントをcatのようにで読んだり、アクティブさせ +たり、ポートを接続させたりすることができます。ほかのコマンドはRTシステムを +管理するためのRTSProfileファイルに関連して使用されます。 + +rtshellのコマンドは、何らかの都合により RTSystemEditor が使うことができない +OpenRTM-aist のユーザ向きです。 +システムリソースが少ない場合、GUIがない場合(特にネットワークにも接続できな +い場合)、スクリプトを使いたい場合などに役に立ちます。コマンドラインを使用 +するのになじみがあるユーザにとってはrtshellは非常に便利です。 + +コマンド +======== + + rtact + RTコンポーネントをアクティブにする。 + + rtcat + RTコンポーネントのメタデータを表示する。 + + rtcheck + 起動中のRTシステムを保存されたRTSProfileと比べる。 + + rtcomp + コンポジットコンポーネントを作る。 + + rtcon + ポートを接続する。 + + rtconf + コンポーネントのコンフィグレーションを編集する。 + + rtcryo + 起動中のRTシステムをRTSProfileファイルに保存する。 + + rtcwd + 現在のワーキングダイレクトリを変更する。 + + rtdeact + コンポーネントをディアクティブにする。 + + rtdel + ネームサーバからオブジェクトを消す。 + + rtdis + ポートの接続を削除する。 + + rtdoc + RTコンポーネントのドキュメンテーションを表示する。 + + rtexit + RTコンポーネントを停止する。 + + rtfind + 起動中のRTコンポーネントやマネージャ等を探す。 + + rtinject + ポートにデータを送る。 + + rtlog + ポートが送るデータをログに保存して再生する。 + + rtls + ダイレクトリのオブジェクトをリストする。 + + rtmgr + マネジャーでRTコンポーネントを管理する。 + + rtprint + ポートが送るデータをターミナルに表示する。 + + rtpwd + 現在のワーキングダイレクトリを表示する。 + + rtreset + RTコンポーネントをリセットする。 + + rtresurrect + RTSProfileファイルに保存されたRTシステムを復元する。 + + rtstart + RTシステムを起動する。 + + rtstodot + 起動中のRTシステムをグラフで表示する。 + + rtstop + RTシステムを停止する。 + + rtteardown + RTシステムを削除する。 + + +RTCツリー +========= + +すべてのコマンドはRTCツリー上で起動します。RTCツリーとは、ネームサーバ上 +のコンテキスト、コンポーネント、マネージャ等をファイルシステムに見立てて +扱うことができる仕組みです。通常のファイルシステムと同じように扱うことが +できます。 + +ネームサーバはルートディレクトリ( ``/`` )からのサブディレクトリとして扱 +われます。その下にはファイルとサブディレクトリが存在します。サブディレク +トリはネームサーバ上のネーミングコンテクストに対応します。ファイルはコン +ポーネントとマネージャーに対応します。 + +ツリーを構築するためのネームサーバを与える方法は2通りあります。一つはコマ +ンドに渡したネームサーバへのパスです。これは現在のツリーの作業ディレクト +リに追加され、最初の要素はネームサーバとして扱われます。 + +もう一つは ``RTCTREE_NAMESERVERS`` 環境変数です。ネームサーバアドレスをセミ +コロンで区切り、リストを渡すこともできます。 + + +シェルコンプリーション +====================== + +Bash(バッシュ)シェルの使う方はrtshellに含めているコンプリーションスク +リプトによってrtshellのコマンドをもっと使いやすくできます。スクリプトは +``${prefix}/share/rtshell`` にインストールされます。以下のコマンドでロー +ドしてください:: + + $ source bash_completion + +以上のコマンドを ``~/.bashrc`` というファイルに保存したら自動的にロードさ +れます。 + +コンプリーションの例:: + + $ rtcwd [TAB] + $ rtcwd localhost/ + $ rtcwd localhost/[TAB] + $ rtcwd localhost/kenroke.host_cxt/ + $ rtcwd localhost/kenroke.host_cxt/[TAB][TAB] + ConsoleIn0.rtc ConfigSample0.rtc manager.mgr Sensor0.rtc + $ rtcwd localhost/kenroke.host_cxt/[ENTER] + $ rtconf ConfigSample0.rtc set [TAB] + double_param0 double_param1 int_param0 int_param1 str_param0 + str_param1 vector_param0 + $ rtcon Sensor0.rtc:[TAB] + in out + + +システムの要件 +============== + +rtshellは **rtctree 3.0** が必要です。インストールされていない場合はコマン +ドは起動しません。 + +RTSProfileを使うコマンドは **rtsprofile 2.0** が必要です。インストールされ +ていない場合はこのコマンドは起動しません。 + +rtshellは **Python 2.6** が必要です。Python 3.0はまだテストされていないの +で動かない可能性はあります。 + +``rtinject`` 、 ``rtlog`` 及び ``rtprint`` は **OpenRTM-python** が必要です。 + +Ubuntu 9.04より古いUbuntuのバージョンの使う方は正しいPythonを手動でイン +ストールする必要です。新しいUbuntuにアップグレードすることをお考えくださ +い。10.04はLTSを提供します。 + +.. include:: ../../common/ja/common_body.txt + +参照 +==== + + ``rtact`` (1), + ``rtcat`` (1), + ``rtcheck`` (1), + ``rtcomp`` (1), + ``rtcon`` (1), + ``rtconf`` (1), + ``rtcryo`` (1), + ``rtcwd`` (1), + ``rtdeact`` (1), + ``rtdel`` (1), + ``rtdis`` (1), + ``rtexit`` (1), + ``rtfind`` (1), + ``rtinject`` (1), + ``rtlog`` (1), + ``rtls`` (1), + ``rtmgr`` (1), + ``rtprint`` (1), + ``rtpwd`` (1), + ``rtreset`` (1), + ``rtresurrect`` (1), + ``rtstart`` (1), + ``rtstodot`` (1), + ``rtstop`` (1), + ``rtteardown`` (1) + diff --git a/doc/rest/ja/rtstart.txt b/doc/rest/ja/rtstart.txt new file mode 100644 index 0000000..2a32d8e --- /dev/null +++ b/doc/rest/ja/rtstart.txt @@ -0,0 +1,69 @@ +======= +rtstart +======= + +-------------------- +RTシステムを起動する +-------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtstart [options] [RTSProfile file] + +概要 +==== + +すべてのコンポーネントを activate することによってRTSProfileに保存され +たRTシステムを起動します。コンポーネントはRTSProfileが指定された順番に +activate されます。RTSProfileに「必要」と +指定されておらず実行中ではないコンポーネントは無視します。 + +ファイル名を指定しない場合、RTSProfileをstdinから読みます。 + +オプション +========== + +--dry-run + 実行する内容を表示する(実際には起動は行われない) + +-x, --xml + XMLフォーマットを使う + +-y, --yaml + YAMLフォーマットを使う + +.. include:: ../../common/ja/common_opts.txt + +ステート変更のプラン +==================== + +.. include:: ../../common/ja/start_stop_plans.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtstart sys.rtsys + +``sys.rtsys`` というファイルに保存されたRTシステムを起動します。 + +:: + + $ rtstart sys.rtsys --dry-run + +``sys.rtsys`` というファイルに保存されたRTシステムを起動するために何を +するかを表示します。(実際には起動されません。) + +参照 +==== + + ``rtcheck`` (1), + ``rtresurrect`` (1), + ``rtstop`` (1) + diff --git a/doc/rest/ja/rtstodot.txt b/doc/rest/ja/rtstodot.txt new file mode 100644 index 0000000..ed921ec --- /dev/null +++ b/doc/rest/ja/rtstodot.txt @@ -0,0 +1,61 @@ +======== +rtstodot +======== + +------------------------------------ +起動中のRTシステムをグラフで表示する +------------------------------------ + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtstodot [options] [RTSProfile file] + +概要 +==== + +GraphvizのdotフォーマットでRTシステムをグラフとして表示します。 +RTSProfileが指定されていない場合、stdinから読みます。 + +オプション +========== + +-x, --xml + XMLフォーマットを使う + +-y, --yaml + YAMLフォーマットを使う + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtstodot sys.rtsys | dot -T xlib + +``sys.rtsys`` というファイルに保存されたRTシステムを表示します。 + +:: + + $ rtstodot sys.rtsys | dot -T eps > sys.eps + +``sys.rtsys`` というファイルに保存されたRTシステムを表示してEncapsulated +PostScriptフォーマットに保存します。 + +:: + + $ rtcryo | rtstodot | dot -T xlib + +現在実行中のRTシステムを表示します。 + +参照 +==== + + ``rtcryo`` (1) + diff --git a/doc/rest/ja/rtstop.txt b/doc/rest/ja/rtstop.txt new file mode 100644 index 0000000..3d409bc --- /dev/null +++ b/doc/rest/ja/rtstop.txt @@ -0,0 +1,70 @@ +====== +rtstop +====== + +-------------------- +RTシステムを停止する +-------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtstop [options] [RTSProfile file] + +概要 +==== + +すべてのコンポーネントを deactivate すること似よってRTSProfileに保存され +たRTシステムを停止します。コンポーネントはRTSProfileが指定された順番に +deactivate されます。RTSProfileに「必要」と +指定されておらず実行中ではないコンポーネントは無視します。 + +ファイル名を指定しない場合、RTSProfileをstdinから読みます。 + +オプション +========== + +--dry-run + 実行する内容を表示する(実際には停止は行われない) + +-x, --xml + XMLフォーマットを使う + +-y, --yaml + YAMLフォーマットを使う + +.. include:: ../../common/ja/common_opts.txt + +ステート変更のプラン +==================== + +.. include:: ../../common/ja/start_stop_plans.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtstop sys.rtsys + +``sys.rtsys`` というファイルに保存されたRTシステムを停止します。 + +:: + + $ rtstop sys.rtsys --dry-run + +``sys.rtsys`` というファイルに保存されたRTシステムを停止するために何を +するかを表示します。(実際には、停止は行われません。) + + +参照 +==== + + ``rtcheck`` (1), + ``rtresurrect`` (1), + ``rtstart`` (1) + diff --git a/doc/rest/ja/rtteardown.txt b/doc/rest/ja/rtteardown.txt new file mode 100644 index 0000000..04a6836 --- /dev/null +++ b/doc/rest/ja/rtteardown.txt @@ -0,0 +1,61 @@ +========== +rtteardown +========== + +-------------------------- +RTシステムの接続を削除する +-------------------------- + +.. include:: ../../common/ja/docinfo_block.txt + +書式 +==== + +rtteardown [options] [RTSProfile file] + +概要 +==== + +RTSProfileに保存されたRTシステムのすべての接続を削除します。 + + +ファイル名を指定しない場合、RTSProfileをstdinから読みます。 + +オプション +========== + +--dry-run + 実行する内容を表示する(実際には削除は行われない) + +-x, --xml + XMLフォーマットを使う + +-y, --yaml + YAMLフォーマットを使う + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtteardown sys.rtsys + +``sys.rtsys`` というファイルに保存されたRTシステムを削除します。 + +:: + + $ rtteardown sys.rtsys --dry-run + +``sys.rtsys`` というファイルに保存されたRTシステムを削除ために何を +するかを表示します。(実際には、削除は行われません。) + +参照 +==== + + ``rtcheck`` (1), + ``rtresurrect`` (1) + diff --git a/doc/rest/ja/rtvlog.txt b/doc/rest/ja/rtvlog.txt new file mode 100644 index 0000000..d445ca8 --- /dev/null +++ b/doc/rest/ja/rtvlog.txt @@ -0,0 +1,67 @@ +====== +rtexit +====== + +-------------------------------- +RTコンポーネントのログを表示する +-------------------------------- + +.. include:: ../../common/docinfo_block.txt + +書式 +==== + +rtvlog [options] [path 2 ...] + +概要 +==== + +個別のRTコンポーネントのログを取得して表示します。RTコンポーネントにはSDOのLoggerイン +ターフェースを対応することが必要です。ログはターミナルに出力します。 + +オプション +======= + +-f FILTER, --filter=FILTER + ログメッセージを送信するロガーオブジェクトのフィルターをします。複数 + 回は可能です。 + +-l LEVEL, --level=LEVEL + 受信するログメッセージのレベルを設定します。指定されたレベルと同等あ + るいはそれより重要な情報が受信されます。ERROR, WARN, INFO, NORMAL, + DEBUG, TRACE, VERBOSE またはPARANOID のうち一つを指定することが可能 + です。 + +.. include:: ../../common/ja/common_opts.txt + +.. include:: ../../common/ja/common_body.txt + +例 +== + +:: + + $ rtvlog /localhost/ConsoleOut0.rtc + +``ConsoleOut0.rtc`` コンポーネントが送信するログメッセージを表示します。 + +:: + + $ rtvlog ConsoleOut0.rtc ConsoleIn0.rtc + +``ConsoleOut0.rtc`` コンポーネントと ``ConsoleIn0.rtc`` コンポーネントが +送信するログメッセージを表示します。 + +:: + + $ rtvlog ConsoleOut0.rtc -f DATAPORT -l DEBUG + +``DEBUG`` 以下の``ConsoleOut0.rtc`` コンポーネントのデータポートが送信 +するログメッセージを表示します。 + + +参照 +==== + + ``rtshell`` (1) + diff --git a/doc/rest/rtact.txt b/doc/rest/rtact.txt new file mode 100644 index 0000000..fbe7a6c --- /dev/null +++ b/doc/rest/rtact.txt @@ -0,0 +1,61 @@ +===== +rtact +===== + +------------------- +activate components +------------------- + +.. include: ../common/docinfo_block.txt + +Synopsis +======== + +rtact [options] [ ...] + +Description +=========== + +Activates the specified RT-Components, provided they are in the +``inactive`` state. + +Options +======= + +-e EC_INDEX, --exec_context=EC_INDEX + Index of the execution context to change state in. The default is 0. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtact /localhost/local.host_cxt/ConsoleOut0.rtc + +Activate ``ConsoleOut0.rtc`` in all owned and participating execution +contexts. + +:: + + $ rtact ConsoleOut0.rtc ConsoleIn0.rtc + +Activate ``ConsoleOut0.rtc`` and ``ConsoleIn0.rtc`` in all owned and +participating execution contexts. + +:: + + $ rtact -e 2 /localhost/local.host_cxt/Motor0.rtc + +Activate ``Motor0.rtc`` in only the execution context with ID 2. + +See Also +======== + +``rtdeact`` (1), +``rtreset`` (1), +``rtcat`` (1) + diff --git a/doc/rest/rtcat.txt b/doc/rest/rtcat.txt new file mode 100644 index 0000000..a197ac6 --- /dev/null +++ b/doc/rest/rtcat.txt @@ -0,0 +1,78 @@ +===== +rtcat +===== + +---------------------------------------- +view component information and meta-data +---------------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtcat [options] + +Description +=========== + +Equivalent to the POSIX ``cat`` command. Reads and displays the +meta-information of RT-Components, ports and managers, as well as +displaying the information obtained from the introspection interfaces of +these objects. + +Options +======= + +-l + Show more information. Specify multiple times for even more + information. [Default:: ``False``] + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc + +Show the basic information about the ``Motor0.rtc`` component. + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc -l + +Show more information about the ``Motor0.rtc`` component, including port +and execution context details. + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc -ll + +Show even more information about the ``Motor0.rtc`` component, including +current connections on each port. + +:: + + $ rtcat /localhost/local.host_cxt/Motor0.rtc:in -l + +Show only the information about the port named ``in`` on the +``Motor0.rtc`` component. + +:: + + $ rtcat /localhost/local.host_cxt/manager.mgr + +Show the basic information about the ``manager.mgr`` manager. + +See Also +======== + +``rtcon`` (1), +``rtconf`` (1), +``rtprint`` (1), +``rtstodot`` (1) + diff --git a/doc/rest/rtcheck.txt b/doc/rest/rtcheck.txt new file mode 100644 index 0000000..5f112c6 --- /dev/null +++ b/doc/rest/rtcheck.txt @@ -0,0 +1,75 @@ +======= +rtcheck +======= + +--------------------------- +check RT-System consistency +--------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtcheck [options] + +Description +=========== + +Checks the consistency of a running system against an RTSProfile. Identifies +errors including missing connections and components in the incorrect state. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +--dry-run + Print what will be done but don't actually do anything. + +-s STATE, --state=STATE + The expected state of the RT Components in the system. The default is + ``Active``. + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtcheck sys.rtsys + +Check if the system specified in the RTSProfile stored in ``sys.rtsys`` +is correctly set up in the current running components, with all +components in the ``active`` state. + +:: + + $ rtcheck sys.rtsys -s Inactive + +The same as above, but expect the components to be in the ``inactive`` +state. + +:: + + $ rtcheck sys.rtsys --dry-run + +Display the actions that will be performed to check the system state. + +See Also +======== + +``rtcat`` (1), +``rtresurrect`` (1), +``rtstart`` (1) + diff --git a/doc/rest/rtcomp.txt b/doc/rest/rtcomp.txt new file mode 100644 index 0000000..33378a9 --- /dev/null +++ b/doc/rest/rtcomp.txt @@ -0,0 +1,116 @@ +====== +rtcomp +====== + +--------------------------- +manage composite components +--------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtcomp [options] + +Description +=========== + +Composes multiple components into a single composite component, exposing +a selection of their ports externally. A new composition can be created +or an existing composition edited. New members can be added to and +members removed from existing compositions, and the exported ports list +can be changed. The type of composition to create can be specified. + +The required option is either the path to an existing composition to +edit, or the path to a manager to create the composition in. If a +manager is specified, a name for the new composition can be specified, +separated from the manager path by a colon. If a name is not specified, +a default name will be chosen. See the Examples_ section for examples. + +When specifying components to add or remove, a list of ports to export +or hide can be specified after the component path, separated from the +path by a colon. The ports in the list should be comma-separated. See +the Examples_ section for examples. + +Options +======= + +-a ADD, --add=ADD + A component to include in the composition. Specify a comma-separated + list of ports to export after the component name, separated by a + colon. + +-o OPTIONS, --options=OPTIONS + Extra options to pass to the component on creation. + +-r REMOVE, --remove=REMOVE + A component or ports to remove from the composition. + +-t TYPE, --type=TYPE + Type of composite component to create. [Default: + PeriodicECSharedComposite] + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtcomp /localhost/manager.mgr:MotorUnit -a + /localhost/Motor0.rtc:out -a /localhost/Controller0.rtc:in,out + +Create a composite component using the ``Motor0.rtc`` and +``Controller0.rtc`` components, exposing the ``in`` and ``out`` ports of +``Controller0.rtc`` and the ``out`` port of ``Motor0.rtc``. The +component's instance name will be ``MotorUnit``. + +:: + + $ rtcomp /localhost/MotorUnit.rtc -a /localhost/Sensor0.rtc:out + +Edit the existing ``MotorUnit.rtc`` composite component, adding the +``Sensor0.rtc`` component as a new user and exporting its ``out`` port. + +:: + + $ rtcomp /localhost/MotorUnit.rtc -a /localhost/Sensor0.rtc:in + +Edit the existing ``MotorUnit.rtc``, which already contains +``Sensor0.rtc`` as a member, to export the ``in`` port of +``Sensor0.rtc``. + +:: + + $ rtcomp /localhost/MotorUnit.rtc -r /localhost/Sensor0.rtc:out + +Edit the existing ``MotorUnit.rtc``, which already contains +``Sensor0.rtc`` as a member, to hide the ``out`` port of +``Sensor0.rtc``. + +:: + + $ rtcomp /localhost/MotorUnit.rtc -r /localhost/Controller0.rtc:in,out + +Edit the existing ``MotorUnit.rtc``, which already contains +``Controller0.rtc`` as a member, to hide the ``in`` and ``out`` ports of +``Controller0.rtc``. + +:: + + $ rtcomp /localhost/MotorUnit.rtc -r /localhost/Controller0.rtc -r + /localhost/Motor0.rtc + +Edit the existing ``MotorUnit.rtc``, which already contains +``Controller0.rtc`` and ``Motor0.rtc`` as a members, to remove them from +the composition. + + +See Also +======== + +``rtmgr`` (1) + diff --git a/doc/rest/rtcon.txt b/doc/rest/rtcon.txt new file mode 100644 index 0000000..a272da6 --- /dev/null +++ b/doc/rest/rtcon.txt @@ -0,0 +1,114 @@ +===== +rtcon +===== + +------------- +connect ports +------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtcon [options] [ ...] + +Description +=========== + +Connects two or more data or service ports together. + +For data ports, the valid properties include:: + + - dataport.data_type + - dataport.dataflow_type + - dataport.interface_type + - dateport.subscription_type + +For service ports, the valid properties include:: + + - port.port_type + +When connecting data ports, the properties below may also be used. Some +properties depend on other properties, and may not have an effect if +their dependencies are not set appropriately. + +========================================= ============================ ========== +Property Value Dependency +========================================= ============================ ========== +dataport.inport.buffer.length +dataport.inport.buffer.read.timeout in seconds +dataport.inport.buffer.read.empty_policy readback, do_nothing, block +dataport.inport.buffer.write.timeout in seconds +dataport.inport.buffer.write.full_policy overwrite, do_nothing, block +dataport.outport.buffer.length +dataport.outport.buffer.read.timeout in seconds +dataport.outport.buffer.read.empty_policy readback, do_nothing, block +dataport.outport.buffer.write.timeout in seconds +dataport.outport.buffer.write.full_policy overwrite, do_nothing, block +dataport.subscription_type flush, new, periodic dataport.dataflow_type is push +dataport.publisher.push_policy all, fifo, skip, new dataport.subscription_type is not flush +dataport.push_rate in Hz dataport.subscription_type is periodic +dataport.publisher.skip_count dataport.publisher.push_policy is skip +========================================= ============================ ========== + +Other properties may also be valid, depending on your OpenRTM +implementation. + +Options +======= + +-i ID, --id=ID + ID of the connection. + +-n NAME, --name=NAME + Name of the connection. + +-p PROPERTIES, --property=PROPERTIES + Connection properties. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtcon /localhost/ConsoleIn0.rtc:out /localhost/ConsoleOut0.rtc:in + +Connect the ``out`` port of ``ConsoleIn0.rtc`` to the ``in`` port of +``ConsoleOut0.rtc`` using the default connection properties. + +:: + + $ rtcon Motor0.rtc:out Sensor0.rtc:in --property + dataport.dataflow_type=pull + +Connect the ``out`` port of ``Motor0.rtc`` to the ``in`` port of +``Sensor0.rtc`` using a ``pull`` connection. + +:: + + $ rtcon Motor0.rtc:out Sensor0.rtc:in -i con1 -n motor_data + +Connect the ``out`` port of ``Motor0.rtc`` to the ``in`` port of +``Sensor0.rtc``, giving the connection the name ``motor_data`` and the +ID ``con1``. + +:: + + $ rtcon ConsoleIn0.rtc:out ConsoleOut0.rtc:in ConsoleOut1.rtc:in + +Connect the ``out`` port of ``ConsoleIn0.rtc`` to the ``in`` port of +``ConsoleOut0.rtc`` and the ``in`` port of ``ConsoleOut1.rtc`` using the +default connection properties. + + +See Also +======== + + ``rtcat`` (1), + ``rtdis`` (1) + diff --git a/doc/rest/rtconf.txt b/doc/rest/rtconf.txt new file mode 100644 index 0000000..232d1cc --- /dev/null +++ b/doc/rest/rtconf.txt @@ -0,0 +1,173 @@ +====== +rtconf +====== + +------------------------------- +manage configuration parameters +------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtconf [options] [command] [args] + +Description +=========== + +Display and edit configuration parameters and sets. + +A command should be one of: + + - list + - set + - get + - act + +If no command is specified, the list command will be executed. + +:: + + list + +The ``list`` command displays the configuration sets and parameters. It +takes no arguments. By default, hidden sets (sets who's name is +surrounded by ``__``) are not displayed. + +:: + + set + +The ``set`` command changes the value of a configuration parameter in +one set. It requires a parameter name and a value as arguments. If no +configuration set is specified (using ``--set``), the parameter is +changed in the currently active configuration set. + +:: + + get + +The ``get`` command prints the value of a configuration parameter in one +configuration set. It requires a parameter name as its argument. If no +configuration set is specified (using ``--set``), the parameter value +from the currently activate configuration set is retrieved. + +:: + + act + +The act command requires no arguments, but a configuration set must be +specified using ``--set``. It activates that set. + +Options +======= + +-a, --all + Do not ignore hidden sets. This option must be specified to work with + hidden configuration sets. + +-l + Show more information. + +-s SET_NAME, --set=SET_NAME + Choose the configuration set to work with. If not specified, the + current active set is used. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtconf /localhost/ConfigSample0.rtc list + +default* + +mode0 + +mode1 + +Display the configuration sets in the ``ConfigSample0.rtc`` component. + +:: + + $ rtconf /localhost/ConfigSample0.rtc -l list + -default* + double_param0 0.99 + double_param1 -0.99 + ... + +Display the configuration sets and their parameters in the +``ConfigSample0.rtc`` component. + +:: + + $ rtconf /localhost/ConfigSample0.rtc -a list + +__constraints__ + +__widget__ + +default* + +mode0 + +mode1 + +Display the configuration sets in the ``ConfigSample0.rtc`` component, +including hidden sets. + +:: + + $ rtconf /localhost/ConfigSample0.rtc -l -s default list + -__constraints__ + double_param0 0<=x<=100 + double_param1 + ... + +Display the parameters of the ``default`` configuration set in the +``ConfigSample0.rtc`` component. + +:: + + $ rtconf /localhost/ConfigSample0.rtc set int_param0 42 + +Change the value of the ``int_param0`` parameter to 42 in the +currently-active configuration set. + +:: + + $ rtconf /localhost/ConfigSample0.rtc -s mode0 set int_param0 42 + +Change the value of the ``int_param0`` parameter to 42 in the ``mode0`` +set. + +:: + + $ rtconf /localhost/ConfigSample0.rtc get int_param0 + 0 + +Get the value of the ``int_param0`` parameter in the currently-active +configuration set. + +:: + + $ rtconf /localhost/ConfigSample0.rtc -s mode0 get int_param0 + 12345 + +Get the value of the ``int_param0`` parameter in the ``mode0`` +configuration set. + +:: + + $ rtconf /localhost/ConfigSample0.rtc act mode1 + +Activate the ``mode1`` configuration set. + +:: + + $ rtconf /localhost/ConfigSample0.rtc -a act __widget__ + +Activate the ``__widget__`` configuration set. + +See Also +======== + + ``rtcat`` (1) + diff --git a/doc/rest/rtcryo.txt b/doc/rest/rtcryo.txt new file mode 100644 index 0000000..3ff3fea --- /dev/null +++ b/doc/rest/rtcryo.txt @@ -0,0 +1,95 @@ +====== +rtcryo +====== + +------------------------------ +save RT-Systems to RTSProfiles +------------------------------ + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtcryo [options] [name servers] + +Description +=========== + +Analyses a running RT-System and saves it to an RTSProfile. The +connections between the components and their current configuration +parameters are saved. Only components with connections are considered to +be a part of the RT-System. + +If no filename is given, the RTSProfile is written to standard output. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +-a ABSTRACT, --abstract=ABSTRACT + Brief description of the RT-System. + +-n SYSNAME, --system-name=SYSNAME + Name of the RT-System. The default is ``RTSystem``. + +-o OUTPUT, --output=OUTPUT + Output file name. If none is specified, stdout is used. + +-v VERSION, --system-version=VERSION + Version of the RT-System. The default is ``0``. + +-e VENDOR, --vendor=VENDOR + Vendor of the RT-System. + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtcryo + +Save the components that are part of the RT-System from all known name +servers, and print the RTSProfile to stdout. + +:: + + $ rtcryo -o sys.rtsys + +Save the components that are part of the RT-System from all known name +servers, and save the RTSProfile to the file ``sys.rtsys``. + +:: + + $ rtcryo localhost + +Save the components that are part of the RT-System from only the +``localhost`` name server to the RTSProfile. + +:: + + $ rtcryo -n 'mysystem' -v 1.0 + +Set the name of the system in the RTSProfile to ``mysystem`` and the +RT-System version to ``1.0``. + +See Also +======== + + ``rtcheck`` (1), + ``rtcon`` (1), + ``rtconf`` (1), + ``rtstart`` (1) + diff --git a/doc/rest/rtcwd.txt b/doc/rest/rtcwd.txt new file mode 100644 index 0000000..26ab5dc --- /dev/null +++ b/doc/rest/rtcwd.txt @@ -0,0 +1,61 @@ +===== +rtcwd +===== + +------------------------------------ +change the current working directory +------------------------------------ + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtcwd [path] + +Description +=========== + +Changes the current working directory in the RTC Tree. + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtcwd + +Change to the root directory. + +:: + + $ rtcwd / + +Change to the root directory. + +:: + + $ rtcwd /localhost/local.host_cxt + +Change to the ``/localhost/local.host_cxt`` directory. + +:: + + $ rtcwd .. + +Change to the parent directory. + +:: + + $ rtcwd ../.. + +Change to the grandparent directory. + +See Also +======== + + ``rtls`` (1), + ``rtpwd`` (1) + diff --git a/doc/rest/rtdeact.txt b/doc/rest/rtdeact.txt new file mode 100644 index 0000000..483da08 --- /dev/null +++ b/doc/rest/rtdeact.txt @@ -0,0 +1,61 @@ +======= +rtdeact +======= + +--------------------- +deactivate components +--------------------- + +.. include: ../common/docinfo_block.txt + +Synopsis +======== + +rtdeact [options] [ ...] + +Description +=========== + +Deactivates the specified RT-Components, provided they are in the +``active`` state. + +Options +======= + +-e EC_INDEX, --exec_context=EC_INDEX + Index of the execution context to change state in. The default is 0. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtdeact /localhost/local.host_cxt/ConsoleOut0.rtc + +Deactivate ``ConsoleOut0.rtc`` in all owned and participating execution +contexts. + +:: + + $ rtdeact ConsoleOut0.rtc ConsoleIn0.rtc + +Deactivate ``ConsoleOut0.rtc`` and ``ConsoleIn0.rtc`` in all owned and +participating execution contexts. + +:: + + $ rtdeact -e 2 /localhost/local.host_cxt/Motor0.rtc + +Deactivate ``Motor0.rtc`` in only the execution context with ID 2. + +See Also +======== + +``rtact`` (1), +``rtreset`` (1), +``rtcat`` (1) + diff --git a/doc/rest/rtdel.txt b/doc/rest/rtdel.txt new file mode 100644 index 0000000..04cff6c --- /dev/null +++ b/doc/rest/rtdel.txt @@ -0,0 +1,75 @@ +===== +rtdel +===== + +-------------------------- +delete name server entries +-------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtdel [options] + +Description +=========== + +Deletes an object's registration from a name server. This command will +not shut down the object itself. If another reference to the object does +not exist, it will no longer be accessible. Care must be taken when +deleting naming contexts and managers not to unlink a large section of +the tree, as you will not be able to get it back. + +This command is particularly useful to remove zombie registrations. It +can mass-remove all known zombies in a single pass. + +Options +======= + +-z, --zombies + Delete only zombies. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtdel /localhost/Motor0.rtc + +Delete the ``Motor0.rtc`` component from the ``localhost`` name server. +The component will not be shut down. + +:: + + $ rtdel -z /localhost/Motor0.rtc + +Delete the ``Motor0.rtc`` component from the ``localhost`` name server, +but only if it is a zombie. + +:: + + $ rtdel /localhost/local.host_cxt + +Delete the ``local.host_cxt`` naming context from the ``localhost`` name +server. Any components and managers registered below the context will +become inaccessible. + +:: + + $ rtdel -z + +Delete all known zombies from all known name servers. + + +See Also +======== + + ``rtls`` (1), + ``rtmgr`` (1) + diff --git a/doc/rest/rtdis.txt b/doc/rest/rtdis.txt new file mode 100644 index 0000000..3b3bc2a --- /dev/null +++ b/doc/rest/rtdis.txt @@ -0,0 +1,75 @@ +===== +rtdis +===== + +---------------- +disconnect ports +---------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtdis [options] [ ...] + +Description +=========== + +Removes connections from between ports. A single connection can be +removed, or all connections from a single port or all of a component's +ports. + +Options +======= + +-i ID, --id=ID + ID of the connection. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtdis /localhost/ConsoleIn0.rtc:out /localhost/ConsoleOut0.rtc:in + +Remove all connections involving the ``out`` port of ``ConsoleIn0.rtc`` +and the ``in`` port of ``ConsoleOut0.rtc``. + +:: + + $ rtdis /localhost/ConsoleIn0.rtc:out + +Remove all connections connected to the ``out`` port of +``ConsoleIn0.rtc``. + +:: + + $ rtdis /localhost/ConsoleIn0.rtc + +Remove all connections connected to all ports of ``ConsoleIn0.rtc``. + +:: + + $ rtdis -i con1 /localhost/ConsoleIn0.rtc:out + +Remove the connection connected to the ``out`` port of +``ConsoleIn0.rtc`` that has the ID ``con1``. + +:: + + $ rtdis -i con1 /localhost/ConsoleIn0.rtc + +Remove the connection connected to any port of ``ConsoleIn0.rtc`` that +has the ID ``con1``. + +See Also +======== + + ``rtcat`` (1), + ``rtcon`` (1) + diff --git a/doc/rest/rtdoc.txt b/doc/rest/rtdoc.txt new file mode 100644 index 0000000..8dc4c3e --- /dev/null +++ b/doc/rest/rtdoc.txt @@ -0,0 +1,171 @@ +===== +rtdoc +===== + +-------------------------------- +print RT-Component documentation +-------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtdoc [options] + +Description +=========== + +Print the documentation for an RT-Component. + +Some RT-Components contain documentation internally, stored in hidden +configuration sets. This tool prints that documentation in several +convenient formats, including reStructuredText, HTML and LaTeX (suitable +for compiling to PDF). + +Options +======= + +-f FORMAT, --format=FORMAT + Output format (one of ``rst``, ``html`` or ``latex``). + +-g, --graph + Draw the component graph. + +.. include:: ../common/common_opts.txt + +RT-Component documentation +========================== + +To be compatible with this tool, an RT-Component must store its +documentation in a configuration set called ``__doc__``. Any parameters +in this set that are *not* hidden are added to the documentation as +sections. + +The common sections are: + + intro + An introduction to the component, giving a brief description of its + purpose. (Title: ``Introduction``.) + + reqs + Pre-requisites for using the component, such as other software that + must be installed. (Title: ``Pre-requisites``.) + + install + How to install the component. (Title: ``Installation``.) + + usage + How to launch and use the component. (Title: ``Usage``.) + + misc + Any other information important to using the component. (Title: + ``Miscellaneous``.) + + changelog + A description of changes to the component since the previous + versions. (Title: ``Changelog``.) + +In addition, a ``ports`` section and a ``config`` section are +automatically created if the component has any ports or any +configuration parameters in its ``default`` configuration set. Any other +sections present in the ``__doc__`` set will also be added to the +documentation. + +You can also set three parameters to add extra information to the +documentation preamble: + + __license__ + The license of the component, such as ``GPL`` or ``BSD``. + + __contact__ + Contact information, such as the author's email address. + + __url__ + The component's home page. + +These parameters can be set either in the component source or in a +configuration file loaded when the component is launched. Because +in-source documentation increases the size of the component binary and +memory requirements, it is recommended that the documentation be set in +a configuration file, with the possible exception of brief contact and +usage information. + +For example, to set them in the source, use something similar to the +following:: + + 'conf.__doc__.__license__', 'LGPL', + 'conf.__doc__.__contact__', 'a@example.com', + 'conf.__doc__.__url__', 'http://www.openrtm.org', + 'conf.__doc__.intro', 'This is the introduction.', + 'conf.__doc__.reqs', 'This component requires nothing.', + 'conf.__doc__.install', 'Type "make install"', + 'conf.__doc__.usage', 'Run comp_standalone.', + 'conf.__doc__.misc', 'Extra information.', + 'conf.__doc__.changelog', 'No changes.', + 'conf.__doc__.Another', 'A non-standard section.', + +By default, the sections are included in the following order: + + intro, reqs, usage, ports, config, misc, changelog, [other sections] + +This can be changed by setting the ``__order__`` parameter in the +``__doc__`` set. It must be set to a comma-separated list of parameter +names, where each parameter name is a section in the documentation. For +example:: + + 'conf.__doc__.__order__', 'intro,ports,config,reqs,Another' + +Any sections not mentioned in this parameter are added after the +specified sections. The order in which they are added is not defined. + +To document ports, add a ``description`` property to the port. For +example:: + + self._inport.addProperty('description', 'This port receives stuff.') + +To document configuration parameters, set the parameter in the +``__description__`` set. For example:: + + 'conf.default.param', '0', + 'conf.__description__.param', 'A test parameter.', + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc + +Print the ``ConsoleOut0.rtc`` component's documentation to stdout. + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc > doc.html + +Print the ``ConsoleOut0.rtc`` component's documentation to the file +``doc.html``. + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc -f rst + +Print the ``ConsoleOut0.rtc`` component's documentation in +reStructuredText format. + +:: + + $ rtdoc /localhost/ConsoleOut0.rtc -f latex > doc.tex && + rubber -d doc.tex + +Make a PDF of ``ConsoleOut0.rtc``'s documentation, using the ``rubber`` +tool to compile the LaTeX file. + +See Also +======== + + ``rtconf`` (1), + ``rubber`` (1) + diff --git a/doc/rest/rtexit.txt b/doc/rest/rtexit.txt new file mode 100644 index 0000000..046b737 --- /dev/null +++ b/doc/rest/rtexit.txt @@ -0,0 +1,43 @@ +====== +rtexit +====== + +----------------------- +shut down RT-Components +----------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtexit [options] + +Description +=========== + +Tell a running RT-Component to exit. The component will execute its +shutdown methods, including the relevant callbacks, clean up its +resources, and exit. + +Options +======= + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtexit /localhost/ConsoleOut0.rtc + +Tell the ``ConsoleOut0.rtc`` component to exit. + +See Also +======== + + ``rtdel`` (1) + diff --git a/doc/rest/rtfind.txt b/doc/rest/rtfind.txt new file mode 100644 index 0000000..bfa57ea --- /dev/null +++ b/doc/rest/rtfind.txt @@ -0,0 +1,88 @@ +====== +rtfind +====== + +-------------------- +search the RTC Tree +-------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtfind [options] + +Description +=========== + +Searches the known name servers in the RTC Tree for components, managers +and other such objects. Constraints can be placed on the search to limit +the results. + +Options +======= + +-i INAME, --iname=INAME + Case-insensitive name pattern. This option can be specified multiple + times. + +-m MAX_DEPTH, --maxdepth=MAX_DEPTH + Maximum depth to search down to in the tree. The default is to search + the entire tree. + +-n NAME, --name=NAME + Case-sensitive name pattern. This option can be specified multiple + times. + +-t TYPE, --type=TYPE + Type of object: ``c`` (component), ``d`` (directory), ``m`` (manager), + ``n`` (name server), ``z`` (zombie). + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtfind / -t c + +Find all components in the tree. The search starts at the root +directory. + +:: + + $ rtfind . -t cm + +Find all components and managers in or below the current working +directory. + +:: + + $ rtfind . -n 'Conso*' -type c + +Find all components in or below the current working directory whose +names start with ``Conso``. + +:: + + $ rtfind . -i 'console?.rtc' -type c + +Find all components in or below the current working directory whose +names start start with ``console`` (case insensitive) and end with +``.rtc`` (case insensitive), with only one character in between. + +:: + + $ for c in `rtfind . -type c -m 1`; do rtact ${c}; done + +(POSIX only) Activate all components in the current working directory. + +See Also +======== + + ``rtls`` (1) + diff --git a/doc/rest/rtinject.txt b/doc/rest/rtinject.txt new file mode 100644 index 0000000..4288061 --- /dev/null +++ b/doc/rest/rtinject.txt @@ -0,0 +1,134 @@ +======== +rtinject +======== + +---------------------- +inject data into ports +---------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtinject [options] [path2:port2...] + +Description +=========== + +Writes constant values to one or more ports. By default, the value is +written once. Options are available to write a set number of times, or +write regularly for a specified length of time. + +A connection will be made to the port using the default connection +settings compatible with the port. + +Options +======= + +-c CONST, --const=CONST + The constant value to send, as a Python expression. If not specified, + values will be read from stdin. Any occurrences of ``{time}`` in the + constant expression will be replaced with the current time. + +-m MODULES, --mod=MODULES + Extra modules to import. If automatic module loading struggles with + the constant's data types, try listing the modules here. The module + and its ``__POA`` partner will be imported. + +-n MAX, --number=MAX + Specify the number of times to write to the port. The default is to + write once. Specify -1 to continuously write forever. + +-p PATHS, --path=PATHS + Extra module search paths to add to the ``PYTHONPATH``. + +-r RATE, --rate=RATE + Specify the rate in Hertz at which to emit data. + +-t TIMEOUT, --timeout=TIMEOUT + Write data for this many seconds, then stop. This option overrides + ``--number``. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in + +Inject the first value received at stdin into the ``in`` port of +``ConsoleOut0.rtc``. + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -c 'RTC.TimedLong({time}, 42)' + +Inject the constant ``42`` with the current system time into the ``in`` +port of ``ConsoleOut0.rtc``. Note the quotes used to protect the Python +expression. + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -c 'RTC.TimedLong(RTC.Time(1, 0), 42)' + +Inject the constant ``42`` with a timestamp of 1 second into the ``in`` +port of ``ConsoleOut0.rtc``. + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -n 5 + +Inject the first five values received at stdin into the ``in`` port of +``ConsoleOut0.rtc``. + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -n 5 -c 'RTC.TimedLong({time}, 42)' + +Inject the constant ``42`` with the current system time into the ``in`` +port of ``ConsoleOut0.rtc`` five times. + +:: + + $ rtinject /localhost/ConsoleOut0.rtc:in -t 5 -r 10 -c 'RTC.TimedLong({time}, 42)' + +Inject the constant ``42`` with the current system time into the ``in`` +port of ``ConsoleOut0.rtc`` at 10Hz for five seconds. + +:: + + $ rtinject /localhost/MyComp0.rtc:in -c 'MyData.MyVal(84)' + +Inject the constant ``MyData.MyVal(84)`` ``in`` port of ``MyComp0.rtc`` +once. The data type is specified in a Python module in the +``PYTHONPATH``, which was generated from an OMG IDL file. + +:: + + $ rtinject /localhost/MyComp0.rtc:in -p /usr/local/mods -c 'MyData.MyVal(84)' + +Inject the constant ``MyData.MyVal(84)`` ``in`` port of ``MyComp0.rtc`` +once. The data type is specified in a Python module that is not in the +``PYTHONPATH``. The path is specified using the ``-p`` option. + +:: + + $ rtinject /localhost/MyComp0.rtc:in -p /usr/local/mods -m mymod -c 'MyData.MyVal(84)' + +Inject the constant ``MyData.MyVal(84)`` ``in`` port of ``MyComp0.rtc`` +once. The data type is specified in the ``mymod`` Python module, which +is in the ``PYTHONPATH``. + + +See Also +======== + + ``rtcat`` (1), + ``rtlog`` (1), + ``rtprint`` (1) + diff --git a/doc/rest/rtlog.txt b/doc/rest/rtlog.txt new file mode 100644 index 0000000..550553a --- /dev/null +++ b/doc/rest/rtlog.txt @@ -0,0 +1,260 @@ +===== +rtlog +===== + +--------------------------- +record and replay log files +--------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtlog [options] : [:...] + +Description +=========== + +Records and replays logs of data sent by components over their ports. +A log file can be made from the data of any number of output ports. This +log file can be replayed at a later time, maintaining the timing +information in order to mimic the original system that was recorded. + +It is possible to only replay some of the streams of data contained in a +log file, for example to select just one laser sensor's data from a log +file containing many laser sensors. Options are available to play back a +selection of entries from the log file based on index or time, change +the playback rate, and modify the timestamps in the replayed data. + +The default action is to record a log file. All ports specified on the +command line must be output ports. If replay mode is enabled, all +specified ports must be input ports matching the recorded data's data +types. + +Each port recorded in a log file creates a single data stream. When +replaying the log file, each data stream can be sent to one or more +target ports. Data streams are identified by name. This name is +specified on the command line as part of the source port. If no name is +given, a default name is created automatically. + +Connections will be made to the ports using the default connection +settings compatible with the port. + +Options +======= + +-a, --absolute-times + Times from the logged data are sent as recorded during replay, rather + than adjusted to the current timeframe. + +-d, --display-info + Display the log information and exit. + +-e END, --end=END + Time or entry index to stop recording or playback. Must be within the + bounds of the log. Specify ``-1`` to record forever or replay to the + end of the log. Use ``--index`` to specify that this value is an + index. + +-f FILENAME, --filename=FILENAME + File name of the log file to record to/playback from. If not specified + for recording, a default will be created based on the current time. + Must be specified for playback. + +--path=PATHS + Extra module search paths to add to the ``PYTHONPATH``. + +-i, --index + Interpret the start and end values as entry indices instead of + timestamps. + +-l LOGGER, --logger=LOGGER + The type of logger to use. The default is the SimplePickle logger + (``simpkl``). Alternatively, the text logger (specify using ``text``) + may be used. The text logger does not support playback. + +-m MODULES, --mod=MODULES + Extra modules to import. If automatic module loading struggles with + the data types, try listing the modules here. The module and its + ``__POA`` partner will be imported. + +-n, --ignore-times + (Replay mode only.) Ignore the log timestamps and play back a fixed + number of entries per execution cycle. Use ``--exec-rate`` to change + the execution rate. + +-p, --play + Replay mode. + +-r RATE, --rate=RATE + (Replay mode only.) Scale the playback speed of the log. + +-s START, --start=START + (Replay mode only.) Time or entry index to start playback from. Must + be within the bounds of the log. Use ``--index`` to specify that this + value is an index. + +-t TIMEOUT, --timeout=TIMEOUT + Record/replay data for this many seconds. This option overrides + ``--start``/``--end``. + +-x EXEC_RATE, --exec-rate=EXEC_RATE + Specify the rate in Hertz at which to run the component. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtlog -f log.rtlog /localhost/ConsoleIn0.rtc:out.numbers + +Log values sent by the ``ConsoleIn0.rtc`` component over its ``out`` +output port. The data stream will be named ``numbers`` in the log file. +The log file will be named ``log.rtlog``. + +:: + + $ rtlog -f log.rtlog -p /localhost/ConsoleOut0.rtc:in.numbers + +Play the entries from the stream named ``numbers`` in the log file into +the ``in`` input port of the ``ConsoleOut0.rtc`` component. + +:: + + $ rtlog -f log.rtlog -d + +Display information about the log file, including its start and end +times and the data streams it contains. + +:: + + $ rtlog -f log.rtlog -e 1292489690 + /localhost/ConsoleIn0.rtc:out.numbers + +Record data until the computer's clock reads 1292489690, then stop +logging. + +:: + + $ rtlog -f log.rtlog -e 10 -i /localhost/ConsoleIn0.rtc:out.numbers + +Record 10 entries, then stop logging. + +:: + + $ rtlog -f log.rtlog -t 10 /localhost/ConsoleIn0.rtc:out.numbers + +Record for 10 seconds, then stop logging. + +:: + + $ rtlog -f log.rtlog -p -s 1292489690 + /localhost/ConsoleOut0.rtc:in.numbers + +Replay data from the log file starting at timestamp 1292489690. + +:: + + $ rtlog -f log.rtlog -p -e 1292489700 + /localhost/ConsoleOut0.rtc:in.numbers + +Replay data from the log file from the beginning until timestamp +1292489700. + +:: + + $ rtlog -f log.rtlog -p -s 1292489690 -e 1292489700 + /localhost/ConsoleOut0.rtc:in.numbers + +Replay data from the log file from timestamp 1292489690 until timestamp +1292489700 (i.e. 10 seconds of data). + +:: + + $ rtlog -f log.rtlog -p -s 5 -i + /localhost/ConsoleOut0.rtc:in.numbers + +Replay data from the log file starting at the 5th entry. + +:: + + $ rtlog -f log.rtlog -p -e 10 /localhost/ConsoleOut0.rtc:in.numbers + +Replay data from the log file from the beginning until the 10th entry. + +:: + + $ rtlog -f log.rtlog -p -s 5 -e 10 + /localhost/ConsoleOut0.rtc:in.numbers + +Replay data from the log file from the 5th entry until the 10th entry +(i.e. 5 entries). + +:: + + $ rtlog -f log.rtlog -p -t 10 /localhost/ConsoleOut0.rtc:in.numbers + +Replay data the first 10 seconds of data from the log file. + +:: + + $ rtlog -f log.rtlog -p -r 5 /localhost/ConsoleOut0.rtc:in.numbers + +Replay the data at five times the speed it was recorded at. + +:: + + $ rtlog -f log.rtlog -p -r 0.2 /localhost/ConsoleOut0.rtc:in.numbers + +Replay the data at one fifth of the speed it was recorded at. + +:: + + $ rtlog -f log.rtlog -p -n 5 -x 1 /localhost/ConsoleOut0.rtc:in.numbers + +Replay the data, executing once per second and playing exactly 5 entries +per execution. + +:: + + $ rtlog -f log.rtlog /localhost/Sensor0.rtc:out.sensor + /localhost/Controller0.rtc:out.ctrl /localhost/Motor0.rtc:out.motor + +Record three streams of data into a single log file. The streams will be +named ``sensor``, ``ctrl`` and ``motor``. + +:: + + $ rtlog -f log.rtlog /localhost/Sensor0.rtc:in.motor + /localhost/Motor0.rtc:in.ctrl + +Play two streams of data from a single log file into different targets. + +:: + + $ rtlog -f log.rtlog -p /localhost/Controller0.rtc:in.sensor + /localhost/Controller0.rtc:in.motor + +Play two streams of data from a log file into a single port. + +:: + + $ rtlog -f log.rtlog -p /localhost/Sensor0.rtc:in.motor + /localhost/Controller0.rtc:in.motor + +Play the same stream of data from a log file into multiple ports. + +See rtinject(1) for examples using ``--mod`` and ``--path``. + +See Also +======== + + ``rtcat`` (1), + ``rtinject`` (1), + ``rtprint`` (1) + diff --git a/doc/rest/rtls.txt b/doc/rest/rtls.txt new file mode 100644 index 0000000..4f06fbb --- /dev/null +++ b/doc/rest/rtls.txt @@ -0,0 +1,106 @@ +==== +rtls +==== + +-------------------------------- +list directories in the RTC Tree +-------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtls [options] [path] + +Description +=========== + +List the contents of the a directory in the RTC Tree. The default is to +list the contents of the current working directory. + +The long display shows the following information in columns for +RT-Components: + + - State + + - Total number of ports/Total connected + + - Input ports/Inputs connected + + - Output ports/Outputs connected + + - Service ports/Service connected + + - Name + +Options +======= + +-l + Use a long listing format. + +-R, --recurse + List recursively. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtls + +List the contents of the current working directory. + +:: + + $ rtls / + +List the contents of the root directory of the RTC Tree. This will show +a list of known name servers. + +:: + + $ rtls /localhost + +List the objects registered directly to the ``localhost`` name server. + +:: + + $ rtls -R /localhost + +List all objects in the ``localhost`` name server, even those registered +to other naming contexts and managers below the name server. + +:: + + $ rtls -l /localhost + +Get a long listing of the objects registered below ``/localhost``, +showing information such as the status of components. + +:: + + $ rtls -lR /localhost + +Get a long listing of all objects in the ``localhost`` name server. + +:: + + $ watch -n 1 rtls -l + +(POSIX only) Display the status of all components in the current working +directory, updating the display once per second. + + +See Also +======== + + ``rtcat`` (1), + ``rtcwd`` (1), + ``rtpwd`` (1) + diff --git a/doc/rest/rtmgr.txt b/doc/rest/rtmgr.txt new file mode 100644 index 0000000..c8213f9 --- /dev/null +++ b/doc/rest/rtmgr.txt @@ -0,0 +1,94 @@ +===== +rtmgr +===== + +---------------- +utilise managers +---------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtmgr [options] + +Description +=========== + +Control a manager, adding and removing shared libraries and components. +Components can be instantiated from shared libraries loaded into the +manager. + +To set a mananger's configuration, use ``rtconf(1)``. To view a +manager's information, use ``rtcat(1)``. + +If multiple commands are given, they are executed in the order they are +specified on the command line. + + +Options +======= + +-c MOD_NAME, --create=MOD_NAME + Create a new component instance from the specified loaded module. + Properties of the new component an be specified after the module name + prefixed with a question mark. + +-d INSTANCE_NAME, --delete=INSTANCE_NAME + Shut down and delete the specified component instance. + +-l MOD_PATH, --load=MOD_PATH + Load the module into the manager. An initialisation function must be + specified after the module path separated by a ":". + +-u MOD_PATH_U, --unload=MOD_PATH_U + Unload the module from the manager. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtmgr /localhost/manager.mgr -l /usr/local/lib/mycomp.so:mycomp_init + +Load the ``mycomp.so`` shared library into the manager. + +:: + + $ rtmgr /localhost/manager.mgr -c mycomp + +Instantiate a new component from the ``mycomp`` shared library. + +:: + + $ rtmgr /localhost/manager.mgr -d MyComp0 + +Shut down and delete the component named ``MyComp0`` from the manager. + +:: + + $ rtmgr /localhost/manager.mgr -u /usr/local/lib/mycomp.so + +Unload the ``mycomp.so`` shared library from the manager. + +:: + + $ rtmgr /localhost/manager.mgr -l /usr/local/lib/mycomp.so:mycomp_init + -c mycomp + +Load the ``mycomp.so`` shared library into the manager and create a +component from it. + + +See Also +======== + + ``rtcat`` (1), + ``rtconf`` (1), + ``rtexit`` (1) + diff --git a/doc/rest/rtprint.txt b/doc/rest/rtprint.txt new file mode 100644 index 0000000..f9a3605 --- /dev/null +++ b/doc/rest/rtprint.txt @@ -0,0 +1,118 @@ +======= +rtprint +======= + +----------------------- +display data from ports +----------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtprint [options] : [:...] + +Description +=========== + +Print the data being sent by one or more output ports to stdout. + +By default, only the first value received from one or more ports is +printed. Options are available to print multiple values or print +regularly for a specified length of time. In any one loop of the port +checks, if only one port out of multiple has data available, that is +counted as a print for the purposes of printing a fixed number of times. + +To print data which cannot be natively printed by Python, create a +formatting function to print that data. The function must receive one +argument: the data to print. For example:: + + def rawpy(data): + return data.__repr__() + +A connection will be made to each port using the default connection +settings compatible with that port. + + +Options +======= + +-m MODULES, --mod=MODULES + Extra modules to import. If automatic module loading struggles with + the constant's data types, try listing the modules here. The module + and its ``__POA`` partner will be imported. + +-n MAX, --number=MAX + Specify the number of times to read from any ports. + +-p PATHS, --path=PATHS + Extra module search paths to add to the ``PYTHONPATH``. + +-r RATE, --rate=RATE + Specify the rate in Hertz at which to read and print. + +-t TIMEOUT, --timeout=TIMEOUT + Read data for this many seconds, then stop. This option overrides + ``--number``. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out + +Print the first value sent by the ``ConsoleIn0.rtc`` component over its +``out`` port. + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out -n 5 + +Print the first five values sent by the ``ConsoleIn0.rtc`` component +over its ``out`` port. + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out -t 5 + +Print the values sent by the ``ConsoleIn0.rtc`` component over its +``out`` port for five seconds. + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out -t 5 -r 10 + +Print the values sent by the ``ConsoleIn0.rtc`` component over its +``out`` port up to ten times a second for for five seconds. + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out#rawpy + +Print the first value sent by the ``ConsoleIn0.rtc`` component over its +``out`` port as a Python expression using the inbuilt ``rawpy`` +formatter. + +:: + + $ rtprint /localhost/ConsoleIn0.rtc:out#printers.my_formatter + +Print the first value sent by the ``ConsoleIn0.rtc`` component over its +``out`` port using the ``my_formatter`` formatting function from the +``printers`` module to print the data. + +See rtinject(1) for examples using ``--mod`` and ``--path``. + +See Also +======== + + ``rtcat`` (1), + ``rtinject`` (1), + ``rtlog`` (1) + diff --git a/doc/rest/rtpwd.txt b/doc/rest/rtpwd.txt new file mode 100644 index 0000000..514a378 --- /dev/null +++ b/doc/rest/rtpwd.txt @@ -0,0 +1,37 @@ +===== +rtpwd +===== + +----------------------------------- +print the current working directory +----------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtpwd + +Description +=========== + +Displays the current working directory in the RTC Tree. + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtpwd + +Print the current working directory. + +See Also +======== + + ``rtcwd`` (1), + ``rtls`` (1) + diff --git a/doc/rest/rtreset.txt b/doc/rest/rtreset.txt new file mode 100644 index 0000000..8349c2d --- /dev/null +++ b/doc/rest/rtreset.txt @@ -0,0 +1,60 @@ +======= +rtreset +======= + +---------------- +reset components +---------------- + +.. include: ../common/docinfo_block.txt + +Synopsis +======== + +rtreset [options] [ ...] + +Description +=========== + +Resets the specified RT-Components, provided they are in the ``error`` +state. + +Options +======= + +-e EC_INDEX, --exec_context=EC_INDEX + Index of the execution context to change state in. The default is 0. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtreset /localhost/local.host_cxt/ConsoleOut0.rtc + +Reset ConsoleOut0.rtc in all owned and participating execution contexts. + +:: + + $ rtreset ConsoleOut0.rtc ConsoleIn0.rtc + +Reset ConsoleOut0.rtc and ConsoleIn0.rtc in all owned and participating +execution contexts. + +:: + + $ rtreset -e 2 /localhost/local.host_cxt/Motor0.rtc + +Reset Motor0.rtc in only the execution context with ID 2. + +See Also +======== + +``rtact`` (1), +``rtdeact`` (1), +``rtcat`` (1) + diff --git a/doc/rest/rtresurrect.txt b/doc/rest/rtresurrect.txt new file mode 100644 index 0000000..f6fab7f --- /dev/null +++ b/doc/rest/rtresurrect.txt @@ -0,0 +1,68 @@ +=========== +rtresurrect +=========== + +-------------------------------------------- +resurrect RT-Systems from stored RTSProfiles +-------------------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtresurrect [options] [RTSProfile file] + +Description +=========== + +Load an RTSProfile and use it with already-running components to restore +an RT-System. The connections between the components and the +configuration parameter values are restored. Any components not marked +as ``required`` in the RTSProfile will be ignored if they are not +running. + +If no file is given, the RTSProfile is read from standard input. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +--dry-run + Print what will be done but don't actually do anything. + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtresurrect sys.rtsys + +Recreate the RT-System specified in the file ``sys.rtsys``. + +:: + + $ rtresurrect sys.rtsys --dry-run + +Display the actions that will be performed to recreate the system. + +See Also +======== + + ``rtcheck`` (1), + ``rtcon`` (1), + ``rtconf`` (1), + ``rtstart`` (1) + diff --git a/doc/rest/rtshell.txt b/doc/rest/rtshell.txt new file mode 100644 index 0000000..5d6ad36 --- /dev/null +++ b/doc/rest/rtshell.txt @@ -0,0 +1,224 @@ +======= +rtshell +======= + +------------------------------------ +command line tools for RT-Middleware +------------------------------------ + +.. include:: ../common/docinfo_block.txt + + +Description +=========== + +rtshell provides commands used to manage individual RT components and +managers, as well as complete RT Systems. It can be used with the +OpenRTM-aist middleware or middlewares that use a compatible CORBA-based +introspection system. + +Many of the commands allow components and managers running on +nameservers to be treated like a file system. Directories can be +entered, components can be cat'd and activated/deactivated/reset, +connections made and removed, and so on. Other commands are used in +conjunction with RtsProfile XML/YAML files to manage complete RT +Systems. + +The commands are aimed at users of OpenRTM-aist who wish to manage +components on low-resource systems, systems where a GUI is not available +(particularly where no network connection is available to manage +components from another computer), as well as those who face other +difficulties using RTSystemEditor. Being familiar with using a +command-line is a benefit when using these commands of rtshell. + +Commands +======== + + rtact + Activate components. + + rtcat + View component information and meta-data. + + rtcheck + Check the consistency of a running system against an RTSProfile. + + rtcomp + Create composite components. + + rtcon + Connect ports together. + + rtconf + View and change configuration parameters and sets. + + rtcryo + Preserve a running system as an RTSProfile. + + rtcwd + Change the current working directory in the RTC Tree. + + rtdeact + Deactivate components. + + rtdel + Delete registrations from a name server. + + rtdis + Disconnect ports. + + rtdoc + Print RT-Component documentation. + + rtexit + Make an RT-Component stop running and exit. + + rtfind + Search for components, managers, etc. in the known name servers. + + rtinject + Inject data into an input port. + + rtlog + Record and replay logs of data sent by ports. + + rtls + List a directory in the RTC Tree. + + rtmgr + Use managers to create and delete RT-Components. + + rtprint + Display the data being written by an output port. + + rtpwd + Print the current working directory in the RTC Tree. + + rtreset + Reset components in the error state. + + rtresurrect + Restore a running system from an RTSProfile. + + rtstart + Start an entire RT-System using an RTSProfile. + + rtstodot + Visualise the running RT-System using the dot file format. + + rtstop + Stop an entire RT-System using an RTSProfile. + + rtteardown + Remove all connections in an RT-System using an RTSProfile. + + +RTC Tree +======== + +The commands operate on the RTC Tree. This is a file system-like tree +built by parsing name servers to find directories, components and +managers. It can be treated like a normal file system. + +Name servers are treated as directories off the root directory, ``/``. +Below them are 'files' and sub-directories. A sub-directory represents a +naming context below the root naming context of a name server. Files are +components and managers. + +The name servers parsed to build the tree are taken from two sources. +The first is the path given to a command. This is appended to the +current working directory of the tree, and the first element is treated +as a name server. + +The second source for name servers is the ``RTCTREE_NAMESERVERS`` +environment variable. This is a semi-colon separated list of name server +addresses. + + +Shell completion +================ + +Users of a Bash-compatible shell can use the included completion script +to make using the commands easier. The script is installed in +``${prefix}/share/rtshell``. Run the following command to load it:: + + $ source bash_completion + +This can be added to the ``~/.bashrc`` file to have it loaded in every +new shell instance. Here are some examples of completion:: + + $ rtcwd [TAB] + $ rtcwd localhost/ + $ rtcwd localhost/[TAB] + $ rtcwd localhost/kenroke.host_cxt/ + $ rtcwd localhost/kenroke.host_cxt/[TAB][TAB] + ConsoleIn0.rtc ConfigSample0.rtc manager.mgr Sensor0.rtc + $ rtcwd localhost/kenroke.host_cxt/[ENTER] + $ rtconf ConfigSample0.rtc set [TAB] + double_param0 double_param1 int_param0 int_param1 str_param0 + str_param1 vector_param0 + $ rtcon Sensor0.rtc:[TAB] + in out + + +System requirements +=================== + +rtshell requires **rtctree 3.0**. It must be installed for the commands +to function. + +The commands that work with RTSProfile files require **rtsprofile 2.0**. +It must be installed for these commands to function. + +rtshell uses the new string formatting operations that were introduced +in **Python 2.6**. It will not function with an earlier version of +Python. It has not been tested with Python 3 and it is likely that +several changes will be necessary to make it function using this version +of Python. + +``rtinject``, ``rtlog`` and ``rtprint`` require the **Python version of +OpenRTM-aist**. + +For Ubuntu users using a version of Ubuntu prior to 9.04, a suitable +Python version must be installed by hand. Consider upgrading to Ubuntu +9.04 or later (10.04 offers LTS). + + +.. include:: ../common/common_body.txt + + +Bugs +==== + +The tools have been reported to not work well with the JAVA ORB. + + +See also +======== + + ``rtact`` (1), + ``rtcat`` (1), + ``rtcheck`` (1), + ``rtcomp`` (1), + ``rtcon`` (1), + ``rtconf`` (1), + ``rtcryo`` (1), + ``rtcwd`` (1), + ``rtdeact`` (1), + ``rtdel`` (1), + ``rtdis`` (1), + ``rtexit`` (1), + ``rtfind`` (1), + ``rtinject`` (1), + ``rtlog`` (1), + ``rtls`` (1), + ``rtmgr`` (1), + ``rtprint`` (1), + ``rtpwd`` (1), + ``rtreset`` (1), + ``rtresurrect`` (1), + ``rtstart`` (1), + ``rtstodot`` (1), + ``rtstop`` (1), + ``rtteardown`` (1) + diff --git a/doc/rest/rtstart.txt b/doc/rest/rtstart.txt new file mode 100644 index 0000000..e9e0723 --- /dev/null +++ b/doc/rest/rtstart.txt @@ -0,0 +1,71 @@ +======= +rtstart +======= + +------------------ +start an RT-System +------------------ + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtstart [options] [RTSProfile file] + +Description +=========== + +Start an RT-System, activating all involved components, using an +RTSProfile. Components are activated in the order specified in the +RTSProfile. Any components not marked as ``required`` in the RTSProfile +will be ignored if they are not running. + +If no file is given, the RTSProfile is read from standard input. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +--dry-run + Print what will be done but don't actually do anything. + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +Start plans +=========== + +.. include:: ../common/start_stop_plans.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtstart sys.rtsys + +Start the RT-System specified in the file ``sys.rtsys``. + +:: + + $ rtstart sys.rtsys --dry-run + +Display the actions that will be performed to start the system. + +See Also +======== + + ``rtcheck`` (1), + ``rtresurrect`` (1), + ``rtstop`` (1) + diff --git a/doc/rest/rtstodot.txt b/doc/rest/rtstodot.txt new file mode 100644 index 0000000..c81163e --- /dev/null +++ b/doc/rest/rtstodot.txt @@ -0,0 +1,65 @@ +======== +rtstodot +======== + +-------------------- +visualise RT-Systems +-------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtstodot [options] [RTSProfile file] + +Description +=========== + +Visualise RT-Systems using the dot file format from Graphviz. + +If no file is given, the profile is read from standard input. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtstodot sys.rtsys | dot -T xlib + +Visualise the system stored in ``sys.rtsys``. + +:: + + $ rtstodot sys.rtsys | dot -T eps > sys.eps + +Visualise the system stored in ``sys.rtsys`` and save it as an +Encapsulated PostScript file. + +:: + + $ rtcryo | rtstodot | dot -T xlib + +Visualise the currently running system. + +See Also +======== + + ``rtcryo`` (1) + diff --git a/doc/rest/rtstop.txt b/doc/rest/rtstop.txt new file mode 100644 index 0000000..f947115 --- /dev/null +++ b/doc/rest/rtstop.txt @@ -0,0 +1,71 @@ +====== +rtstop +====== + +----------------- +stop an RT-System +----------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtstop [options] [RTSProfile file] + +Description +=========== + +Stop an RT-System, deactivating all involved components, using an +RTSProfile. Components are deactivated in the order specified in the +RTSProfile. Any components not marked as ``required`` in the RTSProfile +will be ignored if they are not running. + +If no file is given, the RTSProfile is read from standard input. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +--dry-run + Print what will be done but don't actually do anything. + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +Start plans +=========== + +.. include:: ../common/start_stop_plans.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtstop sys.rtsys + +Stop the RT-System specified in the file ``sys.rtsys``. + +:: + + $ rtstop sys.rtsys --dry-run + +Display the actions that will be performed to stop the system. + +See Also +======== + + ``rtcheck`` (1), + ``rtresurrect`` (1), + ``rtstart`` (1) + diff --git a/doc/rest/rtteardown.txt b/doc/rest/rtteardown.txt new file mode 100644 index 0000000..9356cf0 --- /dev/null +++ b/doc/rest/rtteardown.txt @@ -0,0 +1,63 @@ +========== +rtteardown +========== + +-------------------------------------- +remove all connections in an RT-System +-------------------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtteardown [options] [RTSProfile file] + +Description +=========== + +Tears down an RT-System. Loads an RTSProfile and use it to remove the +connections that make up the RT-System from running components. + +If no file is given, the RTSProfile is read from standard input. + +XML format is used by default; to use RTSProfiles specified in YAML, +specify ``--yaml``. + +Options +======= + +--dry-run + Print what will be done but don't actually do anything. + +-x, --xml + Use XML input format. + +-y, --yaml + Use YAML input format. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtteardown sys.rtsys + +Destroy the RT-System specified in the file ``sys.rtsys``. + +:: + + $ rtteardown sys.rtsys --dry-run + +Display the actions that will be performed to destroy the system. + +See Also +======== + + ``rtcheck`` (1), + ``rtresurrect`` (1) + diff --git a/doc/rest/rtvlog.txt b/doc/rest/rtvlog.txt new file mode 100644 index 0000000..5ff569d --- /dev/null +++ b/doc/rest/rtvlog.txt @@ -0,0 +1,67 @@ +====== +rtexit +====== + +---------------------------- +view RT-Component log output +---------------------------- + +.. include:: ../common/docinfo_block.txt + +Synopsis +======== + +rtvlog [options] [path 2 ...] + +Description +=========== + +View the log output of one or more RT-Components. The RT-Components must +include the SDO Logger interface support, either directly or via the +manager they are running in. The log output will be printed to the +terminal. + +Options +======= + +-f FILTER, --filter=FILTER + Filter the sources that can produce log events. For example, the + events from only a data port can be viewed. Multiple filters can be + specified. + +-l LEVEL, --level=LEVEL + Specify the maximum level of events to receive. Valid levels are + ERROR, WARN, INFO, NORMAL, DEBUG, TRACE, VERBOSE, and PARANOID. + +.. include:: ../common/common_opts.txt + +.. include:: ../common/common_body.txt + +Examples +======== + +:: + + $ rtvlog /localhost/ConsoleOut0.rtc + +View the log events being produced by the ``ConsoleOut0.rtc`` component. + +:: + + $ rtvlog ConsoleOut0.rtc ConsoleIn0.rtc + +View the log events being produced by both the ``ConsoleOut0.rtc`` and +``ConsoleIn0.rtc`` components. + +:: + + $ rtvlog ConsoleOut0.rtc -f DATAPORT -l DEBUG + +View all events up to the level DEBUG from the data ports of the +``ConsoleOut0.rtc`` component. + +See Also +======== + + ``rtshell`` (1) + diff --git a/rtact b/rtact new file mode 100755 index 0000000..b045fd1 --- /dev/null +++ b/rtact @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to move a component to the activated state. + +''' + + +import sys + +from rtshell import rtact + + +if __name__ == '__main__': + sys.exit(rtact.main()) + + +# vim: tw=79 + diff --git a/rtact.bat b/rtact.bat new file mode 100644 index 0000000..6590bf8 --- /dev/null +++ b/rtact.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtact.py %* + diff --git a/rtcat b/rtcat new file mode 100755 index 0000000..fbd27b5 --- /dev/null +++ b/rtcat @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to display component information. + +''' + + +import sys + +from rtshell import rtcat + + +if __name__ == '__main__': + res, lines = rtcat.main() + for l in lines: + print l + sys.exit(res) + +# vim: tw=79 + diff --git a/rtcat.bat b/rtcat.bat new file mode 100644 index 0000000..951533a --- /dev/null +++ b/rtcat.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcat.py %* + diff --git a/rtcheck b/rtcheck new file mode 100755 index 0000000..93ee1bc --- /dev/null +++ b/rtcheck @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command file for rtcheck. + +''' + + +import sys + +from rtshell import rtcheck + + +if __name__ == '__main__': + sys.exit(rtcheck.main()) + + +# vim: tw=79 + diff --git a/rtcheck.bat b/rtcheck.bat new file mode 100644 index 0000000..06f2a7b --- /dev/null +++ b/rtcheck.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcheck.py %* + diff --git a/rtcomp b/rtcomp new file mode 100755 index 0000000..915d08b --- /dev/null +++ b/rtcomp @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to create composite components. + +''' + + +import sys + +from rtshell import rtcomp + + +if __name__ == '__main__': + sys.exit(rtcomp.main()) + + +# vim: tw=79 + diff --git a/rtcomp.bat b/rtcomp.bat new file mode 100644 index 0000000..361f8eb --- /dev/null +++ b/rtcomp.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcomp.py %* + diff --git a/rtcon b/rtcon new file mode 100755 index 0000000..22c33d5 --- /dev/null +++ b/rtcon @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to connect two ports. + +''' + + +import sys + +from rtshell import rtcon + + +if __name__ == '__main__': + sys.exit(rtcon.main()) + + +# vim: tw=79 + diff --git a/rtcon.bat b/rtcon.bat new file mode 100644 index 0000000..9b33d3c --- /dev/null +++ b/rtcon.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcon.py %* + diff --git a/rtconf b/rtconf new file mode 100755 index 0000000..5c9c091 --- /dev/null +++ b/rtconf @@ -0,0 +1,34 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to manage component configuration. + +''' + + +import sys + +from rtshell import rtconf + + +if __name__ == '__main__': + res, lines = rtconf.main() + for l in lines: + print l + sys.exit(res) + +# vim: tw=79 + diff --git a/rtconf.bat b/rtconf.bat new file mode 100644 index 0000000..cb6bdf3 --- /dev/null +++ b/rtconf.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtconf.py %* + diff --git a/rtcryo b/rtcryo new file mode 100755 index 0000000..318b28f --- /dev/null +++ b/rtcryo @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcryo command. + +''' + + +import sys + +from rtshell import rtcryo + + +if __name__ == '__main__': + sys.exit(rtcryo.main()) + + +# vim: tw=79 + diff --git a/rtcryo.bat b/rtcryo.bat new file mode 100644 index 0000000..39b7d67 --- /dev/null +++ b/rtcryo.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcryo.py %* + diff --git a/rtcwd.bat b/rtcwd.bat new file mode 100644 index 0000000..4e6bb03 --- /dev/null +++ b/rtcwd.bat @@ -0,0 +1,15 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +python -c "import sys; import rtshell.rtcwd; sys.exit(rtshell.rtcwd.main(['%*']))" > settmp.bat +settmp +del settmp.bat + diff --git a/rtdeact b/rtdeact new file mode 100755 index 0000000..b13bfe7 --- /dev/null +++ b/rtdeact @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to move a component to the inactive state. + +''' + + +import sys + +from rtshell import rtdeact + + +if __name__ == '__main__': + sys.exit(rtdeact.main()) + + +# vim: tw=79 + diff --git a/rtdeact.bat b/rtdeact.bat new file mode 100644 index 0000000..8bc2961 --- /dev/null +++ b/rtdeact.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtdeact.py %* + diff --git a/rtdel b/rtdel new file mode 100755 index 0000000..044808f --- /dev/null +++ b/rtdel @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Delete an object from a name server. + +''' + + +import sys + +from rtshell import rtdel + + +if __name__ == '__main__': + sys.exit(rtdel.main()) + + +# vim: tw=79 + diff --git a/rtdel.bat b/rtdel.bat new file mode 100644 index 0000000..f00311e --- /dev/null +++ b/rtdel.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtdel.py %* + diff --git a/rtdis b/rtdis new file mode 100755 index 0000000..39b1e70 --- /dev/null +++ b/rtdis @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to disconnect ports. + +''' + + +import sys + +from rtshell import rtdis + + +if __name__ == '__main__': + sys.exit(rtdis.main()) + + +# vim: tw=79 + diff --git a/rtdis.bat b/rtdis.bat new file mode 100644 index 0000000..fe72bce --- /dev/null +++ b/rtdis.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtdis.py %* + diff --git a/rtdoc b/rtdoc new file mode 100755 index 0000000..86c24d9 --- /dev/null +++ b/rtdoc @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Yosuke Matsusaka and Geoffrey Biggs + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to display RT-Component documentation. + +''' + + +import sys + +from rtshell import rtdoc + + +if __name__ == '__main__': + sys.exit(rtdoc.main()) + + +# vim: tw=79 + diff --git a/rtdoc.bat b/rtdoc.bat new file mode 100644 index 0000000..5920316 --- /dev/null +++ b/rtdoc.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtdoc.py %* + diff --git a/rtexit b/rtexit new file mode 100755 index 0000000..3beae13 --- /dev/null +++ b/rtexit @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to exit a component. + +''' + + +import sys + +from rtshell import rtexit + + +if __name__ == '__main__': + sys.exit(rtexit.main()) + + +# vim: tw=79 + diff --git a/rtexit.bat b/rtexit.bat new file mode 100644 index 0000000..ff84ad6 --- /dev/null +++ b/rtexit.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtexit.py %* + diff --git a/rtfind b/rtfind new file mode 100755 index 0000000..8b0235a --- /dev/null +++ b/rtfind @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to find components, managers, etc. + +''' + + +import sys + +from rtshell import rtfind + + +if __name__ == '__main__': + res, matches = rtfind.main() + for m in matches: + print m + sys.exit(res) + + +# vim: tw=79 + diff --git a/rtfind.bat b/rtfind.bat new file mode 100644 index 0000000..5176729 --- /dev/null +++ b/rtfind.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtfind.py %* + diff --git a/rtinject b/rtinject new file mode 100755 index 0000000..a975e94 --- /dev/null +++ b/rtinject @@ -0,0 +1,31 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Inject a single shot of data into an input port of a component. + +''' + + +import sys + +from rtshell import rtinject + + +if __name__ == '__main__': + sys.exit(rtinject.main()) + +# vim: tw=79 + diff --git a/rtinject.bat b/rtinject.bat new file mode 100644 index 0000000..b7181c9 --- /dev/null +++ b/rtinject.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtinject.py %* + diff --git a/rtlog b/rtlog new file mode 100755 index 0000000..4e11b37 --- /dev/null +++ b/rtlog @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to print data being sent by an output port. + +''' + + +import sys + +import rtshell.rtlog + + +if __name__ == '__main__': + sys.exit(rtshell.rtlog.main()) + + +# vim: tw=79 + diff --git a/rtlog.bat b/rtlog.bat new file mode 100644 index 0000000..532f38b --- /dev/null +++ b/rtlog.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtlog.py %* + diff --git a/rtls b/rtls new file mode 100755 index 0000000..dfebc34 --- /dev/null +++ b/rtls @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to list naming contexts. + +''' + + +import sys + +from rtshell import rtls + + +if __name__ == '__main__': + res, lines = rtls.main() + for l in lines: + print l + sys.exit(res) + + +# vim: tw=79 + diff --git a/rtls.bat b/rtls.bat new file mode 100644 index 0000000..a7303f1 --- /dev/null +++ b/rtls.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtls.py %* + diff --git a/rtmgr b/rtmgr new file mode 100755 index 0000000..d1f5555 --- /dev/null +++ b/rtmgr @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command for controlling managers. + +''' + + +import sys + +import rtshell.rtmgr + + +if __name__ == '__main__': + sys.exit(rtshell.rtmgr.main()) + + +# vim: tw=79 + diff --git a/rtmgr.bat b/rtmgr.bat new file mode 100644 index 0000000..289e265 --- /dev/null +++ b/rtmgr.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtmgr.py %* + diff --git a/rtprint b/rtprint new file mode 100755 index 0000000..759b863 --- /dev/null +++ b/rtprint @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to print data being sent by an output port. + +''' + + +import sys + +import rtshell.rtprint + + +if __name__ == '__main__': + sys.exit(rtshell.rtprint.main()) + + +# vim: tw=79 + diff --git a/rtprint.bat b/rtprint.bat new file mode 100644 index 0000000..7a1963e --- /dev/null +++ b/rtprint.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtprint.py %* + diff --git a/rtpwd b/rtpwd new file mode 100755 index 0000000..3cea936 --- /dev/null +++ b/rtpwd @@ -0,0 +1,47 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to show the current value of the current working directory environment +variable. + +''' + + +import os +import sys + + +from rtshell.path import ENV_VAR + + +def main(argv): + if len(argv) > 1 and (argv[1] == '--help' or argv[1] == '-h'): + print >>sys.stderr, \ + 'Print the name of the current rtshell working directory.' + return 0 + if ENV_VAR in os.environ: + print os.environ[ENV_VAR] + else: + print '/' + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) + + +# vim: tw=79 + diff --git a/rtpwd.bat b/rtpwd.bat new file mode 100644 index 0000000..50efdc4 --- /dev/null +++ b/rtpwd.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtpwd.py %* + diff --git a/rtreset b/rtreset new file mode 100755 index 0000000..67d18e3 --- /dev/null +++ b/rtreset @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to move a component from the error state to the inactive state. + +''' + + +import sys + +from rtshell import rtreset + + +if __name__ == '__main__': + sys.exit(rtreset.main()) + + +# vim: tw=79 + diff --git a/rtreset.bat b/rtreset.bat new file mode 100644 index 0000000..4bc7f05 --- /dev/null +++ b/rtreset.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtreset.py %* + diff --git a/rtresurrect b/rtresurrect new file mode 100755 index 0000000..2e2968e --- /dev/null +++ b/rtresurrect @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command file for rtresurrect. + +''' + + +import sys + +from rtshell import rtresurrect + + +if __name__ == '__main__': + sys.exit(rtresurrect.main()) + + +# vim: tw=79 + diff --git a/rtresurrect.bat b/rtresurrect.bat new file mode 100644 index 0000000..d3e1a3e --- /dev/null +++ b/rtresurrect.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtresurrect.py %* + diff --git a/rtshell/__init__.py b/rtshell/__init__.py new file mode 100644 index 0000000..aa266ee --- /dev/null +++ b/rtshell/__init__.py @@ -0,0 +1,25 @@ +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Commands for managing RT Components and RTM-based systems from a shell. + +''' + + +RTSH_VERSION = '3.0.0' + + +# vim: tw=79 + diff --git a/rtshell/actions.py b/rtshell/actions.py new file mode 100644 index 0000000..49853e8 --- /dev/null +++ b/rtshell/actions.py @@ -0,0 +1,807 @@ +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Function objects for actions that can be performed using rtctree. + +''' + + +import sys + +import rtctree.exceptions +import rtctree.path + +import option_store +import rts_exceptions + + +############################################################################### +## Base action function object + +class Action(object): + '''Base class for all action function objects. + + Action objects should implement the _execute method. This will receive one + argument (a reference to the RTCTree object) and should implement the + action. It must return True for success or False for failure, and a very + brief error message. + + All actions must be provided with one or more result callback objects. + These will be called in the order they are set after performing the action + and passed the result of the action's _execute method. Its job is to take + appropriate measures based on the outcome of the action. Typically, the + first should perform a verification that the result meets necessary + criteria, such as a required action succeeding. If no callbacks are + provided, a default (@ref BaseCallback) will be inserted. + + Action objects must implement the __str__ method. They should print out a + description of what they will do. This description should include details + specific to that instance of the action (for example, "Will activate + component 'ConsoleIn0.rtc'"). + + ''' + + def __init__(self, callbacks=[]): + super(Action, self).__init__() + self._callbacks = callbacks + + def __call__(self, rtctree=None): + result, err = self._execute(rtctree) + if not self._callbacks: + c = BaseCallback() + c(result, err) + else: + for c in self._callbacks: + c(result, err) + + def __str__(self): + return 'Base action' + + def add_callback(self, callback): + self._callbacks.append(callback) + + @property + def optional(self): + '''Is this action optional?''' + for cb in self._callbacks: + if cb.__class__ == RequiredActionCB: + return False + return True + + def _action_string(self, action_desc): + if self._callbacks: + action_desc += ' ({0}'.format(self._callbacks[0]) + for c in self._callbacks[1:]: + action_desc += ', {0}'.format(c) + action_desc += ')' + return action_desc + + def _execute(self, rtctree): + '''Base for action execution method. + + Return (True, '') or (False, 'Why I failed.') when implementing this + method. + + ''' + raise NotImplementedError + + +############################################################################### +## Base callback + +class BaseCallback(object): + '''Base class for callback objects. + + Callback objects must implement the __call__ method, and receive two + values: + - A boolean indicating success or failure of the action. + - An error message to optionally be printed on failure. None if no message. + + ''' + def __init__(self, *args, **kwargs): + super(BaseCallback, self).__init__() + + def __call__(self, result, err_msg): + if err_msg: + if not result: + print >>sys.stderr, 'Action failed: ' + err_msg + else: + if not result: + print >>sys.stderr, 'Action failed.' + + def __str__(self): + return '' + + +############################################################################### +## Required action callback + +class RequiredActionCB(BaseCallback): + '''Callback for a required action. + + Checks the action result and raises @ref RequiredActionFailedError if the + action failed. + + ''' + def __init__(self, *args, **kwargs): + super(RequiredActionCB, self).__init__(*args, **kwargs) + + def __call__(self, result, err_msg): + if not result: + raise rts_exceptions.RequiredActionFailedError(err_msg) + + def __str__(self): + return 'Required' + + +############################################################################### +## Check if a required component is present + +class CheckForRequiredCompAct(Action): + '''Check for a required component in the RTC Tree. + + This action checks the rtctree to see if a component is present at a + particular path. If it finds a component at that path, it will check that + the component's ID and instance name to ensure it is the desired component. + If the component is not present or is the wrong component, this action will + fail. Otherwise, it will succeed. + + ''' + def __init__(self, path_str, id, instance_name, callbacks=[]): + super(CheckForRequiredCompAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._path = rtctree.path.parse_path(path_str)[0] + self._id = id + self._instance_name = instance_name + + def __str__(self): + return self._action_string('Check for required component \ +"{0}", "{1}" at path {2}'.format(self._id, self._instance_name, + self._path_str)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Checking for required component {0} with ID \ +"{1}" and instance name "{2}"'.format(self._path_str, self._id, + self._instance_name) + # Check there is a component at the specified path + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return False, \ + 'Required component missing: {0}'.format(self._path_str) + # Check the instance names match + if comp.instance_name != self._instance_name: + return False, 'Component instance names mismatched: {0} != \ +{1}'.format(comp.instance_name, self._instance_name) + # Check the IDs match - in rtctree, the ID is formed from like so: + # 'RTC:'::: + id = 'RTC:{0}:{1}:{2}:{3}'.format(comp.vendor, comp.category, + comp.type_name, comp.version) + if id != self._id: + return False, 'Component IDs mismatched: {0} != {1}'.format(id, + self._id) + # All good + return True, None + + +############################################################################### +## Check if a port exists on a component + +class CheckForPortAct(Action): + '''Check for a port on a component in the RTC Tree. + + This action checks the rtctree to see if a component is present at a + particular path. If it finds a component at that path, it will check that + the component has the desired port. If the port is not present on the + component, it will fail. Otherwise, it will succeed. No check is performed + to ensure that the correct component is at that path; for that, use the + @ref CheckForRequiredCompAct action. + + This action will not fail if the specified component does not exist or is + incorrect. To cause an abort in these situations, use @ref + CheckForRequiredCompAct. + + ''' + def __init__(self, path_str, port_name, callbacks=[]): + super(CheckForPortAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._path = rtctree.path.parse_path(path_str)[0] + self._port_name = port_name + + def __str__(self): + return self._action_string('Check for required port "{0}" on \ +component at path {1}'.format(self._port_name, self._path_str)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Checking for required port {0} on component \ +{1}'.format(self._port_name, self._path_str) + # Get the component at the specified path + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return True, None + # Check for the port + if not comp.has_port_by_name(self._port_name): + return False, \ + 'Required port not found: {0}'.format(self._port_name) + # All good + return True, None + + +############################################################################### +## Check the active configuration set of a component. + +class CheckActiveConfigSetAct(Action): + '''Checks if a configuration set is active in a component. + + This action checks if the active configuration set of a component is as + expected. It will check if the set exists first; if no such set exists, + the action will fail. + + This action will not fail if the specified component does not exist or is + incorrect. To cause an abort in these situations, use @ref + CheckForRequiredCompAct. + + ''' + def __init__(self, path_str, set, callbacks=[]): + super(CheckActiveConfigSetAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._path = rtctree.path.parse_path(path_str)[0] + self._set = str(set) # Cannot send unicode strings to CORBA + + def __str__(self): + return self._action_string('Check configuration set "{0}" is active '\ + 'on component {1}'.format(self._set, self._path_str)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Checking configuration set "{0}" is active '\ + 'on component {1}'.format(self._set, self._path_str) + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return False, 'Component missing: {0}'.format(self._path_str) + if comp.active_conf_set_name != self._set: + return False, 'Wrong configuration set is active on {0} '\ + '(Active set: {1})'.format(self._path_str, + comp.active_conf_set_name) + return True, None + + +############################################################################### +## Set the active configuration set of a component + +class SetActiveConfigSetAct(Action): + '''Set the active configuration set of a component. + + This action sets the active configuration set of a component to the + specified configuration set. It will check if the set exists first; if no + such set exists, the action will fail. + + This action will not fail if the specified component does not exist or is + incorrect. To cause an abort in these situations, use @ref + CheckForRequiredCompAct. + + ''' + def __init__(self, path_str, set, callbacks=[]): + super(SetActiveConfigSetAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._path = rtctree.path.parse_path(path_str)[0] + self._set = str(set) # Cannot send unicode strings to CORBA + + def __str__(self): + return self._action_string('Set configuration set "{0}" active on \ +component at path {1}'.format(self._set, self._path_str)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Setting configuration set "{0}" active on \ +component {1}'.format(self._set, self._path_str) + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return False, 'Component missing: {0}'.format(self._path_str) + try: + comp.activate_conf_set(self._set) + except rts_exceptions.NoConfSetError: + return False, 'Invalid configuration set: {0}'.format(self._set) + return True, None + + +############################################################################### +## Set a configuration parameter in a configuration set + +class CheckConfigParamAct(Action): + '''Check the value of a configuration parameter. + + This action checks that the value of a configuration parameter is correct. + It will fail if the set or the parameter does not exist. + + This action will not fail if the specified component does not exist or is + incorrect. To cause an abort in these situations, use @ref + CheckForRequiredCompAct. + + ''' + def __init__(self, path_str, set, param, value, callbacks=[]): + super(CheckConfigParamAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._path = rtctree.path.parse_path(path_str)[0] + self._set = str(set) # Cannot send unicode strings to CORBA + self._param = str(param) + self._value = str(value) + + def __str__(self): + return self._action_string('Check parameter "{0}" in set "{1}" on '\ + 'component at path "{2}" is "{3}"'.format(self._param, + self._set, self._path_str, self._value)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Checking parameter "{0}" in set "{1}" on '\ + 'component "{2}" is "{3}"'.format(self._param, self._set, + self._path_str, self._value) + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return False, 'Component missing: {0}'.format(self._path_str) + if not self._set in comp.conf_sets: + return False, 'Invalid configuration set: {0}'.format(self._set) + if not comp.conf_sets[self._set].has_param(self._param): + return False, 'Invalid configuration parameter: '\ + '{0}'.format(self._param) + if comp.conf_sets[self._set].data[self._param] != self._value: + return False, 'Configuration parameter {0} in set {1} on '\ + 'component {2} is incorrect (value: {3})'.format( + self._param, self._set, self._path_str, + comp.conf_sets[self._set].data[self._param]) + return True, None + + +############################################################################### +## Set a configuration parameter in a configuration set + +class SetConfigParamValueAct(Action): + '''Change the value of a configuration parameter in a set. + + This action sets the value of the given configuration parameter in the + given configuration set. It will fail if the set does not exist, or the + parameter does not exist in that set. + + This action will not fail if the specified component does not exist or is + incorrect. To cause an abort in these situations, use @ref + CheckForRequiredCompAct. + + ''' + def __init__(self, path_str, set, parameter, new_value, callbacks=[]): + super(SetConfigParamValueAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._path = rtctree.path.parse_path(path_str)[0] + self._set = str(set) # Cannot send unicode strings to CORBA + self._param = str(parameter) + self._new_value = str(new_value) + + def __str__(self): + return self._action_string('Set parameter "{0}" in set "{1}" on \ +component at path {2} to "{3}"'.format(self._param, self._set, + self._path_str, self._new_value)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Setting parameter "{0}" in set "{1}" on \ +component at path {2} to "{3}"'.format(self._param, self._set, + self._path_str, self._new_value) + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return False, 'Component missing: {0}'.format(self._path_str) + try: + comp.set_conf_set_value(self._set, self._param, self._new_value) + except rts_exceptions.NoConfSetError: + return False, 'Invalid configuration set: {0}'.format(self._set) + except rts_exceptions.NoSuchConfParamError: + return False, 'Invalid configuration parameter: {0}'.format(self._param) + comp.reparse_conf_sets() + if self._set == comp.active_conf_set_name: + comp.activate_conf_set(self._set) + return True, None + + +############################################################################### +## Check if a connection between two components exists and is correct + +class CheckForConnAct(Action): + '''Check for a correct connection between two components. + + This action checks if there is a connection between the specified source + and destination ports. If there is, it will check that any given properties + are also correct. + + No check is performed to ensure that the correct component is at that path; + for that, use the @ref CheckForRequiredCompAct action. + + This action will not fail if the specified component does not exist or is + incorrect. To cause an abort in these situations, use @ref + CheckForRequiredCompAct. + + ''' + def __init__(self, source, dest, id, props={}, callbacks=[]): + super(CheckForConnAct, self).__init__(callbacks=callbacks) + self._source = source + self._s_path = rtctree.path.parse_path(self._source[0])[0] + self._dest = dest + self._d_path = rtctree.path.parse_path(self._dest[0])[0] + self._id = id + self._props = props + + def __str__(self): + return self._action_string('Check for connection from {0}:{1} to ' \ + '{2}:{3} with properties {4}'.format(self._source[0], + self._source[1], self._dest[0], self._dest[1], + self._props)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print 'Checking for connection between {0}:{1} and ' \ + '{2}:{3}'.format(self._source[0], self._source[1], + self._dest[0], self._dest[1]) + # Get the source component + s_comp = rtctree.get_node(self._s_path) + if not s_comp or not s_comp.is_component: + return False, 'Source component missing: {0}'.format(\ + self._source[0]) + s_port = s_comp.get_port_by_name(self._source[1]) + if not s_port: + return False, 'Source port missing: {0}:{1}'.format(\ + self._source[0], self._source[1]) + # Get the destination component + d_comp = rtctree.get_node(self._d_path) + if not d_comp or not d_comp.is_component: + return False, 'Destination component missing: {0}'.format(\ + self._dest[0]) + d_port = d_comp.get_port_by_name(self._dest[1]) + if not d_port: + return False, 'Destination port missing: {0}:{1}'.format(\ + self._dest[0], self._dest[1]) + + conn = s_port.get_connection_by_id(self._id) + if not conn: + # No connection: fail + return False, 'No connection between {0}:{1} and {2}:{3}'.format( + self._source[0], self._source[1], self._dest[0], + self._dest[1]) + conn = d_port.get_connection_by_id(self._id) + if not conn: + # No connection: fail + return False, 'No connection between {0}:{1} and {2}:{3}'.format( + self._source[0], self._source[1], self._dest[0], + self._dest[1]) + # Check the properties + for k in self._props: + if self._props[k] != conn.properties[k]: + return False, 'Property {0} of connection from {1}:{2} to '\ + '{3}:{4} is incorrect.'.format(k, self._source[0], + self._source[1], self._dest[0], self._dest[1]) + + # All good + return True, None + + +############################################################################### +## Connect two ports + +class ConnectPortsAct(Action): + '''Connect two ports together. + + This action connects two ports together using the provided connection + profile. It will fail if either the components or the ports ports are not + present. No check is made to ensure the components at the specified paths + are the correct components. + + ''' + def __init__(self, source_path, source_port, dest_path, dest_port, + name, id, properties, callbacks=[]): + super(ConnectPortsAct, self).__init__(callbacks=callbacks) + self._source_path_str = source_path + self._source_path = rtctree.path.parse_path(source_path)[0] + self._source_port = source_port + self._dest_path_str = dest_path + self._dest_path = rtctree.path.parse_path(dest_path)[0] + self._dest_port = dest_port + self._name = name + self._id = id + self._properties = properties.copy() + + def __str__(self): + return self._action_string('Connect {0}:{1} to {2}:{3} with \ +ID {4} and properties {5}'.format(self._source_path_str, self._source_port, + self._dest_path_str, self._dest_port, self._id, + self._properties)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, 'Connect {0}:{1} to {2}:{3} with \ +ID {4} and properties {5}'.format(self._source_path_str, self._source_port, + self._dest_path_str, self._dest_port, self._id, + self._properties) + source_comp = rtctree.get_node(self._source_path) + if not source_comp or not source_comp.is_component: + return False, 'Source component missing: {0}'.format(\ + self._source_path_str) + s_port = source_comp.get_port_by_name(self._source_port) + if not s_port: + return False, 'Source port missing: {0}:{1}'.format(\ + self._source_path_str, self._source_port) + dest_comp = rtctree.get_node(self._dest_path) + if not dest_comp or not dest_comp.is_component: + return False, 'Destination component missing: {0}'.format(\ + self._dest_path_str) + d_port = dest_comp.get_port_by_name(self._dest_port) + if not d_port: + return False, 'Destination port missing: {0}:{1}'.format(\ + self._dest_path_str, self._dest_port) + + conn = s_port.get_connection_by_id(self._id) + if not conn: + if d_port.get_connection_by_id(self._id) is None: + # No existing connection + s_port.connect([d_port], name=self._name, id=self._id, + props=self._properties) + return True, None + else: + # The destination port has a connection with that ID but + # different ports. + return False, \ + 'Destination port has existing connection with ID {0}'.format( + self._id) + else: + if len(conn.ports) != 2 or not conn.has_port(d_port): + # The source port has a connection with that ID but different + # ports. + return False, \ + 'Source port has existing connection with ID {0}'.format( + self._id) + else: + # The connection already exists - check the properties match + for k in self._properties: + if self._properties[k] != conn.properties[k]: + return False, \ + 'Property {0} of existing connection from '\ + '{1}:{2} to {3}:{4} with ID {5} does not '\ + 'match'.format(k, self._source_path_str, + self._source_port, self._dest_path_str, + self._dest_port, self._id) + if option_store.OptionStore().verbose: + print >>sys.stderr, \ + 'Skipped existing connection with ID {0}'.format( + self._id) + return True, None + + +############################################################################### +## Disconnect two data ports + +class DisconnectPortsAct(Action): + '''Disconnect two ports. + + This action disconnects two ports. It will fail if either the components or + the ports ports are not present. No check is made to ensure the components + at the specified paths are the correct components. + + ''' + def __init__(self, source_path, source_port, dest_path, dest_port, id, + callbacks=[]): + super(DisconnectPortsAct, self).__init__(callbacks=callbacks) + self._source_path_str = source_path + self._source_path = rtctree.path.parse_path(source_path)[0] + self._source_port = source_port + self._dest_path_str = dest_path + self._dest_path = rtctree.path.parse_path(dest_path)[0] + self._dest_port = dest_port + self._id = id + + def __str__(self): + return self._action_string('Disconnect {0}:{1} from {2}:{3} with ID {4}'.format(\ + self._source_path_str, self._source_port, self._dest_path_str, + self._dest_port, self._id)) + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, \ + 'Disconnecting {0}:{1} from {2}:{3} with ID {4}'.format(\ + self._source_path_str, self._source_port, + self._dest_path_str, self._dest_port, self._id) + source_comp = rtctree.get_node(self._source_path) + if not source_comp or not source_comp.is_component: + return False, 'Source component missing: {0}'.format(\ + self._source_path_str) + source_port_obj = source_comp.get_port_by_name(self._source_port) + if not source_port_obj: + return False, 'Source port missing: {0}:{1}'.format(\ + self._source_path_str, self._source_port) + dest_comp = rtctree.get_node(self._dest_path) + if not dest_comp or not dest_comp.is_component: + return False, 'Destination component missing: {0}'.format(\ + self._dest_path_str) + dest_port_obj = dest_comp.get_port_by_name(self._dest_port) + if not dest_port_obj: + return False, 'Destination port missing: {0}:{1}'.format(\ + self._dest_path_str, self._dest_port) + + s_conn = source_port_obj.get_connection_by_id(self._id) + if not s_conn: + return False, 'No connection from {0}:{1} with ID {2}'.format( + self._source_path_str, self._source_port, self._id) + d_conn = dest_port_obj.get_connection_by_id(self._id) + if not d_conn: + return False, 'No connection to {0}:{1} with ID {2}'.format( + self._dest_path_str, self._dest_port, self._id) + s_conn.disconnect() + return True, None + + +############################################################################### +## State change base action + +class StateChangeAct(Action): + '''Base action for actions that change a component's state. + + Actions that inherit from this should provide three members: + - self._action_str: A string describing the action for use in str(). e.g. + "Activate". + - self._verbose_str: A similar string for use in the verbose output. e.g. + "Activating". + - self._action_impl: A function to be called by self._execute to perform + the action. It will be passed two arguments; the first is the component + node from rtctree, the second is the index of the execution context + involved. This should return (True, None) or False and an error string. + + ''' + def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]): + super(StateChangeAct, self).__init__(callbacks=callbacks) + self._path_str = path_str + self._comp_id = comp_id + self._instance_name = instance_name + self._path = rtctree.path.parse_path(path_str)[0] + self._ec_id = ec_id + + def __str__(self): + return self._action_string('{0} {1} in execution context {2}'.format(\ + self._action_str, self._path_str, self._ec_id)) + + @property + def comp_id(self): + '''Identification string of the component.''' + return self._comp_id + + @property + def ec_id(self): + '''Target execution context ID.''' + return self._ec_id + + @property + def instance_name(self): + '''Instance name of the target component.''' + return self._instance_name + + @property + def path(self): + '''Full path of the target component.''' + return self._path_str + + def _execute(self, rtctree): + if option_store.OptionStore().verbose: + print >>sys.stderr, '{0} {1} in {2}'.format(self._verbose_str, + self._path_str, self._ec_id) + comp = rtctree.get_node(self._path) + if not comp or not comp.is_component: + return False, 'Component missing: {0}'.format(self._path_str) + ec_index = comp.get_ec_index(int(self._ec_id)) + if ec_index < 0: + return False, 'Invalid execution context: {0}'.format(self._ec_id) + return self._action_impl(comp, ec_index) + + +############################################################################### +## Check component state + +class CheckCompStateAct(StateChangeAct): + '''Check component state in an execution context. + + This action checks that the state of an execution context is as expected. + + ''' + def __init__(self, path_str, comp_id, instance_name, ec_id, expected, + callbacks=[]): + super(CheckCompStateAct, self).__init__(path_str, comp_id, + instance_name, ec_id, callbacks=callbacks) + self._expected = expected + self._action_str = 'Check state is {0} for'.format(self._expected) + self._verbose_str = 'Checking state is {0} for'.format(self._expected) + + def _action_impl(self, comp, ec_index): + if (self._expected.lower() == 'active' and \ + comp.state_in_ec(ec_index) == comp.ACTIVE) or \ + (self._expected.lower() == 'inactive' and \ + comp.state_in_ec(ec_index) == comp.INACTIVE) or \ + (self._expected.lower() == 'error' and \ + comp.state_in_ec(ec_index) == comp.ERROR) or \ + (self._expected.lower() == 'created' and \ + comp.state_in_ec(ec_index) == comp.CREATED) or \ + (self._expected.lower() == 'unknown' and \ + comp.state_in_ec(ec_index) == comp.UNKNOWN): + return True, None + return False, 'Component {0} is in incorrect state {1}'.format( + self._path_str, + comp.get_state_in_ec_string(ec_index, add_colour=False)) + + +############################################################################### +## Activate a component + +class ActivateCompAct(StateChangeAct): + '''Activate a component. + + This action changes the status of a component to active. + + ''' + def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]): + super(ActivateCompAct, self).__init__(path_str, comp_id, instance_name, + ec_id, callbacks=callbacks) + self._action_str = 'Activate' + self._verbose_str = 'Activating' + + def _action_impl(self, comp, ec_index): + comp.activate_in_ec(ec_index) + return True, None + + +############################################################################### +## Deactivate a component + +class DeactivateCompAct(StateChangeAct): + '''Deactivate a component. + + This action changes the status of a component to inactive. + + ''' + def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]): + super(DeactivateCompAct, self).__init__(path_str, comp_id, + instance_name, ec_id, callbacks=callbacks) + self._action_str = 'Deactivate' + self._verbose_str = 'Deactivating' + + def _action_impl(self, comp, ec_index): + comp.deactivate_in_ec(ec_index) + return True, None + + +############################################################################### +## Reset a component + +class ResetCompAct(StateChangeAct): + '''Reset a component. + + This action changes the status of a component to inactive from error. + + ''' + def __init__(self, path_str, comp_id, instance_name, ec_id, callbacks=[]): + super(ResetCompAct, self).__init__(path_str, comp_id, instance_name, + ec_id, callbacks=callbacks) + self._action_str = 'Reset' + self._verbose_str = 'Resetting' + + def _action_impl(self, comp, ec_index): + comp.reset_in_ec(ec_index) + return True, None + + +# vim: tw=79 + diff --git a/rtshell/comp_mgmt.py b/rtshell/comp_mgmt.py new file mode 100644 index 0000000..8a2bb9d --- /dev/null +++ b/rtshell/comp_mgmt.py @@ -0,0 +1,194 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Functions for component management. + +''' + + +import OpenRTM_aist +import re +import RTC +import rtctree.tree +import rtctree.utils +import sys + +import gen_comp +import rts_exceptions + + +def find_comp_in_mgr(name, mgr): + '''Find a component in a manager. + + @param name The type name of the component to search for. + @param mgr The manager to which the component is registered. + + ''' + for c in mgr.getComponents(): + if c.getTypeName() == name: + return c + raise rts_exceptions.MissingCompError(name) + + +def get_comp(rtc, tree=None, orb=None): + '''Get a rtctree.Component object from an rtctree.RTCTree. + + Get the component object by searching the RTCTree for the specified RTC. + + @param rtc Path to the component. This should be in + the format used by rtctree, i.e. a list of path entries, with + the first being a /. e.g. ['/', 'localhost', 'comp0.rtc']. + @param tree An already-populated rtctree.RTCTree object, or None if one + should be created. + @param orb An ORB to use if the tree must be created, or None to make one. + + ''' + if not tree: + tree = rtctree.tree.RTCTree(paths=rtc, orb=orb, filter=[rtc]) + + if not tree.has_path(rtc): + raise rts_exceptions.NoSuchObjectError(rtc) + comp = tree.get_node(rtc) + if not comp.is_component: + raise rts_exceptions.NotAComponentError(rtc) + return comp + + +def find_port(rtc, port, tree=None, orb=None): + '''Get a rtctree.Port object from an rtctree.RTCTree. + + Get the port object by searching the RTCTree for the specified RTC, then + looking for the specified port on that component. + + @param rtc Path to the component that should have a port. This should be in + the format used by rtctree, i.e. a list of path entries, with + the first being a /. e.g. ['/', 'localhost', 'comp0.rtc']. + @param port Name of the port. + @param tree An already-populated rtctree.RTCTree object, or None if one + should be created. + @param orb An ORB to use if the tree must be created, or None to make one. + + ''' + comp = get_comp(rtc, tree=tree, orb=orb) + port_obj = comp.get_port_by_name(port) + if not port_obj: + raise rts_exceptions.PortNotFoundError(rtc, port) + return port_obj + + +def choose_name(base, tree): + '''Choose a name for the component from a given base. + + The name is chosen such that it does not conflict with other possible + instances of the base name by appending an index number. + + @param base The base name to append the index to. + @param tree A populated RTCTree to search for other instances of the + same type of component. + + ''' + def get_result(node, args): + return int(regex.match(node.name).group(1)) + def is_gen_comp(node): + if regex.match(node.name): + return True + return False + regex = re.compile('{0}(\d+)0.rtc'.format(base)) + matches = tree.iterate(get_result, filter=['is_component', is_gen_comp]) + if not matches: + return base + '0' + matches.sort() + return base + '{0}'.format(matches[-1] + 1) + + +def make_comp(name_base, tree, cons, port_specs, event=None, rate=1.0, + max=-1, **kwargs): + name = choose_name(name_base, tree) + mgr = OpenRTM_aist.Manager.init(1, [sys.argv[0]]) + mgr.setModuleInitProc(gen_comp.make_init(name, cons, port_specs, + event=event, rate=rate, max=max, **kwargs)) + mgr.activateManager() + mgr.runManager(True) + return name, mgr + + +def delete_comp(mgr, comp): + '''Delete the component from the manager.''' + mgr.deleteComponent(comp=comp) + + +def shutdown(mgr): + '''Shut down the manager.''' + mgr.shutdown() + mgr.join() + + +def connect(comp, port_specs, tree): + def find_local_port(name, ports): + for p in ports: + if p.get_port_profile().name.split('.')[-1] == name: + return p + raise rts_exceptions.PortNotFoundError(comp.getTypeName(), name) + + props = {'dataport.dataflow_type':'push', + 'dataport.interface_type':'corba_cdr', + 'dataport.subscription_type':'flush'} + ports = comp.get_ports() + conns = [] + for p in port_specs: + local_port = find_local_port(p.name, ports) + for t in p.targets: + dest_port = find_port(t[0], t[1], tree) + props['dataport.data_type'] = \ + dest_port.properties['dataport.data_type'] + prof = RTC.ConnectorProfile(p.name + '_' + t[1], + '', [local_port, dest_port.object], + rtctree.utils.dict_to_nvlist(props)) + res, connector = local_port.connect(prof) + if res != RTC.RTC_OK: + raise rts_exceptions.ConnectFailedError(t[0], t[1]) + conns.append(connector) + return conns + + +def disconnect(comp): + '''Disconnect all connections to @ref comp. + + @param comp An RTObject. + + ''' + ports = comp.get_ports() + for p in ports: + p.disconnect_all() + + +def activate(comp): + for ec in comp.get_owned_contexts(): + if ec.activate_component(comp.getObjRef()) != RTC.RTC_OK: + raise rts_exceptions.ActivateError(comp.getTypeName()) + for ec in comp.get_participating_contexts(): + if ec.activate_component(comp.getObjRef()) != RTC.RTC_OK: + raise rts_exceptions.ActivateError(comp.getTypeName()) + + +def deactivate(comp): + for ec in comp.get_owned_contexts(): + if ec.deactivate_component(comp.getObjRef()) != RTC.RTC_OK: + raise rts_exceptions.DeactivateError(comp.getTypeName()) + for ec in comp.get_participating_contexts(): + if ec.deactivate_component(comp.getObjRef()) != RTC.RTC_OK: + raise rts_exceptions.DeactivateError(comp.getTypeName()) + diff --git a/rtshell/fmt.py b/rtshell/fmt.py new file mode 100644 index 0000000..55f941b --- /dev/null +++ b/rtshell/fmt.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Built-in formatters for rtprint. + +''' + +import inspect +import rts_exceptions + + +############################################################################### +## Python source formatter + +def rawpy(data): + return data.__repr__() + + +############################################################################### +## Formatter importer + +def import_formatter(form, modmgr): + '''Import a formatter. + + This function attempts to evaluate an expression specifying a function + object that can be used to format a piece of data. The imported function + must receive one positional argument, which is the data to format. + + @param form The formatter expression. + @param modmgr The module manager to use to evaluate @ref form. + + ''' + # Special case for internal formatters: replace 'rtshell' with 'fmt' + form_rpl = form + if form.startswith('rtshell.'): + form_rpl = 'fmt.' + form[8:] + try: + form_fun = modmgr.evaluate(form_rpl) + except Exception, e: + raise rts_exceptions.ImportFormatterError(e) + # Check if the formatter is a function + if type(form_fun) != type(import_formatter): + raise rts_exceptions.BadFormatterError(form) + args, varargs, varkw, defaults = inspect.getargspec(form_fun) + if len(args) != 1 or varargs or varkw or defaults: + raise BadFormatterError(form) + return form_fun + diff --git a/rtshell/gen_comp.py b/rtshell/gen_comp.py new file mode 100644 index 0000000..164ebf4 --- /dev/null +++ b/rtshell/gen_comp.py @@ -0,0 +1,219 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Base class for generated-on-demand components. + +''' + + +import inspect +import OpenRTM_aist +import RTC +import sys +import traceback + + +############################################################################### +## Port class + +class Port(object): + '''Class to store the objects used for a port.''' + def __init__(self, data, port, formatter=None, raw_spec=None, *args, + **kwargs): + super(Port, self).__init__() + self._data = data + self._port = port + self._formatter = formatter + self._raw = raw_spec + members = [m for m in dir(self.data) if not m.startswith('_')] + if len(members) == 2 and 'tm' in members and \ + 'data' in members and self.data.tm.__class__ == RTC.Time: + self._standard_type = True + else: + self._standard_type = False + + @property + def data(self): + '''Get the port's data reference.''' + return self._data + + @property + def port(self): + '''Get the port object.''' + return self._port + + @property + def formatter(self): + '''Get the formatter function for the port, if any.''' + return self._formatter + + @property + def name(self): + '''Get the port's name.''' + return self._port.getName() + + @property + def raw(self): + '''Get the raw port spec for this port, if any.''' + return self._raw + + @property + def standard_type(self): + '''Check if the port's data type is an RTC standard type. + + RTC standard types have a tm member (the timestamp) and a data member + (the data). + + ''' + return self._standard_type + + def read(self): + '''Read the next value from the port into self.data.''' + self._data = self._port.read() + + def format(self): + '''Return a string representation of the value of self.data. + + If self.formatter is not None, that function will be called to create + the string representation. Otherwise, str() will be used except in the + cases of data that contains a .tm member of type RTC.Time and a .data + member. In that case, the time will be pretty-printed, followed by the + data member, printed using str(). + + ''' + if self.formatter: + return self.formatter(self.data) + else: + members = [m for m in dir(self.data) if not m.startswith('_')] + if len(members) == 2 and 'tm' in members and \ + 'data' in members and self.data.tm.__class__ == RTC.Time: + return '[{0}.{1:09}] {2}'.format(self.data.tm.sec, + self.data.tm.nsec, self.data.data) + else: + return str(self.data) + + +############################################################################### +## Generated-on-demand component class + +class GenComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, mgr, port_specs, event=None, max=-1, *args, **kwargs): + '''Constructor. + + @param mgr Reference to the manager that created this component. + @param port_spec The port layout of the component. This must be + a list of port_types.PortSpec objects. + @param event An event object that can be .set() to indicate + that the component has finished its assigned task + and should be shut down. + @param max The maximum number of times this component should + perform its onExecute function before setting the + event to request a shutdown. Defaults to -1, for + unlimited. + + ''' + OpenRTM_aist.DataFlowComponentBase.__init__(self, mgr) + self._port_specs = port_specs + self._event = event + self._max = max + self._count = 0 + + def onInitialize(self): + try: + self._ports = {} + for p in self._port_specs: + args, varargs, varkw, defaults = \ + inspect.getargspec(p.type.__init__) + if defaults: + init_args = tuple([None \ + for ii in range(len(args) - len(defaults) - 1)]) + else: + init_args = [None for ii in range(len(args) - 1)] + if p.input: + port_con = OpenRTM_aist.InPort + port_reg = self.registerInPort + else: + port_con = OpenRTM_aist.OutPort + port_reg = self.registerOutPort + p_data = p.type(*init_args) + p_port = port_con(p.name, p_data) + port_reg(p.name, p_port) + self._ports[p.name] = Port(p_data, p_port, + formatter=p.formatter, raw_spec=p) + except: + print >>sys.stderr, traceback.format_exc() + return RTC.RTC_ERROR + return RTC.RTC_OK + + def onExecute(self, ec_id): + # Call the component behaviour + res = RTC.RTC_OK + if self._count < self._max or self._max < 0: + res, executed = self._behv(ec_id) + if executed > 0: + self._count += executed + if self._max > -1 and self._count >= self._max: + self._set() + return res + + def _behv(self, ec_id): + '''Behaviour function for derived components. + + Deriving classes must implement this function. It will be called by + onExecute. It must return a tuple of (RTC result code, _behv result + value). The RTC result code is used to create the result of onExecute; + if no errors occur, it must be RTC.RTC_OK. The _behv result code is + used to tell the component if the behaviour was able to execute + (whether it succeeded or not), for the purposes of execution counting. + It should be the number of iterations executed. + + ''' + pass + + def _set(self): + '''Call set() on the event object to notify waiters.''' + if self._event: + self._event.set() + + +def make_factory(cons, port_specs, event=None, max=-1, **kwargs): + def fact_fun(mgr): + return cons(mgr, port_specs, event=event, max=max, **kwargs) + return fact_fun + + +def make_init(name, cons, port_specs, event=None, rate=1.0, max=-1, **kwargs): + def init_fun(mgr): + spec= ['implementation_id', name, + 'type_name', name, + 'description', 'rtshell generated-on-demand component.', + 'version', '3.0', + 'vendor', 'rtshell', + 'category', 'Generated', + 'activity_type', 'DataFlowComponent', + 'max_instance', '1', + 'language', 'Python', + 'lang_type', 'SCRIPT', + ''] + profile = OpenRTM_aist.Properties(defaults_str=spec) + mgr.registerFactory(profile, + make_factory(cons, port_specs, event=event, max=max, **kwargs), + OpenRTM_aist.Delete) + comp = mgr.createComponent(name + + '?exec_cxt.periodic.type=PeriodicExecutionContext&' + 'exec_cxt.periodic.rate={0}'.format(rate)) + return init_fun + diff --git a/rtshell/ilog.py b/rtshell/ilog.py new file mode 100644 index 0000000..df16c61 --- /dev/null +++ b/rtshell/ilog.py @@ -0,0 +1,365 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Log interface. + +''' + + +import sys + + +############################################################################### +## Log exceptions. + +class EndOfLogError(EOFError): + '''The end of the log has been reached while reading.''' + pass + + +class InvalidIndexError(EOFError): + '''An invalid index was requested.''' + pass + + +############################################################################### +## Entry timestamps + +class EntryTS(object): + def __init__(self, sec=0, nsec=0, time=None): + super(EntryTS, self).__init__() + if time is not None: + self._sec, self._nsec = self._get_values(time) + else: + self._sec = sec + self._nsec = nsec + + def __repr__(self): + return 'EntryTS(_sec={0}, _nsec={1})'.format(self._sec, self._nsec) + + def __str__(self): + return '{0}.{1:09}'.format(self._sec, self._nsec) + + def __lt__(self, other): + sec, nsec = self._get_values(other) + if self._sec < sec: + return True + elif self._sec == sec: + if self._nsec < nsec: + return True + return False + + def __le__(self, other): + sec, nsec = self._get_values(other) + if self._sec < sec: + return True + elif self._sec == sec: + if self._nsec <= nsec: + return True + return False + + def __eq__(self, other): + sec, nsec = self._get_values(other) + if self._sec == sec and self._nsec == nsec: + return True + return False + + def __ne__(self, other): + sec, nsec = self._get_values(other) + if self._sec != sec or self._nsec != nsec: + return True + return False + + def __gt__(self, other): + sec, nsec = self._get_values(other) + if self._sec > sec: + return True + elif self._sec == sec: + if self._nsec > nsec: + return True + return False + + def __ge__(self, other): + sec, nsec = self._get_values(other) + if self._sec > sec: + return True + elif self._sec == sec: + if self._nsec >= nsec: + return True + return False + + @property + def float(self): + '''Get the time value as a float.''' + return float(self._sec) + float(self._nsec) / 1e9 + + @property + def sec(self): + return self._sec + + @sec.setter + def sec(self, sec): + self._sec = sec + + @property + def nsec(self): + return self._nsec + + @nsec.setter + def nsec(self, nsec): + self._nsec = nsec + + def _get_values(self, other): + if type(other) == EntryTS: + return other.sec, other.nsec + else: + return int(other), int((other * 1000000000) % 1000000000) + + +############################################################################### +## Log interface. All loggers must conform to this. + +class Log(object): + def __init__(self, mode='r', meta=None, verbose=False, *args, **kwargs): + '''Base constructor. + + The log will be opened on construction. It should be closed manually, + as Python does not guarantee that __del__() will be called. + + @param mode Permissions. Specificy 'r' for read, 'w' for write or 'rw' + for read/write. Not all logs support all permissions. + Read/write permissions are particularly uncommon. + @param meta A block of data to write into the log. Implementations + are free to deal with this any way they wish, as long as it + can be retrieved in read mode. However, there is no + requirement that it can be changed after opening the log + for writing. Users should set it before opening the log. + @param verbose Print verbose output to stderr. + + ''' + super(Log, self).__init__() + self._mode = mode + self._meta = meta + self._vb = verbose + self.open() + + def __del__(self): + self.close() + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + if exc_type == None: + self.close(finalise=True) + else: + self.close(finalise=False) + return False + + def __iter__(self): + return self + + def next(self): + d = self.read() + if not d: + raise StopIteration + return d[0] + + def __str__(self): + return 'Log interface object.' + + @property + def end(self): + '''The position of the final entry in the log. + + A tuple of (index, timestamp). + + ''' + return self._get_end() + + @property + def eof(self): + '''True if the log has reached the end.''' + return self._eof() + + @property + def metadata(self): + '''Return the metadata from the log (if any).''' + return self._meta + + @metadata.setter + def metadata(self, metadata): + self._meta = metadata + + @property + def mode(self): + '''The mode of the log.''' + return self._mode + + @property + def name(self): + '''The name of the log.''' + return self._name + + @property + def pos(self): + '''The current position in the log. + + A tuple of (index, timestamp). + + This points at the current position - i.e. the entry most recently + read. + + ''' + return self._get_cur_pos() + + @property + def start(self): + '''The position of the first entry in the log. + + A tuple of (index, timestamp). + + ''' + return self._get_start() + + def open(self): + '''Opens the log.''' + self._open() + + def finalise(self): + '''Prepare the log to be closed. + + Any cleaning up that needs to be done before closing the log should + be done here. + + This function is called just before closing the log by @ref close. + If using the context manager statement (the 'with' statement), it will + be called automatically, unless an exception has occured. + + It is not required for objects implementing the Log interface to + implement this function. + + ''' + self._finalise() + + def close(self, finalise=True): + '''Closes the log. + + @param finalise Whether the log should be finalised before closing. + Defaults to True. + + ''' + if finalise: + self.finalise() + self._close() + + def write(self, timestamp, data): + '''Writes an entry to the log. + + The timestamp is necessary to allow reading back data at the + same rate as it was recorded. It must be an object that + supports comparisons using <, <=, =, >= and >. ilog.EntryTS + provides a suitable object. + + ''' + raise NotImplementedError + + def read(self, timestamp=None, number=None): + '''Read entries from the log. + + If a time limit is given, all entries until that time limit is + reached will be read. + + If a number is given, that number of entries will be returned. + This option overrides the time limit option. + + If EOF is hit before the requested entries are read, what was + read will be returned and @ref eof will return True. + + If neither option is given, the next value will be returned. + + Returns a list of tuples, [(index, timestamp, data), ...]. + + ''' + raise NotImplementedError + + def rewind(self): + '''Rewind the log to the first entry.''' + raise NotImplementedError + + def seek(self, timestamp=None, index=None): + '''Rewind or fast-forward the log. + + If the timestamp or index is earlier than the current position, the log + will be rewound. If it is later, the log will be fast-forwarded. + + When the log is rewound, it will go back to the first entry before + the given timestamp or index. If an entry exactly matches the given + timestamp or index, the log position will be at that entry, meaning + that the next value read will be that entry. + + When a log is fast-forwarded, it will go to the first entry after the + given timestamp or index. If an entry exactly matches the given + timestamp or index, the log position will be at that entry, meaning + that the next value read will be that entry. + + ''' + raise NotImplementedError + + def _close(self): + raise NotImplementedError + + def _eof(self): + return True + + def _finalise(self): + pass + + def _get_cur_pos(self): + '''Get the current position in the log. + + Should be implemented by implementation objects. Called by the + @ref position property. + + ''' + raise NotImplementedError + + def _get_start(self): + '''Get the position of the first entry in the log. + + Should be implemented by implementation objects. Called by the + @ref start property. + + ''' + raise NotImplementedError + + def _get_end(self): + '''Get the position of the last entry in the log. + + Should be implemented by implementation objects. Called by the + @ref end property. + + ''' + raise NotImplementedError + + def _open(self): + raise NotImplementedError + + def _vb_print(self, string): + '''Print verbose information when self._vb is True.''' + if self._vb: + print >>sys.stderr, string + diff --git a/rtshell/modmgr.py b/rtshell/modmgr.py new file mode 100644 index 0000000..5c440a4 --- /dev/null +++ b/rtshell/modmgr.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Objects for managing dynamically-loaded modules and evaluating strings. + +''' + + +import imp +import inspect +import OpenRTM_aist +import os.path +import re +import RTC +import sys +import time + +import rts_exceptions + + +############################################################################### +## Module class - stores a dynamically imported module. + +class Module(object): + def __init__(self, name, mod=None, *args, **kwargs): + super(Module, self).__init__() + self._name = name + self._mod = mod + + def __str__(self): + return '{0}: {1}'.format(self._name, self._mod) + + @property + def name(self): + '''The name of the module, as it would be called in source.''' + return self._name + + @property + def mod(self): + '''The module object.''' + return self._mod + + def _load_mod(self): + '''Loads the module object.''' + f = None + try: + f, p, d = imp.find_module(self._name) + self._mod = imp.load_module(self._name, f, p, d) + finally: + if f: + f.close() + + +class AutoModule(Module): + def __init__(self, name, *args, **kwargs): + super(AutoModule, self).__init__(name, *args, **kwargs) + self._load_mod() + + +############################################################################### +## ModuleMgr class - keeps track of loaded extra modules and provides +## evaluation of Python expressions + +class ModuleMgr(object): + def __init__(self, verbose=False, paths=[], *args, **kwargs): + super(ModuleMgr, self).__init__() + self._mods = {'RTC': Module('RTC', mod=RTC)} + self._verb = verbose + self._add_paths(paths) + + def _add_paths(self, paths=[]): + for p in paths: + if self._verb: + print >>sys.stderr, 'Adding {0} to PYTHONPATH'.format(p) + sys.path.insert(0, p) + + def evaluate(self, expr): + self._auto_import(expr) + repl_expr = self._repl_mod_name(_replace_time(expr)) + if not repl_expr: + raise rts_exceptions.EmptyConstExprError + if self._verb: + print >>sys.stderr, 'Evaluating expression {0}'.format(repl_expr) + const = eval(repl_expr) + return const + + def find_class(self, name): + '''Find a class constructor in one of the modules. + + The first matching class's constructor will be returned. + + @param name The name of the class to search for. + + ''' + # Replace / in the name with . to create a Python path + name = name.replace('/', '.') + self._auto_import(name) + # Strip the name down to the class + name = _find_object_name(name) + for m in self._mods.values(): + if m.name == 'RTC': + # Search RTC last to allow user types to override RTC types + continue + types = [member for member in inspect.getmembers(m.mod, + inspect.isclass) if member[0] == name or "IDL:"+self._mods.keys()[0]+"/"+member[0]+":1.0" == name] + if len(types) == 0: + continue + elif len(types) != 1: + raise rts_exceptions.AmbiguousTypeError(type_name) + else: + # Check for the POA module + if m.name != 'RTC': + if not [other_m for other_m in self._mods.values() \ + if other_m.name == m.name + '__POA']: + raise rts_exceptions.MissingPOAError(m.name) + if self._verb: + print >>sys.stderr, 'Found type {0} in module {1}'.format( + name, m.name) + return types[0][1] + # If got to here, the type was not found in any other module, so search + # the RTC module + m = self._mods['RTC'] + types = [member for member in inspect.getmembers(m.mod, + inspect.isclass) if member[0] == name] + if len(types) != 0: + if len(types) != 1: + raise rts_exceptions.AmbiguousTypeError(type_name) + if self._verb: + print >>sys.stderr, 'Found type {0} in module {1}'.format( + name, m.name) + return types[0][1] + raise rts_exceptions.TypeNotFoundError(name) + + def load_mod(self, mod): + '''Load a module.''' + m = AutoModule(mod) + self._mods[mod] = m + + def load_mods(self, mods): + '''Load a list of modules. + + @param mods The module names, as a list of strings. + + ''' + [self.load_mod(m) for m in mods] + + def load_mods_and_poas(self, mods): + '''Load a set of modules and their POA modules. + + @param mods The module names, as a list of strings. + + ''' + for m in mods: + self.load_mod(m) + try: + self.load_mod(m + '__POA') + except ImportError: + print >>sys.stderr, '{0}: Failed to import module {1}'.format(\ + os.path.basename(sys.argv[0]), m + '__POA') + pass + + @property + def loaded_mod_names(self): + return self._mods.keys() + + def _auto_import(self, expr): + '''Tries to import all module names found in an expression. + + A failure to import a module will cause a warning, not an error. + + ''' + names = [m for m in _find_module_names(expr) if m not in self._mods] + if self._verb: + print >>sys.stderr, 'Automatically importing modules {0}'.format( + names) + for n in names: + try: + self.load_mod(n) + except ImportError: + print >>sys.stderr, \ + '{0}: Warning: failed to import module {1}'.format( + os.path.basename(sys.argv[0]), n) + continue + try: + self.load_mod(n + '__POA') + except ImportError: + print >>sys.stderr, \ + '{0}: Warning: failed to import module {1}'.format( + os.path.basename(sys.argv[0]), n + '__POA') + continue + + def _repl_mod_name(self, expr): + '''Replace the name of a module. + + Replaces a reference to a module in a string with its reference in + the modules array. + + ''' + for m in self._mods: + if m in expr: + expr = expr.replace(m, 'self._mods["{0}"].mod'.format(m)) + return expr + + +############################################################################### +## Internal support functions + +def _replace_time(expr): + '''Replaces any occurances with {time} with the system time.''' + now = time.time() + sys_time = RTC.Time(int(now), int((now - int(now)) * 1e9)) + return expr.format(time=sys_time) + + +def _find_module_names(expr): + '''Finds all potential module names in an expression.''' + return [x[:-1] for x in re.findall(r'(?P[a-zA-Z][\w.]*\.)+[a-zA-Z]', + expr)] + + +def _find_object_name(expr): + '''Finds the object at the end of a module...module.object line.''' + return expr[expr.rfind('.') + 1:] + diff --git a/rtshell/option_store.py b/rtshell/option_store.py new file mode 100644 index 0000000..047ec66 --- /dev/null +++ b/rtshell/option_store.py @@ -0,0 +1,31 @@ +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Singleton containing option values. + +''' + + +import sys + +class OptionStore(object): + def __new__(cls, *p, **k): + if not '_the_instance' in cls.__dict__: + cls._the_instance = object.__new__(cls) + return cls._the_instance + + +# vim: tw=79 + diff --git a/rtshell/path.py b/rtshell/path.py new file mode 100644 index 0000000..e1ba6c0 --- /dev/null +++ b/rtshell/path.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Functions for dealing with input paths. + +''' + + +import os + + +ENV_VAR='RTCSH_CWD' + + +def cmd_path_to_full_path(cmd_path): + '''Given a path from the user, returns a suitable full path based on the + value of the environment variable specified in ENV_VAR. + + ''' + if cmd_path.startswith('/'): + return cmd_path + if ENV_VAR in os.environ and os.environ[ENV_VAR]: + if os.environ[ENV_VAR].endswith('/') or cmd_path.startswith('/'): + return os.environ[ENV_VAR] + cmd_path + else: + return os.environ[ENV_VAR] + '/' + cmd_path + # If ENV_VAR is not set, assume the current working dir is the root dir + return '/' + cmd_path + + +# vim: tw=79 + diff --git a/rtshell/plan.py b/rtshell/plan.py new file mode 100644 index 0000000..8be5b9d --- /dev/null +++ b/rtshell/plan.py @@ -0,0 +1,643 @@ +# -*- Python -*- # -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Creation and execution of state change plans. + +''' + + +import operator +import os +import rtctree.path +import rtsprofile.message_sending +import sys +import thread +import threading +import time +import traceback +import types + +import rts_exceptions + + +class Counter: + def __init__(self): + self._counter = 1 + + @property + def value(self): + self._counter += 1 + return self._counter - 1 +ider = Counter() + + +############################################################################### +## Action executor objects + +class ActionExecutor(threading.Thread): + '''An object for managing execution of an action. + + This object is capable of executing an action immediately when it is + called, or delaying execution until a set of conditions is reached. Which + should occur is chosen automatically. If execution needs to be delayed, a + new thread will be started to manage it. This thread will sleep until all + pre-conditions for the action are met. Any number of condition objects can + be added. + + Callbacks can be added to be executed after executing the action. + + ''' + def __init__(self, action=None, owner_flag=None, *args, **kwargs): + super(ActionExecutor, self).__init__(*args, **kwargs) + self._action = action + self._callbacks = [] + self._conditions = [] + self._cancelled = False + self._cancel_lock = threading.Lock() + self._error = None + self._err_lock = threading.Lock() + self._flag = threading.Event() + self._completed = False + self._completed_lock = threading.Lock() + self._id = ider.value + self._owner_flag = owner_flag + + def __str__(self): + result = self.id_string + ' ' + if self._conditions: + result += '[{0}'.format(self._conditions[0]) + for c in self._conditions[1:]: + result += ', {0}'.format(c) + result += '] ' + return result + str(self._action) + + def __call__(self, *args, **kwargs): + self._args = args + self._kwargs = kwargs + if self.immediate: + self._execute_action() + else: + self._start_conds() + self.start() + + def add_callback(self, callback): + '''Add a new callback to be executed after the action.''' + self._callbacks.append(callback) + + def add_condition(self, condition): + '''Add a new condition on the action's execution.''' + self._conditions.append(condition) + + def cancel(self): + '''Cancel this action.''' + with self._cancel_lock: + self._cancelled = True + self.set() + + def set(self): + '''Notify this action executor that a condition may have been met.''' + self._flag.set() + + def wait_for_exit(self): + '''Wait for this action executor to exit.''' + if self.immediate: + # If this executor is immediate, it won't have a thread. + return + self.join() + + @property + def action(self): + '''The action object that will be executed.''' + return self._action + + @action.setter + def action(self, action): + self._action = action + + @property + def complete(self): + '''Has this action completed yet?''' + with self._completed_lock: + return self._completed + + @property + def error(self): + '''Any error that has occurred in this executor or one of its + conditions.''' + with self._err_lock: + return self._error + + @property + def id(self): + '''ID of this action.''' + return self._id + + @property + def id_string(self): + '''ID of this action as a string.''' + return '{' + '{0}'.format(self._id) + '}' + + @property + def immediate(self): + '''Tests if this executor can execute immediately. + + If this executor has any conditions that are not immediate, the + executor itself is not immediate. + + ''' + for c in self._conditions: + if not c.immediate: + return False + return True + + @property + def sort_order(self): + '''The integer order for this action in plans. + + Generally, all actions will have a sequence number. For those that + don't, this property will be negative. Actions should be executed in + the order of their sequence number, from smaller to bigger. + + ''' + if not self._conditions: + return -1 + return min([c.sequence for c in self._conditions]) + + def run(self): + cons_satisfied = False + if not self._conditions: + # All conditions have been met + cons_satisfied = True + while not cons_satisfied: + for c in self._conditions: + if c.error: + # Propagate the error upwards + self._error = c.error + if self._owner_flag: + self._owner_flag.set() + return + self._flag.wait() + self._flag.clear() + with self._cancel_lock: + if self._cancelled: + self._cancel_conditions() + return + self._reduce_conds() + if not self._conditions: + # All conditions have been met + cons_satisfied = True + self._execute_action() + if self._owner_flag: + self._owner_flag.set() + with self._completed_lock: + self._completed = True + + def _cancel_conditions(self): + for c in self._conditions: + c.cancel() + for c in self._conditions: + c.wait_for_exit() + + def _do_callbacks(self): + for c in self._callbacks: + c(*self._args, **self._kwargs) + + def _execute_action(self): + print >>sys.stderr, 'Executing {0} {1}'.format(self.id_string, + self._action) + self._action(*self._args, **self._kwargs) + self._do_callbacks() + + def _reduce_conds(self): + result = [] + for c in self._conditions: + if c.satisfied: + c.wait_for_exit() + else: + result.append(c) + continue + self._conditions = result + + def _start_conds(self): + for c in self._conditions: + if not c.immediate: + c.set_args(*self._args, **self._kwargs) + c.start() + + +############################################################################### +## Condition objects + +class BasicCondition(object): + '''A simple condition specifying just a sequence ordering. + + This condition is immediate. + + All other condition types should inherit from this type, and must implement + the @ref start method. + + ''' + def __init__(self, executor=None, sequence=-1, desc='', *args, **kwargs): + super(BasicCondition, self).__init__() + self._executor = executor + self._sequence = sequence + self._desc = desc + self._error = None + self._err_lock = threading.Lock() + self._immediate = True + self._satisfied = True + self._sat_lock = threading.Lock() + + def __str__(self): + return 'Order {0}'.format(self._sequence) + + def cancel(self): + return + + def set_args(self, *args, **kwargs): + self._args = args + self._kwargs = kwargs + + def start(self): + return + + def wait_for_exit(self): + '''Wait for this condition's thread to exit.''' + # Nothing to join in an immediate condition + return + + @property + def error(self): + '''Any error that has occurred in this condition.''' + with self._err_lock: + return self._error + + @property + def immediate(self): + '''Will this condition be satisfied immediately?''' + return self._immediate + + @property + def satisfied(self): + '''Is this condition satisfied?''' + with self._sat_lock: + return self._satisfied + + @property + def sequence(self): + '''The sequence order of this condition.''' + return self._sequence + + +class SleepCondition(BasicCondition): + '''A condition that waits for a period of time before being satisfied. + + This condition is delayed. + + This condition is essentially a sleep. It starts a threaded timer, which + sleeps for the given period of time (in ms) before waking up and setting + the condition to satisfied. + + ''' + def __init__(self, wait_time=0, *args, **kwargs): + super(SleepCondition, self).__init__(wait_time=wait_time, *args, **kwargs) + self._wait_time_ms = wait_time + self._wait_time = wait_time / 1000.0 + self._immediate = False + self._satisfied = False + self._timer = None + + def __str__(self): + return super(SleepCondition, self).__str__() + \ + '/Wait {0}ms'.format(self._wait_time_ms) + + def cancel(self): + self._timer.cancel() + self._timer.join() + + def satisfy(self): + with self._sat_lock: + self._satisfied = True + self._executor.set() + + def start(self): + self._timer = threading.Timer(self._wait_time, self.satisfy) + self._timer.start() + + +class DelayedCondition(BasicCondition, threading.Thread): + '''Base class for delayed conditions. + + Inheriting condition objects should implement the @ref check method, + returning True or False appropriately. + + Delayed conditions start a separate thread, which they use to perform their + condition check at an appropriate time. They use the reference to their + owner to signal it that the condition has been met. If their condition is + not met within an optional timeout (specified in ms), @ref + PrecedingTimeoutError is set. Set the timeout to None for no timeout. + + Once a delayed condition is satisfied, you should ensure its thread has + completed by calling @ref wait_for_exit. + + ''' + def __init__(self, timeout=None, *args, **kwargs): + super(DelayedCondition, self).__init__(timeout=timeout, *args, **kwargs) + self._immediate = False + self._satisfied = False + self._cancelled = False + self._cancel_lock = threading.Lock() + self._timeout = timeout / 1000.0 + + def __str__(self): + return super(DelayedCondition, self).__str__() + \ + '/' + self._desc + + def cancel(self): + with self._cancel_lock: + self._cancelled = True + + def start(self): + threading.Thread.start(self) + + def wait_for_exit(self): + self.join() + + def run(self): + self._start_time = time.time() + while True: + try: + satisfied = self._check() + except Exception, e: + self._set_error(traceback.format_exc()) + break + with self._cancel_lock: + if self._cancelled: + return + with self._sat_lock: + self._satisfied = satisfied + if satisfied: + # Signal the owner + self._executor.set() + break + if type(self._timeout) is not types.NoneType: + # Check if the remaining time is greater than zero + if self._check_timeout() <= 0.0: + self._set_error( + rts_exceptions.PrecedingTimeoutError(self._desc)) + return + + def _check_timeout(self): + diff = time.time() - self._start_time + return self._timeout - diff + + def _set_error(self, e): + with self._err_lock: + self._error = e + # Signal the owner so it checks the error condition + self._executor.set() + + +class EventCondition(DelayedCondition): + '''A condition that waits for an event. + + This condition is delayed. + + This condition waits on a @ref threading.Event object. It uses a separate + thread to perform the wait; it will sleep until its event is set. When the + event is set, it wakes up and notifies its executor, then exits. If the + event is not set within an optional timeout (specified in ms), @ref + PrecedingTimeoutError is set. Set timeout to None for no timeout. + + ''' + def __init__(self, *args, **kwargs): + super(EventCondition, self).__init__(*args, **kwargs) + self._event = threading.Event() + + def cancel(self): + self._event.set() + super(EventCondition, self).cancel() + + def set(self): + self._event.set() + + def _check(self): + self._event.wait(self._timeout) + if self._event.is_set(): + return True + return False + + +class MonitorCondition(DelayedCondition): + '''A condition that monitors a state. + + This condition is delayed. + + This condition continuously monitors the state of a callback function. When + the callback's return value matches a provided target value, the condition + is satisfied. If this does not occur within an optional timeout (specified + in ms), @ref PrecedingTimeoutError is set. Set timeout to None for no + timeout. The callback will be called at the frequency specified, in Hertz. + + The callback will be passed all the arguments that get passed to @ref + set_args. It should accept any arguments it needs, as well as *args and + **kwargs. + + ''' + def __init__(self, callback=None, target=None, freq=100, *args, **kwargs): + super(MonitorCondition, self).__init__(callback=callback, + target=target, freq=freq, *args, **kwargs) + self._callback = callback + self._target = target + self._sleep_time = 1.0 / freq + + def _check(self): + if self._callback(*self._args, **self._kwargs) == self._target: + return True + time.sleep(self._sleep_time) + return False + + +############################################################################### +## Plan object + +def _make_check_comp_state_cb(rtsprofile, target_comp): + def cb(rtctree=None, *args, **kwargs): + comp = rtsprofile.find_comp_by_target(target_comp) + path = '/' + comp.path_uri + comp = rtctree.get_node(rtctree.path.parse_path(path)[0]) + return comp.refresh_state_in_ec(comp.get_ec_index(target_comp.id)) + return cb + +def _make_action_cb(target_ec): + def cb(*args, **kwargs): + target_ec.set() + return cb + +class Plan(object): + '''A plan for changing the state of an RT System. + + A plan has two sets of actions to perform. The first is stored in a sorted + list; it is all actions that are to be executed immediately. The second + set is stored in a separate list, also sorted. This set contains actions + that will be executed at a later point in time, based on some condition. + Many of these will execute on their own threads. + + To execute the plan, call it. A plan can be cancelled during execution with + the @ref cancel method. As immediate actions will all be executed before + @ref execute returns, this is mainly useful for stopping the delayed + actions after an error occurs. + + ''' + def __init__(self, *args, **kwargs): + super(Plan, self).__init__(*args, **kwargs) + self._immediates = [] + self._laters = [] + self._cancelled = False + self._cancel_lock = threading.Lock() + self._complete_flag = threading.Event() + + def __str__(self): + result = '' + for a in self._immediates: + result += '{0}\n'.format(a) + for a in self._laters: + result += '{0}\n'.format(a) + return result[:-1] + + def cancel(self): + '''Cancel execution of this plan.''' + with self._cancel_lock: + self._cancelled = True + + def execute(self, *args, **kwargs): + '''Execute this plan.''' + error = None + for a in self._immediates: + a(*args, **kwargs) + for a in self._laters: + a(*args, **kwargs) + while self._laters and not error: + self._complete_flag.wait() + with self._cancel_lock: + if self._cancelled: + for a in self._laters: + a.cancel() + break + for a in self._laters: + if a.error: + for b in self._laters: + b.cancel() + error = a.error + break + if self._complete_flag.is_set(): + self._laters = [a for a in self._laters if not a.complete] + self._complete_flag.clear() + for a in self._laters: + a.wait_for_exit() + if error: + raise rts_exceptions.PlanExecutionError(error) + + def make(self, rtsprofile, actions, conds_source, monitor_target): + '''Make a plan from a list of actions and an RTSProfile.''' + all = {} + # First build a dictionary indexed by target for each action + for a in actions: + all[(a.ec_id, a.comp_id, a.instance_name)] = \ + ActionExecutor(action=a, owner_flag=self._complete_flag) + # For each action, find all its conditions and add them to the action's + # executor. + for a in actions: + # First add an executor for each action to a temporary dictionary + conds = self._get_action_conditions(conds_source, a) + if not conds: + continue + for c in conds: + target = (c.target_component.id, + c.target_component.component_id, + c.target_component.instance_name) + action = all[target] + if c.__class__ == rtsprofile.message_sending.Condition: + # Just a sequencing value + action.add_condition(BasicCondition(executor=action, + sequence=c.sequence)) + elif c.__class__ == rtsprofile.message_sending.WaitTime: + # An action to be executed after a certain amount of time + action.add_condition(SleepCondition(executor=action, + wait_time=c.wait_time, sequence=c.sequence)) + elif c.__class__ == rtsprofile.message_sending.Preceding: + # An action that waits for a previous action to + # occur/complete. + if c.sending_timing == 'SYNC': + # Wait for action to complete + for p in c.preceding_components: + desc = 'Sync to {0}'.format(p.instance_name) + timeout = c.timeout + if timeout == 0: + timeout = None + mc = MonitorCondition(executor=action, + sequence=c.sequence, + callback=_make_check_comp_state_cb(rtsprofile, p), + target=monitor_target, + desc=desc, timeout=timeout) + action.add_condition(mc) + target_p = (p.id, p.component_id, p.instance_name) + if all[target_p].action.optional: + print >>sys.stderr, 'Warning: action depends \ +on an optional action: "{0}". This may cause a deadlock if the previous \ +action\'s component is not present.'.format(desc) + else: + # Wait for action to occur + for p in c.preceding_components: + desc = "After {0}'s action".format(p.instance_name) + timeout = c.timeout + if timeout == 0: + timeout = None + ec = EventCondition(executor=action, + sequence=c.sequence, desc=desc, + timeout=timeout) + action.add_condition(ec) + target_p = (p.id, p.component_id, p.instance_name) + all[target_p].add_callback(_make_action_cb(ec)) + if all[target_p].action.optional: + print >>sys.stderr, 'Warning: action depends \ +on an optional action: "{0}". This may cause a deadlock if the previous \ +action\'s component is not present.'.format(desc) + + for k, a in all.items(): + if a.immediate: + self._immediates.append(a) + else: + self._laters.append(a) + self._immediates.sort(key=operator.attrgetter('sort_order')) + self._laters.sort(key=operator.attrgetter('sort_order')) + + def _get_action_conditions(self, conds_source, action): + # Get the corresponding conditions for an action, if any. + result = [] + if conds_source and conds_source.targets: + for c in conds_source.targets: + target = c.target_component + if target.id == action.ec_id and \ + target.component_id == action.comp_id and \ + target.instance_name == action.instance_name: + result.append(c) + return result + + def _signal_complete(self): + self._complete_flag.set() + + +# vim: tw=79 + diff --git a/rtshell/port_types.py b/rtshell/port_types.py new file mode 100644 index 0000000..511467c --- /dev/null +++ b/rtshell/port_types.py @@ -0,0 +1,220 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Classes and functions for managing port types. + +''' + + +import re +import rtctree.path + +import comp_mgmt +import fmt +import rts_exceptions + + +############################################################################### +## Class for managing port specifications. + +class PortSpec(object): + def __init__(self, name, type, target, input=True, formatter=None, + type_name='', raw='', *args, **kwargs): + super(PortSpec, self).__init__() + self._formatter = formatter + self._input = input + self._name = name + self._raw_specs = [raw] + self._targets = [target] + self._type = type + self._type_name = type_name + + def __str__(self): + if self._formatter: + fmt_str = '#{0}'.format(self._formatter) + else: + fmt_str = '' + result = '' + for t in self._targets: + result += '{0}.{1}{2},'.format(rtctree.path.format_path(t), + self._name, fmt_str) + return result[:-1] + + @property + def formatter(self): + '''Get the port's formatter function.''' + return self._formatter + + @property + def input(self): + '''If the port is an input port or not.''' + return self._input + + @property + def name(self): + '''The name of the port.''' + return self._name + + @property + def output(self): + '''If the port is an output port or not.''' + return not self._input + + @property + def raw(self): + '''The raw port specifications that created this PortSpec.''' + return self._raw_specs + + @property + def targets(self): + '''The target ports of this port, as [(path, port_name), ...].''' + return self._targets + + @property + def type(self): + '''The port's data type constructor function.''' + return self._type + + @property + def type_name(self): + '''The port's data type name.''' + return self._type_name + + def add_target(self, target, raw=''): + '''Add an additional target for this port.''' + self._targets.append(target) + self._raw_specs.append(raw) + + +############################################################################### +## Functions for building port specifications. + +def make_port_specs(ports, modmgr, tree): + '''Create a list of PortSpec objects matching the ports given. + + The ports are searched for in the given RTCTree, and PortSpec objects are + created matching them. The component holding each port is found, then the + port object matching the given port name is found. A PortSpec is given + matching its data type and with the reverse direction. If the target port + is an InPort, a PortSpec for an OutPort will be created, and vice versa. + + @param ports The paths to the target ports. Each must be a tuple of + (path, port, name, formatter) where path is a list of path + components in the format used by rtctree. + @param modmgr The ModuleMgr object to use to evaluate the format + expression. + @param tree An RTCTree to search for the ports in. + + ''' + result = {} + index = 0 + for (rtc, port, name, form, raw) in ports: + port_obj = comp_mgmt.find_port(rtc, port, tree) + if port_obj.porttype == 'DataInPort': + input = False + elif port_obj.porttype == 'DataOutPort': + input = True + else: + raise rts_exceptions.BadPortTypeError(rtc, port) + if name is None: + if input: + name = 'input{0}'.format(index) + else: + name = 'output{0}'.format(index) + index += 1 + data_type = port_obj.properties['dataport.data_type'] + # Strip the IDL header and version if present + if data_type.startswith('IDL:'): + data_type = data_type[4:] + colon = data_type.rfind(':') + if colon != -1: + data_type = data_type[:colon] + port_cons = modmgr.find_class(data_type) + if form: + # Look up the formatter in one of the user-provided modules + formatter = fmt.import_formatter(form, modmgr) + else: + formatter = None + if name in result: + # Already have a port with this name so add a target + if (input != result[name].input or + port_cons != result[name].type or + formatter != result[name].formatter): + raise rts_exceptions.SameNameDiffSpecError(raw) + result[name].add_target((rtc, port), raw=raw) + else: + result[name] = (PortSpec(name, port_cons, (rtc, port), input=input, + formatter=formatter, + type_name=port_obj.properties['dataport.data_type'], raw=raw)) + return result.values() + + +def parse_targets(targets): + '''Parse target ports, as specified on the command line. + + Parses target ports specified onto the command line into a tuple of + (path, port, name, formatter, target), where path is in the rtctree + format. + + @param targets A list of target ports, as strings. Each string should + be in the format "path:port.name#formatter", e.g. + "/localhost/blurg.host_cxt/comp0.rtc:input.stuff#print_stuff". + The name component is optional; if it is not present, + neither should the '.' character be. The formatter + component is optional; if it is not present, neither + should the '#' character be. A name is not required + to use a formatter. + + ''' + regex = re.compile(r'^(?P[:\-\w/.\(\)]+?)(?:\.(?P\w+))?(?:#(?P
[\w.]+))?$') + result = [] + for t in targets: + m = regex.match(t) + if not m: + raise rts_exceptions.BadPortSpecError(t) + raw_path, name, formatter = m.groups() + path, port = rtctree.path.parse_path(raw_path) + if not port or not path[-1]: + raise rts_exceptions.BadPortSpecError(t) + result.append((path, port, name, formatter, t)) + return result + + +def require_all_input(port_specs): + '''Checks that all ports in the specification are inputs. + + Raises a @ref PortNotInputError exception if any ports are output. + + @param port_specs A list of @ref PortSpec objects. + + ''' + for p in port_specs: + if not p.input: + raise rts_exceptions.PortNotInputError(p.name) + + +def require_all_output(port_specs): + '''Checks that all ports in the specification are outputs. + + Raises a @ref PortNotOutputError exception if any ports are output. + + @param port_specs A list of @ref PortSpec objects. + + ''' + for p in port_specs: + if not p.output: + raise rts_exceptions.PortNotOutputError(p.name) + diff --git a/rtshell/rtact.py b/rtshell/rtact.py new file mode 100644 index 0000000..512a7c7 --- /dev/null +++ b/rtshell/rtact.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to move a component to the activated state. + +''' + + +import state_control_base + + +def activate_action(object, ec_index): + object.activate_in_ec(ec_index) + + +def main(argv=None, tree=None): + return state_control_base.base_main('Activate a component.', + activate_action, argv) + + +# vim: tw=79 + diff --git a/rtshell/rtcat.py b/rtshell/rtcat.py new file mode 100644 index 0000000..f5fa05d --- /dev/null +++ b/rtshell/rtcat.py @@ -0,0 +1,473 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to display component information. + +''' + + +import optparse +import os +import os.path +import rtctree.exceptions +import rtctree.tree +import rtctree.path +import rtctree.utils +import SDOPackage +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def format_port(port, comp, start_indent=0, use_colour=True, long=0): + result = [] + indent = start_indent + if long > 0: + tag = '-' + else: + tag = '+' + name_string = rtctree.utils.build_attr_string('bold', + supported=use_colour) + port.name + \ + rtctree.utils.build_attr_string('reset', supported=use_colour) + result.append('{0}{1}: {2}'.format(tag.rjust(indent), port.porttype, + name_string)) + if long > 0: + indent += 2 + keys = port.properties.keys() + keys.sort() + pad_length = max([len(key) for key in keys]) + 2 + for key in keys: + result.append('{0}{1}{2}'.format(''.ljust(indent), + key.ljust(pad_length), port.properties[key])) + if port.porttype == 'CorbaPort' and port.interfaces: + for intf in port.interfaces: + result.append('{0}Interface:'.format(''.ljust(indent))) + pad_length = 15 # = len('Instance name') + 2 + indent += 2 + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Instance name'.ljust(pad_length), + intf.instance_name)) + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Type name'.ljust(pad_length), + intf.type_name)) + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Polarity'.ljust(pad_length), + intf.polarity_as_string(add_colour=use_colour))) + indent -= 2 + num_conns = len(port.connections) + for conn in port.connections: + if long > 1: + tag2 = '-' + else: + tag2 = '+' + dest_ports = [] + for name, p in conn.ports: + # Handle the case of unknown port owners + if not p: + dest_ports.append(name) + num_conns -= 1 + # Filter out ports belonging to this comp + elif not comp.get_port_by_ref(p.object): + dest_ports.append(name) + num_conns -= 1 + if dest_ports: + result.append('{0}Connected to {1}'.format( + tag2.rjust(indent), rtctree.utils.build_attr_string('bold', + supported=use_colour) + dest_ports[0] + \ + rtctree.utils.build_attr_string('reset', + supported=use_colour))) + if len(dest_ports) > 1: + for dp in dest_ports[1:]: + result.append('{0}{1}{2}'.format(''.ljust(indent), + ''.ljust(14), + rtctree.utils.build_attr_string('bold', + supported=use_colour) + dp + \ + rtctree.utils.build_attr_string('reset', + supported=use_colour))) + if long > 1: + indent += 2 + keys = [k for k in conn.properties.keys() \ + if not k.endswith('inport_ref') \ + if not k.endswith('inport_ior')] + pad_length = max([len('Name')] + \ + [len(key) for key in keys]) + 2 + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Name'.ljust(pad_length), conn.name)) + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'ID'.ljust(pad_length), conn.id)) + for key in keys: + result.append('{0}{1}{2}'.format(''.ljust(indent), + key.ljust(pad_length), + conn.properties[key])) + indent -= 2 + if num_conns > 0: + if num_conns > 1: + plural = 's' + else: + plural = '' + result.append('{0}({1} other connection{2})'.format(\ + ''.rjust(indent), num_conns, plural)) + indent -= 2 + return result + + +def find_composite_comp(tree, member, inst_name): + def get_fp(mgr, args): + for c in mgr.components: + if c.instance_name == inst_name: + return c.full_path_str + return None + def is_correct_mgr(node): + has_member = False + has_inst_name = False + for c in node.components: + if c.instance_name == inst_name: + has_inst_name = True + elif c.instance_name == member.instance_name: + has_member = True + return has_member and has_inst_name + return tree.iterate(get_fp, filter=['is_manager', is_correct_mgr]) + + +def format_composite(comp, tree, start_indent=0, use_colour=True, long=0): + result = [] + indent = start_indent + for o in comp.organisations: + if not o.sdo_id: + sdo_id = 'Unknown' + else: + sdo_id = o.sdo_id + id_str = rtctree.utils.build_attr_string('bold', + supported=use_colour) + sdo_id + \ + rtctree.utils.build_attr_string('reset', + supported=use_colour) + if long > 0: + tag = '-' + else: + tag = '+' + result.append('{0}Composition {1}'.format(tag.rjust(indent), + id_str)) + if long > 0: + indent += 2 + padding = 8 # = len('Member') + 2 + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'ID'.ljust(padding), o.org_id)) + for m in o.members: + c_path = find_composite_comp(tree, comp, m) + if c_path: + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Member'.ljust(padding), c_path[0])) + else: + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Member'.ljust(padding), 'Unknown')) + indent -= 2 + return result + + +def format_comp_member(comp, tree, start_indent=0, use_colour=True, long=0): + result = [] + indent = start_indent + for po in comp.parent_organisations: + if not po.sdo_id: + sdo_id = 'Unknown' + else: + sdo_id = po.sdo_id + id_str = rtctree.utils.build_attr_string('bold', + supported=use_colour) + sdo_id + \ + rtctree.utils.build_attr_string('reset', + supported=use_colour) + if long > 0: + tag = '-' + else: + tag = '+' + result.append('{0}Parent composition {1}'.format(tag.rjust(indent), + id_str)) + if long > 0: + indent += 2 + padding = 6 # = len('Path') + 2 + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'ID'.ljust(padding), po.org_id)) + composite_path = find_composite_comp(tree, comp, po.sdo_id) + if composite_path: + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Path'.ljust(padding), composite_path[0])) + else: + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Path'.ljust(padding), 'Unknown')) + indent -= 2 + return result + + +def format_ec(ec, start_indent=0, use_colour=True, long=0): + result = [] + indent = start_indent + handle_str = rtctree.utils.build_attr_string('bold', + supported=use_colour) + str(ec.handle) + \ + rtctree.utils.build_attr_string('reset', + supported=use_colour) + if long > 0: + result.append('{0}Execution Context {1}'.format(\ + '-'.rjust(indent), handle_str)) + padding = 7 # = len('State') + 2 + indent += 2 + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'State'.ljust(padding), + ec.running_as_string(add_colour=use_colour))) + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Kind'.ljust(padding), + ec.kind_as_string(add_colour=use_colour))) + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Rate'.ljust(padding), ec.rate)) + if ec.owner_name: + result.append('{0}{1}{2}'.format(''.ljust(indent), + 'Owner'.ljust(padding), ec.owner_name)) + if ec.participant_names: + if long > 1: + result.append('{0}{1}'.format('-'.rjust(indent), + 'Participants'.ljust(padding))) + indent += 2 + for pn in ec.participant_names: + result.append('{0}{1}'.format(''.ljust(indent), + pn)) + indent -= 2 + else: + result.append('{0}{1}'.format('+'.rjust(indent), + 'Participants'.ljust(padding))) + if ec.properties: + if long > 1: + result.append('{0}{1}'.format('-'.rjust(indent), + 'Extra properties'.ljust(padding))) + indent += 2 + keys = ec.properties.keys() + keys.sort() + pad_length = max([len(key) for key in keys]) + 2 + for key in keys: + result.append('{0}{1}{2}'.format(''.ljust(indent), + key.ljust(pad_length), ec.properties[key])) + indent -= 2 + else: + result.append('{0}{1}'.format('+'.rjust(indent), + 'Extra properties'.ljust(padding))) + indent -= 2 + else: + result.append('{0}Execution Context {1}'.format(\ + '+'.rjust(indent), handle_str)) + return result + + +def format_component(comp, tree, use_colour=True, long=0): + result = [] + result.append('{0} {1}'.format(comp.name, + comp.get_state_string(add_colour=use_colour))) + + indent = 2 + profile_items = [('Category', comp.category), + ('Description', comp.description), + ('Instance name', comp.instance_name), + ('Type name', comp.type_name), + ('Vendor', comp.vendor), + ('Version', comp.version)] + if comp.parent: + profile_items.append(('Parent', comp.parent_object)) + if comp.is_composite: + if comp.is_composite_member: + profile_items.append(('Type', 'Composite composite member')) + else: + profile_items.append(('Type', 'Composite')) + elif comp.is_composite_member: + profile_items.append(('Type', 'Monolithic composite member')) + else: + profile_items.append(('Type', 'Monolithic')) + pad_length = max([len(item[0]) for item in profile_items]) + 2 + for item in profile_items: + result.append('{0}{1}{2}'.format(''.ljust(indent), + item[0].ljust(pad_length), + item[1])) + + if comp.properties: + if long > 1: + result.append('{0}Extra properties:'.format(''.ljust(indent))) + indent += 2 + extra_props = comp.properties + keys = extra_props.keys() + keys.sort() + pad_length = max([len(key) for key in keys]) + 2 + for key in keys: + result.append('{0}{1}{2}'.format(''.ljust(indent), + key.ljust(pad_length), + extra_props[key])) + else: + result.append('{0}{1}'.format('+'.rjust(indent), + 'Extra properties')) + indent -= 2 + + if comp.is_composite: + result += format_composite(comp, tree, start_indent=indent, + use_colour=use_colour, long=long) + if comp.is_composite_member: + result += format_comp_member(comp, tree, start_indent=indent, + use_colour=use_colour, long=long) + for ec in comp.owned_ecs: + result += format_ec(ec, start_indent=indent, + use_colour=use_colour, long=long) + for p in comp.ports: + result += format_port(p, comp, start_indent=indent, + use_colour=use_colour, long=long) + + return result + + +def format_manager(mgr, use_colour=True, long=0): + def add_profile_entry(dest, title, key): + if key in mgr.profile: + dest.append('{0}: {1}'.format(title, mgr.profile[key])) + else: + print >>sys.stderr, '{0}: Warning: "{1}" profile entry is \ +missing. Possible version conflict between rtshell and OpenRTM-aist.'.format(\ + sys.argv[0], key) + + result = [] + add_profile_entry(result, 'Name', 'name') + add_profile_entry(result, 'Instance name', 'instance_name') + add_profile_entry(result, 'Process ID', 'pid') + add_profile_entry(result, 'Naming format', 'naming_formats') + add_profile_entry(result, 'Refstring path', 'refstring_path') + add_profile_entry(result, 'Components precreate', 'components.precreate') + result.append('Modules:') + add_profile_entry(result, ' Load path', 'modules.load_path') + add_profile_entry(result, ' Config path', 'modules.config_path') + add_profile_entry(result, ' Preload', 'modules.preload') + add_profile_entry(result, ' Init function prefix', + 'modules.init_func_prefix') + add_profile_entry(result, ' Init function suffix', + 'modules.init_func_suffix') + add_profile_entry(result, ' Download allowed', + 'modules.download_allowed') + add_profile_entry(result, ' Absolute path allowed', + 'modules.abs_path_allowed') + result.append('OS:') + add_profile_entry(result, ' Version', 'os.version') + add_profile_entry(result, ' Architecture', 'os.arch') + add_profile_entry(result, ' Release', 'os.release') + add_profile_entry(result, ' Host name', 'os.hostname') + add_profile_entry(result, ' Name', 'os.name') + # List loaded libraries + result.append('Loaded modules:') + for lm in mgr.loaded_modules: + result.append(' Filepath: {0}'.format(lm['file_path'])) + # List loadable libraries + result.append('Loadable modules:') + for lm in mgr.loadable_modules: + result.append(' {0}'.format(lm['module_file_path'])) + + return result + + +def cat_target(cmd_path, full_path, options, tree=None): + use_colour = rtctree.utils.colour_supported(sys.stdout) + + path, port = rtctree.path.parse_path(full_path) + if not path[-1]: + # There was a trailing slash + trailing_slash = True + path = path[:-1] + else: + trailing_slash = False + + if not tree: + if options.long > 0: + # Longer output needs to look around the tree, so don't filter + filter = [] + else: + filter = [path] + tree = rtctree.tree.RTCTree(paths=path, filter=filter) + + if not tree.has_path(path): + raise rts_exceptions.NoSuchObjectError(cmd_path) + object = tree.get_node(path) + if port: + if not object.is_component: + raise rts_exceptions.NotAComponentError(cmd_path) + if trailing_slash: + raise rts_exceptions.NoSuchObjectError(cmd_path) + p = object.get_port_by_name(port) + if not p: + raise rts_exceptions.PortNotFoundError(path, port) + return format_port(p, object, start_indent=0, + use_colour=use_colour, long=options.long) + else: + if object.is_component: + if trailing_slash: + raise rts_exceptions.NoSuchObjectError(cmd_path) + return format_component(object, tree, use_colour=use_colour, + long=options.long) + elif object.is_manager: + return format_manager(object, use_colour=use_colour, + long=options.long) + elif object.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_path) + else: + raise rts_exceptions.NoSuchObjectError(cmd_path) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [path] +Display information about a manager or component.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-l', dest='long', action='count', default=0, + help='Show more information. Specify multiple times for even '\ + 'more information. [Default: False]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1, [] + + if not args: + # If no path given then can't do anything. + print >>sys.stderr, '{0}: Cannot cat a directory.'.format( + os.path.basename(sys.argv[0])) + return 1, [] + elif len(args) == 1: + cmd_path = args[0] + else: + print >>sys.stderr, usage + return 1, [] + full_path = path.cmd_path_to_full_path(cmd_path) + + result = [] + try: + result = cat_target(cmd_path, full_path, options, tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1, [] + return 0, result + + +# vim: tw=79 + diff --git a/rtshell/rtcheck.py b/rtshell/rtcheck.py new file mode 100644 index 0000000..bf09ca7 --- /dev/null +++ b/rtshell/rtcheck.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcheck library. + +''' + + +import optparse +import os +import rtctree.path +import rtctree.tree +import rtsprofile.rts_profile +import sys +import traceback + +import actions +import option_store +import rts_exceptions +import rtshell + + +class SystemNotOKCB(rtshell.actions.BaseCallback): + '''Callback for a required action. + + Checks the action result and raises @ref RequiredActionFailedError if the + action failed. + + ''' + def __init__(self, *args, **kwargs): + super(SystemNotOKCB, self).__init__(*args, **kwargs) + self._failed = False + + def __call__(self, result, err_msg): + if err_msg: + print >>sys.stderr, err_msg + if not result: + self._failed = True + + def __str__(self): + return 'Required' + + @property + def failed(self): + '''Did any calls to this callback indicate failure?''' + return self._failed + + +def get_data_conn_props(conn): + return {'dataport.dataflow_type': str(conn.data_flow_type), + 'dataport.interface_type': str(conn.interface_type), + 'dataport.subscription_type': str(conn.subscription_type), + 'dataport.data_type': str(conn.data_type)} + + +def check_comps(rtsprofile, req_cb): + checks = [] + for comp in [c for c in rtsprofile.components if c.is_required]: + checks.append(rtshell.actions.CheckForRequiredCompAct('/' + + comp.path_uri, comp.id, comp.instance_name, callbacks=[req_cb])) + for comp in [c for c in rtsprofile.components if not c.is_required]: + checks.append(rtshell.actions.CheckForRequiredCompAct('/' + + comp.path_uri, comp.id, comp.instance_name)) + return checks + + +def check_connection(c, rtsprofile, props, cbs): + s_comp = rtsprofile.find_comp_by_target(c.source_data_port) + s_path = '/' + s_comp.path_uri + s_port = c.source_data_port.port_name + prefix = s_comp.instance_name + '.' + if s_port.startswith(prefix): + s_port = s_port[len(prefix):] + d_comp = rtsprofile.find_comp_by_target(c.target_data_port) + d_path = '/' + d_comp.path_uri + d_port = c.target_data_port.port_name + prefix = d_comp.instance_name + '.' + if d_port.startswith(prefix): + d_port = d_port[len(prefix):] + return rtshell.actions.CheckForConnAct((s_path, s_port), (d_path, d_port), + str(c.connector_id), props, callbacks=cbs) + + +def check_connections(rtsprofile, req_cb): + checks = [] + for c in rtsprofile.required_data_connections(): + props = get_data_conn_props(c) + checks.append(check_connection(c, rtsprofile, props, [req_cb])) + + for c in rtsprofile.optional_data_connections(): + props = get_data_conn_props(c) + checks.append(check_connection(c, rtsprofile, props, [])) + + for c in rtsprofile.required_service_connections(): + checks.append(check_connection(c, rtsprofile, {} [req_cb])) + + for c in rtsprofile.optional_service_connections(): + checks.append(check_connection(c, rtsprofile, {}, [])) + + return checks + + +def check_configs(rtsprofile, req_cb): + checks = [] + # Check the correct set is active + for c in rtsprofile.components: + if c.active_configuration_set: + checks.append(rtshell.actions.CheckActiveConfigSetAct('/' + + c.path_uri, c.active_configuration_set, callbacks=[req_cb])) + for cs in c.configuration_sets: + for p in cs.configuration_data: + checks.append(rtshell.actions.CheckConfigParamAct('/' + + c.path_uri, cs.id, p.name, p.data, callbacks=[req_cb])) + return checks + + +def check_states(rtsprofile, expected, req_cb): + checks = [] + for comp in [c for c in rtsprofile.components if c.is_required]: + for ec in comp.execution_contexts: + checks.append(rtshell.actions.CheckCompStateAct('/' + + comp.path_uri, comp.id, comp.instance_name, ec.id, expected, + callbacks=[req_cb])) + for comp in [c for c in rtsprofile.components if not c.is_required]: + for ec in comp.execution_contexts: + checks.append(rtshell.actions.CheckCompStateAct('/' + + comp.path_uri, comp.id, comp.instance_name, ec.id, expected)) + return checks + + +def check(profile=None, xml=True, state='Active', dry_run=False, tree=None): + # Load the profile + if profile: + # Read from a file + with open(profile) as f: + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f) + else: + # Read from standard input + lines = sys.stdin.read() + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines) + + # Build a list of actions to perform that will check the system + cb = SystemNotOKCB() + actions = (check_comps(rtsp, cb) + check_connections(rtsp, cb) + + check_configs(rtsp, cb) + check_states(rtsp, state, cb)) + if dry_run: + for a in actions: + print a + else: + if not tree: + # Load the RTC Tree, using the paths from the profile + tree = rtctree.tree.RTCTree(paths=[rtctree.path.parse_path( + '/' + c.path_uri)[0] for c in rtsp.components]) + for a in actions: + a(tree) + if cb.failed: + return False + return True + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Check that the running RT System conforms to an RTSProfile.''' + parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION) + parser.add_option('--dry-run', dest='dry_run', action='store_true', + default=False, help="Print what will be done but don't actually '\ + 'do anything. [Default: %default]") + parser.add_option('-s', '--state', dest='state', action='store', + type='string', default='Active', + help='The expected state of the RT Components in the system. ' \ + '[Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML input format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML input format. [Default: False]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError: ', e + return 1 + rtshell.option_store.OptionStore().verbose = options.verbose + + if not args: + profile = None + elif len(args) == 1: + profile = args[0] + else: + print >>sys.stderr, usage + return 1 + + try: + if not check(profile=profile, xml=options.xml, state=options.state, + dry_run=options.dry_run, tree=tree): + return 1 + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(sys.argv[0], e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtcomp.py b/rtshell/rtcomp.py new file mode 100644 index 0000000..e9acfc6 --- /dev/null +++ b/rtshell/rtcomp.py @@ -0,0 +1,288 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the compose-components command. + +''' + + +import optparse +import os +import rtctree.exceptions +import rtctree.path +import rtctree.tree +import rtctree.utils +import SDOPackage +import SDOPackage__POA +import sys +import traceback + +import path +import rtmgr +import rts_exceptions +import rtshell + + +def parse_member_paths(source_paths): + paths = [] + for p in source_paths: + ports = [] + split = p.split(':') + if len(split) == 2: + p = split[0] + ports = split[1].split(',') + elif len(split) > 2: + raise rtctree.exceptions.BadPathError(p) + fp = path.cmd_path_to_full_path(p) + c_path, ignored = rtctree.path.parse_path(fp) + paths.append((p, c_path, ports)) + return paths + + +def get_comp_objs(paths, tree): + objs = {} + for fp, cp, ports in paths: + obj = tree.get_node(cp) + if not obj: + raise rts_exceptions.NoSuchObjectError(fp) + if not obj.is_component: + raise rts_exceptions.NotAComponentError(fp) + objs[fp] = (obj, ports) + return objs + + +def get_potential_comp_objs(paths, tree): + objs = {} + zombies = {} + for fp, cp, ports in paths: + obj = tree.get_node(cp) + if not obj: + zombies[fp] = (cp[0], ports) + else: + objs[fp] = (obj, ports) + return objs, zombies + + +def create_composition(mgr, name, options, comp_type): + if not options.startswith('&'): + options = '&' + options + mgr.create_component('{0}?&instance_name={1}{2}'.format(comp_type, name, + options)) + return mgr.get_node([mgr.name, name + '.rtc']) + + +def add_to_composition(comp, rtcs, tree, verbose): + # Set the exported ports + current_ports = comp.conf_sets['default'].data['exported_ports'].split(',') + current_ports = [x for x in current_ports if x] + new_ports = current_ports + for rtc in rtcs: + c = rtcs[rtc][0] + for p in rtcs[rtc][1]: + # Port existence check has already been done + p_name = rtcs[rtc][0].instance_name + '.' + p + if p_name not in new_ports: + if verbose: + print >>sys.stderr, \ + 'Exporting port {0} from composition'.format(p_name) + new_ports.append(p_name) + if new_ports: + new_ports = reduce(lambda x, y: x + ',' + y, new_ports) + comp.set_conf_set_value('default', 'exported_ports', new_ports) + comp.activate_conf_set('default') + # Add the new RTCs to the composition + to_add = [] + for rtc in rtcs: + c = rtcs[rtc][0] + if not comp.is_member(c): + if verbose: + print >>sys.stderr, \ + 'Adding component {0} to composition'.format(rtc) + to_add.append(c) + elif verbose and not rtcs[rtc][1]: + # Only print this message if the component didn't have any ports to + # add + print >>sys.stderr, \ + 'Component {0} is already in composition'.format(rtc) + comp.add_members(to_add) + + +def rem_from_composition(comp, rtcs, tree, verbose): + current_ports = comp.conf_sets['default'].data['exported_ports'].split(',') + current_ports = [x for x in current_ports if x] + new_ports = current_ports + for rtc in rtcs: + if type(rtcs[rtc][0]) is str: + inst_name = rtcs[rtc][0] + else: + inst_name = rtcs[rtc][0].instance_name + for p in rtcs[rtc][1]: + p_name = inst_name + '.' + p + if p_name in new_ports: + if verbose: + print >>sys.stderr, \ + 'Hiding port {0} in composition'.format(p_name) + new_ports.remove(p_name) + elif verbose: + print >>sys.stderr, \ + 'Port {0} is already hidden in composition'.format( + p_name) + if new_ports: + new_ports = reduce(lambda x, y: x + ',' + y, new_ports) + else: + new_ports = '' + comp.set_conf_set_value('default', 'exported_ports', new_ports) + comp.activate_conf_set('default') + # Remove RTCs that have no ports specified from the composition + to_remove = [] + for rtc in rtcs: + if rtcs[rtc][1]: + # Ignore components that had ports specified + continue + c = rtcs[rtc][0] + if comp.is_member(c): + if verbose: + print >>sys.stderr, \ + 'Removing component {0} from composition'.format(rtc) + to_remove.append(c) + elif verbose: + print >>sys.stderr, \ + 'Component {0} is not in composition'.format(rtc) + comp.remove_members(to_remove) + + +def manage_composition(tgt_raw_path, tgt_full_path, options, tree=None): + # Parse paths of components to add/remove + add_paths = parse_member_paths(options.add) + rem_paths = parse_member_paths(options.remove) + + # The target, either a manager or a component + tgt_path, tgt_suffix = rtctree.path.parse_path(tgt_full_path) + + # Make a tree + if not tree: + paths = [tgt_path] + [y for x, y, z in add_paths + rem_paths] + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + tgt_obj = tree.get_node(tgt_path) + if not tgt_obj: + raise rts_exceptions.NoSuchObjectError(tgt_raw_path) + + # Input sanity check: ensure all components and ports to be added exist + add_rtcs = get_comp_objs(add_paths, tree) + for rtc in add_rtcs: + for p in add_rtcs[rtc][1]: + if not add_rtcs[rtc][0].get_port_by_name(p): + raise rts_exceptions.PortNotFoundError(rtc, p) + # Ensure all ports to be removed that are on components that are alive + # exist + rem_rtcs, rem_zombies = get_potential_comp_objs(rem_paths, tree) + for rtc in rem_rtcs: + for p in rem_rtcs[rtc][1]: + if not rem_rtcs[rtc][0].get_port_by_name(p): + raise rts_exceptions.PortNotFoundError(rtc, p) + + if tgt_obj.is_manager: + # Create composition + if not tgt_suffix: + tgt_suffix = 'CompositeRTC' + tgt_raw_path += ':' + tgt_suffix + # Check if this composition already exists + comp = tgt_obj.get_node([tgt_obj.name, tgt_suffix + '.rtc']) + if not comp: + # Cannot remove components when creating a new composition + if options.remove: + raise rts_exceptions.CannotRemoveFromNewCompositionError() + # No composition exists in this manager; make a new one + if options.verbose: + print >>sys.stderr, 'Creating new composition {0}'.format( + tgt_raw_path) + comp = create_composition(tgt_obj, tgt_suffix, options.options, + options.type) + elif options.verbose: + print >>sys.stderr, 'Editing existing composition {0}'.format( + tgt_raw_path) + elif tgt_obj.is_component: + # Edit composition - there should be no suffix + if tgt_suffix: + raise rts_exceptions.NotAComponentError(tgt_raw_path) + comp = tgt_obj + if options.verbose: + print >>sys.stderr, 'Editing existing composition {0}'.format( + tgt_raw_path) + else: + raise rts_exceptions.NotAComponentOrManagerError(tgt_raw_path) + if not comp.is_composite: + raise rts_exceptions.NotACompositeComponentError(tgt_raw_path) + + if add_paths: + add_to_composition(comp, add_rtcs, tree, options.verbose) + if rem_paths: + rem_rtcs.update(rem_zombies) + rem_from_composition(comp, rem_rtcs, tree, options.verbose) + if not comp.members[comp.organisations[0].org_id]: + if options.verbose: + print >>sys.stderr, 'Composition {0} has no members'.format( + tgt_raw_path) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Manage composite components.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-a', '--add', dest='add', action='append', + type='string', default=[], help='A component to include in the ' + 'composition. Specify a comma-separated list of ports to export ' + 'after the component name, separated by a colon.') + parser.add_option('-o', '--options', dest='options', action='store', + type='string', default='', help='Extra options to pass to the '\ + 'component on creation.') + parser.add_option('-r', '--remove', dest='remove', action='append', + type='string', default=[], help='A component or ports to remove ' + 'from the composition.') + parser.add_option('-t', '--type', dest='type', action='store', + type='string', default='PeriodicECSharedComposite', + help='Type of composite component to create. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if len(args) != 1: + print >>sys.stderr, '{0}: No manager or existing composite component '\ + 'specified.'.format(sys.argv[0]) + return 1 + full_path = path.cmd_path_to_full_path(args[0]) + + try: + manage_composition(args[0], full_path, options, tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(sys.argv[0], e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtcon.py b/rtshell/rtcon.py new file mode 100644 index 0000000..f65159d --- /dev/null +++ b/rtshell/rtcon.py @@ -0,0 +1,126 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to connect two ports. + +''' + + +import optparse +import os +import os.path +import rtctree.exceptions +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def connect_ports(paths, options, tree=None): + cmd_paths, fps = zip(*paths) + pathports = [rtctree.path.parse_path(fp) for fp in fps] + for ii, p in enumerate(pathports): + if not p[1]: + raise rts_exceptions.NotAPortError(cmd_paths[ii]) + if not p[0][-1]: + raise rts_exceptions.NotAPortError(cmd_paths[ii]) + paths, ports = zip(*pathports) + + if not tree: + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + + port_objs = [] + for ii, p in enumerate(pathports): + obj = tree.get_node(p[0]) + if not obj: + raise rts_exceptions.NoSuchObjectError(cmd_paths[ii]) + if obj.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_paths[ii]) + if not obj.is_component: + raise rts_exceptions.NotAComponentError(cmd_paths[ii]) + port_obj = obj.get_port_by_name(p[1]) + if not port_obj: + raise rts_exceptions.PortNotFoundError(p[0], p[1]) + port_objs.append(port_obj) + + conn_name = options.name if options.name else None + port_objs[0].connect(port_objs[1:], name=conn_name, id=options.id, + props=options.properties) + + +def main(argv=None, tree=None): + def property_callback(option, opt, option_value, parser): + if option_value.count('=') != 1: + raise optparse.OptionValueError('Bad property format: {0}'.format( + option_value)) + key, equals, value = option_value.partition('=') + if not getattr(parser.values, option.dest): + setattr(parser.values, option.dest, {}) + if key in getattr(parser.values, option.dest): + print >>sys.stderr, '{0}: Warning: duplicate property: {1}'.format( + sys.argv[0], option_value) + getattr(parser.values, option.dest)[key] = value + + usage = '''Usage: %prog [options] [ ...] +Connect two or more ports.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-i', '--id', dest='id', action='store', type='string', + default='', help='ID of the connection. [Default: %default]') + parser.add_option('-n', '--name', dest='name', action='store', + type='string', default=None, + help='Name of the connection. [Default: %default]') + parser.add_option('-p', '--property', dest='properties', action='callback', + callback=property_callback, type='string', + help='Connection properties.') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if not getattr(options, 'properties'): + setattr(options, 'properties', {}) + + if not args: + # If no paths given then can't do anything. + print >>sys.stderr, '{0}: No ports specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + paths = [(p, path.cmd_path_to_full_path(p)) for p in args] + + try: + connect_ports(paths, options, tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtconf.py b/rtshell/rtconf.py new file mode 100644 index 0000000..a703002 --- /dev/null +++ b/rtshell/rtconf.py @@ -0,0 +1,246 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to manage component configuration. + +''' + + +import optparse +import os +import os.path +import rtctree.exceptions +import rtctree.tree +import rtctree.path +import rtctree.utils +import sys +import traceback + +import path +import rtshell +import rts_exceptions + + +def is_hidden(name): + hidden_prefix = '__' + hidden_suffix = '__' + return name.startswith(hidden_prefix) and name.endswith(hidden_suffix) + + +def format_conf_set(set_name, set, is_active, use_colour, long): + result = [] + indent = 0 + if long: + tag = '-' + else: + tag = '+' + if is_active: + title = tag + rtctree.utils.build_attr_string(['bold', 'green'], + supported=use_colour) + set_name + '*' + \ + rtctree.utils.build_attr_string('reset', supported=use_colour) + if set.description: + title += ' ({0})'.format(set.description) + else: + title = tag + rtctree.utils.build_attr_string('bold', + supported=use_colour) + set_name + \ + rtctree.utils.build_attr_string('reset', supported=use_colour) + if set.description: + title += ' ({0})'.format(set.description) + result.append(title) + + if long: + params = set.data.keys() + if params: + params.sort() + padding = len(max(params, key=len)) + 2 + indent += 2 + for param in params: + result.append('{0}{1}{2}'.format(''.ljust(indent), + param.ljust(padding), set.data[param])) + indent -= 2 + + return result + + +def format_conf_sets(sets, active_set_name, all, use_colour, long): + result = [] + set_keys = [k for k in sets.keys() if not is_hidden(k) or all] + set_keys.sort() + for set_name in set_keys: + result += format_conf_set(set_name, sets[set_name], + set_name == active_set_name, use_colour, long) + return result + + +def get_comp(cmd_path, full_path, tree=None): + path, port = rtctree.path.parse_path(full_path) + if port: + # Can't configure a port + raise rts_exceptions.NotAComponentError(cmd_path) + if not path[-1]: + # There was a trailing slash + raise rts_exceptions.NoSuchObjectError(cmd_path) + + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + comp = tree.get_node(path) + if not comp: + raise rts_exceptions.NoSuchObjectError(cmd_path) + if comp.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_path) + if not comp.is_component: + raise rts_exceptions.NotAComponentError(cmd_path) + return tree, comp + + + +def print_conf_sets(cmd_path, full_path, options, tree=None): + use_colour = rtctree.utils.colour_supported(sys.stdout) + tree, comp = get_comp(cmd_path, full_path, tree) + + if options.set_name: + if is_hidden(options.set_name) and not options.all: + raise rts_exceptions.NoConfSetError(options.set_name) + if not options.set_name in comp.conf_sets: + raise rts_exceptions.NoConfSetError(options.set_name) + return format_conf_set(options.set_name, + comp.conf_sets[options.set_name], + options.set_name == comp.active_conf_set_name, + use_colour, options.long) + else: + return format_conf_sets(comp.conf_sets, + comp.active_conf_set_name, options.all, + use_colour, options.long) + + +def set_conf_value(param, new_value, cmd_path, full_path, options, tree=None): + tree, comp = get_comp(cmd_path, full_path, tree) + + if not options.set_name: + options.set_name = comp.active_conf_set_name + if is_hidden(options.set_name) and not options.all: + raise rts_exceptions.NoConfSetError(options.set_name) + comp.set_conf_set_value(options.set_name, param, new_value) + if options.set_name == comp.active_conf_set_name: + # Re-activate the set to update the config param internally in the + # component. + comp.activate_conf_set(options.set_name) + + +def get_conf_value(param, cmd_path, full_path, options, tree=None): + tree, comp = get_comp(cmd_path, full_path, tree) + + if not options.set_name: + options.set_name = comp.active_conf_set_name + if is_hidden(options.set_name) and not options.all: + raise rts_exceptions.NoConfSetError(options.set_name) + + if not options.set_name in comp.conf_sets: + raise rts_exceptions.NoConfSetError(options.set_name) + if not param in comp.conf_sets[options.set_name].data: + raise rtctree.exceptions.NoSuchConfParamError(param) + return [comp.conf_sets[options.set_name].data[param]] + + +def activate_set(cmd_path, full_path, options, tree=None): + if is_hidden(options.set_name) and not options.all: + raise rts_exceptions.NoConfSetError(options.set_name) + tree, comp = get_comp(cmd_path, full_path, tree) + if not options.set_name in comp.conf_sets: + raise rts_exceptions.NoConfSetError(options.set_name) + comp.activate_conf_set(options.set_name) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [command] [args] +Display and edit configuration parameters and sets.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-a', '--all', dest='all', action='store_true', + default=False, + help='Do not ignore hidden sets. [Default: %default]') + parser.add_option('-l', dest='long', action='store_true', default=False, + help='Show more information. [Default: %default]') + parser.add_option('-s', '--set', dest='set_name', action='store', + default='', help='Choose the configuration set to manipulate. '\ + '[Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1, [] + + if not args: + print >>sys.stderr, usage + return 1, [] + elif len(args) == 1: + cmd_path = args[0] + cmd = 'list' + args = args[1:] + else: + cmd_path = args[0] + cmd = args[1] + args = args[2:] + full_path = path.cmd_path_to_full_path(cmd_path) + + result = [] + try: + if cmd == 'list': + # Print the configuration sets + result = print_conf_sets(cmd_path, full_path, options, tree) + elif cmd == 'set': + # Need to get more arguments + if len(args) == 2: + param = args[0] + new_value = args[1] + else: + print >>sys.stderr, usage + return 1, [] + set_conf_value(param, new_value, cmd_path, full_path, options, + tree) + elif cmd == 'get': + #Need to get more arguments + if len(args) == 1: + param = args[0] + else: + print >>sys.stderr, usage + return 1, [] + result = get_conf_value(param, cmd_path, full_path, options, tree) + elif cmd == 'act': + if len(args) != 0 or options.set_name == '': + print >>sys.stderr, usage + return 1, [] + activate_set(cmd_path, full_path, options, tree) + else: + print >>sys.stderr, usage + return 1, [] + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1, [] + return 0, result + + +# vim: tw=79 + diff --git a/rtshell/rtcryo.py b/rtshell/rtcryo.py new file mode 100644 index 0000000..d8377fb --- /dev/null +++ b/rtshell/rtcryo.py @@ -0,0 +1,302 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcryo library. + +''' + + +import datetime +import optparse +import os.path +import rtctree.tree +import rtctree.path +import rtsprofile +import rtsprofile.rts_profile +import rtsprofile.component +import rtsprofile.config_set +import rtsprofile.exec_context +import rtsprofile.port_connectors +import rtsprofile.ports +import rtsprofile.targets +import sys +import traceback + +import option_store +import rtshell + + +def clean_props(props): + '''Clean properties of dangerous values and wrong data types. + + Make sure the properties don't have IORs or similar in them, because + they will confuse the notify_connect calls. + + Make sure that all keys are not unicode. + + ''' + new_props = {} + for p in props: + if p == 'dataport.corba_cdr.inport_ior': + continue + if p == 'dataport.corba_cdr.inport_ref': + continue + if p == 'dataport.corba_cdr.outport_ior': + continue + if p == 'dataport.corba_cdr.outport_ref': + continue + new_props[str(p)] = str(props[p]) + return new_props + + +def make_comp_id(comp): + return 'RTC:{0}:{1}:{2}:{3}'.format(comp.vendor, comp.category, + comp.type_name, comp.version) + + +def find_all_used_components(tree): + # Finds all component nodes in the tree + def get_node(node, args): + return node + def is_in_dir(node): + if node.parent.is_manager: + return False + return True + return [c for c in tree.iterate(get_node, + filter=['is_component', is_in_dir]) \ + if c.connected_ports] + + +def find_unique_connectors(tree, components): + # Finds all unique connections between the components + data_connectors = [] + seen_svc_connectors = [] + svc_connectors = [] + def in_svc_list(conn): + for c in svc_connectors: + if c.connector_id == conn.id: + return True + return False + + for comp in components: + for op in comp.connected_outports: + for conn in op.connections: + name = comp.instance_name + '.' + op.name + source_port = rtsprofile.targets.TargetPort( + component_id=make_comp_id(comp), + instance_name=comp.instance_name, port_name=name) + source_port.properties['COMPONENT_PATH_ID'] = \ + comp.full_path_str[1:] + # Get the list of ports this connection goes to + dest_ports = [name for name, p in conn.ports \ + if not comp.get_port_by_ref(p.object)] + # Assume the first is the destination and find its component + path = rtctree.path.parse_path(dest_ports[0]) + dest_comp = tree.get_node(path[0]) + # Now have all the info we need to make the target + name = dest_comp.instance_name + '.' + path[1] + dest_port = rtsprofile.targets.TargetPort( + component_id=make_comp_id(dest_comp), + instance_name=dest_comp.instance_name, port_name=name) + dest_port.properties['COMPONENT_PATH_ID'] = \ + dest_comp.full_path_str[1:] + # Check if the data type is known (see issue 13) + if 'dataport.data_type' in conn.properties: + data_type = conn.properties['dataport.data_type'] + else: + data_type = dest_port.port_name + rts_conn = rtsprofile.port_connectors.DataPortConnector( + connector_id=conn.id, name=conn.name, + data_type=data_type, + interface_type=conn.properties['dataport.interface_type'], + data_flow_type=conn.properties['dataport.dataflow_type'], + subscription_type=conn.properties['dataport.subscription_type'], + source_data_port=source_port, + target_data_port=dest_port) + rts_conn.properties = clean_props(conn.properties) + data_connectors.append(rts_conn) + + for sp in comp.connected_svcports: + for conn in sp.connections: + if in_svc_list(conn): + continue; + seen_svc_connectors.append(conn) + name = comp.instance_name + '.' + sp.name + source_port = rtsprofile.targets.TargetPort( + component_id=make_comp_id(comp), + instance_name=comp.instance_name, port_name=name) + source_port.properties['COMPONENT_PATH_ID'] = \ + comp.full_path_str[1:] + # Get the list of ports this connection goes to + dest_ports = [name for name, p in conn.ports \ + if not comp.get_port_by_ref(p.object)] + if not dest_ports: + # Skip ports with no or unknown connections + # (Unknown connections cannot be preserved) + # See issue 13 + continue + # Assume the first is the destination and find its component + path = rtctree.path.parse_path(dest_ports[0]) + dest_comp = tree.get_node(path[0]) + # Now have all the info we need to make the target + name = dest_comp.instance_name + '.' + path[1] + dest_port = rtsprofile.targets.TargetPort( + component_id=make_comp_id(dest_comp), + instance_name=dest_comp.instance_name, port_name=name) + dest_port.properties['COMPONENT_PATH_ID'] = \ + dest_comp.full_path_str[1:] + rts_conn = rtsprofile.port_connectors.ServicePortConnector( + connector_id=conn.id, name=conn.name, + source_service_port=source_port, + target_service_port=dest_port) + rts_conn.properties = clean_props(conn.properties) + svc_connectors.append(rts_conn) + return data_connectors, svc_connectors + + +def tree_comps_to_rts_comps(components): + rts_comps = [] + for comp in components: + active_conf_set = comp.active_conf_set_name if comp.active_conf_set \ + else '' + new_rtsc = rtsprofile.component.Component(id=make_comp_id(comp), + path_uri=comp.full_path_str[1:], + active_configuration_set=active_conf_set, + instance_name=comp.instance_name, + composite_type=rtsprofile.composite_type.NONE, + is_required=True) + for dp in comp.inports: + new_rtsc.data_ports.append(rtsprofile.ports.DataPort(dp.name)) + for dp in comp.outports: + new_rtsc.data_ports.append(rtsprofile.ports.DataPort(dp.name)) + for sp in comp.svcports: + new_rtsc.service_ports.append(rtsprofile.ports.ServicePort(sp.name)) + for cs in comp.conf_sets: + new_cs = rtsprofile.config_set.ConfigurationSet(id=cs) + for param in comp.conf_sets[cs].data: + new_cs.configuration_data.append( + rtsprofile.config_set.ConfigurationData(name=param, + data=comp.conf_sets[cs].data[param])) + new_rtsc.configuration_sets.append(new_cs) + for ec in comp.owned_ecs: + new_rtsc.execution_contexts.append( + rtsprofile.exec_context.ExecutionContext( + id=str(ec.handle), + kind=ec.kind_as_string(add_colour=False).upper(), + rate=ec.rate)) + new_rtsc.properties['IOR'] = \ + comp.nameserver.orb.object_to_string(comp.object) + rts_comps.append(new_rtsc) + return rts_comps + + +def data_conns_to_rts_conns(connectors): + result = [] + for conn in connectors: + source_port = rtsprofile.targets.TargetPort() + dest_port = rtsprofile.targets.TargetPort() + return result + + +def freeze_dry(servers, dest='-', xml=True, abstract='', vendor='', sysname='', + version='', tree=None): + if not tree: + tree = rtctree.tree.RTCTree(servers=servers) + # Run through the tree finding component names and connections to + # preserve. + components = find_all_used_components(tree) + # Create a list of objects for the profile + rts_components = tree_comps_to_rts_comps(components) + data_connectors, svc_connectors = find_unique_connectors(tree, + components) + # Create an empty RTSProfile and add the information to it + rtsp = rtsprofile.rts_profile.RtsProfile() + rtsp.abstract = abstract + today = datetime.datetime.today() + today = today.replace(microsecond=0) + rtsp.creation_date = today.isoformat() + rtsp.update_date = today.isoformat() + rtsp.version = rtsprofile.RTSPROFILE_SPEC_VERSION + rtsp.id = 'RTSystem :{0}.{1}.{2}'.format(vendor, sysname, version) + rtsp.components = rts_components + rtsp.data_port_connectors = data_connectors + rtsp.service_port_connectors = svc_connectors + + if dest == '-': + # Write XML to stdout + if xml: + sys.stdout.write(rtsp.save_to_xml()) + else: + sys.stdout.write(rtsp.save_to_yaml()) + else: + # Write to a file + f = open(dest, 'w') + if xml: + f.write(rtsp.save_to_xml()) + else: + f.write(rtsp.save_to_yaml()) + f.close() + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [name servers] +Record a running RT System in an RTSProfile specification.''' + parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION) + parser.add_option('-a', '--abstract', dest='abstract', action='store', + type='string', default='RT System created by rtcryo.', + help='Brief description of the RT System.') + parser.add_option('-n', '--system-name', dest='sysname', action='store', + type='string', default='RTSystem', + help='Name of the RT System. [Default: %default]') + parser.add_option('-o', '--output', dest='output', action='store', + type='string', default='-', + help='Output file name. [Default: standard out]') + parser.add_option('-v', '--system-version', dest='version', action='store', + type='string', default='0', + help='Version of the RT System. [Default: %default]') + parser.add_option('-e', '--vendor', dest='vendor', action='store', + type='string', default='Me', + help='Vendor of the RT System. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML output format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML output format. [Default: False]') + parser.add_option('--verbose', dest='verbose', action='store_true', + default=False, help='Verbose output. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError: ', e + return 1 + option_store.OptionStore().verbose = options.verbose + + try: + freeze_dry(args, dest=options.output, xml=options.xml, + abstract=options.abstract, vendor=options.vendor, + sysname=options.sysname, version=options.version, tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(sys.argv[0], e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtcwd.py b/rtshell/rtcwd.py new file mode 100644 index 0000000..bcea8ea --- /dev/null +++ b/rtshell/rtcwd.py @@ -0,0 +1,106 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Create a command to change the current working directory environment variable. + +''' + + +#!/usr/bin/env python + +import os +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions + +if sys.platform == 'win32': + SET_CMD = 'set' + EQUALS = '=' + QUOTE = '' +elif 'SHELL' in os.environ and 'csh' in os.environ['SHELL']: + SET_CMD = 'setenv' + EQUALS = ' ' + QUOTE = '"' +else: + SET_CMD = 'export' + EQUALS = '=' + QUOTE = '"' + + +def make_cmd_line(dest): + return '{0} {1}{2}{3}{4}{3}'.format(SET_CMD, path.ENV_VAR, EQUALS, + QUOTE, dest) + + +def cd(cmd_path, full_path): + path, port = rtctree.path.parse_path(full_path) + if port: + raise rts_exceptions.NotADirectoryError(cmd_path) + if not path[-1]: + # Remove trailing slash part + path = path[:-1] + tree = rtctree.tree.RTCTree(paths=path) + if not tree.has_path(path): + raise rts_exceptions.NotADirectoryError(cmd_path) + if not tree.is_directory(path): + raise rts_exceptions.NotADirectoryError(cmd_path) + return make_cmd_line(full_path) + + +def main(argv=None, tree=None): + if argv: + sys.argv = [sys.argv[0]] + argv + if len(sys.argv) < 2: + # Change to the root dir + print '{0} {1}{3}{2}/{2}'.format(SET_CMD, path.ENV_VAR, QUOTE, EQUALS) + return 0 + + # Take the first argument only + cmd_path = sys.argv[1] + + try: + if cmd_path == '.' or cmd_path == './': + # Special case for '.': do nothing + if path.ENV_VAR in os.environ: + print make_cmd_line(os.environ[path.ENV_VAR]) + else: + print make_cmd_line('/') + elif cmd_path == '..' or cmd_path == '../': + # Special case for '..': go up one directory + if path.ENV_VAR in os.environ and os.environ[path.ENV_VAR] and \ + os.environ[path.ENV_VAR] != '/': + parent = os.environ[path.ENV_VAR][\ + :os.environ[path.ENV_VAR].rstrip('/').rfind('/')] + if not parent: + parent = '/' + print make_cmd_line(parent) + else: + print make_cmd_line('/') + else: + full_path = path.cmd_path_to_full_path(cmd_path) + print cd(cmd_path, full_path) + except Exception, e: + print >>sys.stderr, 'rtcwd: {0}'.format(e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtdeact.py b/rtshell/rtdeact.py new file mode 100644 index 0000000..26d209f --- /dev/null +++ b/rtshell/rtdeact.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to move a component to the inactive state. + +''' + + +import state_control_base + + +def deactivate_action(object, ec_index): + object.deactivate_in_ec(ec_index) + + +def main(argv=None, tree=None): + return state_control_base.base_main('Deactivate a component.', + deactivate_action, argv) + + +# vim: tw=79 + diff --git a/rtshell/rtdel.py b/rtshell/rtdel.py new file mode 100644 index 0000000..08f45de --- /dev/null +++ b/rtshell/rtdel.py @@ -0,0 +1,125 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of deleting an object from a name server. + +''' + + +import optparse +import os +import os.path +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def delete_object_reference(cmd_path, full_path, options, tree=None): + path, port = rtctree.path.parse_path(full_path) + if port: + raise rts_exceptions.UndeletableObjectError(cmd_path) + if not path[-1]: + path = path[:-1] + + # Cannot delete name servers + if len(path) == 2: + raise rts_exceptions.UndeletableObjectError(cmd_path) + + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + if options.zombies and not tree.is_zombie(path): + raise rts_exceptions.NotZombieObjectError(cmd_path) + + # There is no point in doing path checks for the path, as the path we are + # deleting may not be in the tree if it's a zombie. Instead, we need to + # find its parent, and use that to remove the name. + parent = tree.get_node(path[:-1]) + if parent.is_manager: + raise rts_exceptions.ParentNotADirectoryError(cmd_path) + if not parent.is_directory: + raise rts_exceptions.ParentNotADirectoryError(cmd_path) + parent.unbind(path[-1]) + + +def delete_all_zombies(options, tree=None): + if not tree: + tree = rtctree.tree.RTCTree() + if not tree: + return 1 + def del_zombie(node, args): + try: + node.parent.unbind(node.name) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(sys.argv[0], e) + tree.iterate(del_zombie, filter=['is_zombie']) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Delete an object from a name server.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-z', '--zombies', dest='zombies', action='store_true', + default=False, help='Delete only zombies. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + try: + if not args: + if not options.zombies: + print >>sys.stderr, '{0}: No path given.'.format(sys.argv[0]) + return 1 + else: + # If no path given, delete all zombies found + delete_all_zombies(options, tree) + elif len(args) == 1: + full_path = path.cmd_path_to_full_path(args[0]) + # Some sanity checks + if full_path == '/': + print >>sys.stderr, '{0}: Cannot delete the root '\ + 'directory.'.format(sys.argv[0]) + return 1 + delete_object_reference(args[0], full_path, options, tree) + else: + print >>sys.stderr, usage + return 1 + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtdis.py b/rtshell/rtdis.py new file mode 100644 index 0000000..15b114a --- /dev/null +++ b/rtshell/rtdis.py @@ -0,0 +1,163 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to disconnect ports. + +''' + + +import optparse +import os +import os.path +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def disconnect_all(cmd_path, full_path, options, tree=None): + path, port = rtctree.path.parse_path(full_path) + if not path[-1]: + raise rts_exceptions.NoSuchObjectError(cmd_path) + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + object = tree.get_node(path) + if not object: + raise rts_exceptions.NoSuchObjectError(cmd_path) + if not object.is_component: + raise rts_exceptions.NotAComponentError(cmd_path) + + if port: + # Disconnect a single port + port_obj = object.get_port_by_name(port) + if not port_obj: + raise rts_exceptions.PortNotFoundError(path, port) + if options.id: + conn = port_obj.get_connection_by_id(options.id) + if not conn: + raise rts_exceptions.ConnectionIDNotFoundError(options.id, + cmd_path) + conn.disconnect() + else: + port_obj.disconnect_all() + else: + if options.id: + # Hunt through the ports for the connection ID + for p in object.ports: + conn = p.get_connection_by_id(options.id) + if not conn: + continue + conn.disconnect() + return + raise rts_exceptions.ConnectionIDNotFoundError(options.id, + cmd_path) + else: + # Disconnect all ports + object.disconnect_all() + + +def disconnect_ports(paths, options, tree=None): + cmd_paths, fps = zip(*paths) + pathports = [rtctree.path.parse_path(fp) for fp in fps] + for ii, p in enumerate(pathports): + if not p[1]: + raise rts_exceptions.NotAPortError(cmd_paths[ii]) + if not p[0][-1]: + raise rts_exceptions.NotAPortError(cmd_paths[ii]) + paths, ports = zip(*pathports) + + if not tree: + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + + port_objs = [] + for ii, p in enumerate(pathports): + obj = tree.get_node(p[0]) + if not obj: + raise rts_exceptions.NoSuchObjectError(cmd_paths[ii]) + if obj.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_paths[ii]) + if not obj.is_component: + raise rts_exceptions.NotAComponentError(cmd_paths[ii]) + port_obj = obj.get_port_by_name(p[1]) + if not port_obj: + raise rts_exceptions.PortNotFoundError(p[0], p[1]) + port_objs.append(port_obj) + if len(port_objs) < 2: + raise rts_exceptions.NoDestPortError + + if options.id: + all_conns = port_objs[0].get_connections_by_dests(port_objs[1:]) + conns = [] + for c in all_conns: + if c.id == options.id: + conns.append(c) + else: + conns = port_objs[0].get_connections_by_dests(port_objs[1:]) + + if not conns: + raise rts_exceptions.MultiConnectionNotFoundError + for c in conns: + c.disconnect() + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [destination path] +Remove connections.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-i', '--id', dest='id', action='store', type='string', + default='', help='ID of the connection.') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + try: + if len(args) == 1: + # Disconnect all + cmd_path = args[0] + disconnect_all(cmd_path, path.cmd_path_to_full_path(cmd_path), + options, tree) + elif len(args) > 1: + # Disconnect a set of ports + paths = [(p, path.cmd_path_to_full_path(p)) for p in args] + disconnect_ports(paths, options, tree) + else: + print >>sys.stderr, usage + return 1 + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + + +# vim: tw=79 + diff --git a/rtshell/rtdoc.py b/rtshell/rtdoc.py new file mode 100644 index 0000000..2511570 --- /dev/null +++ b/rtshell/rtdoc.py @@ -0,0 +1,270 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Yosuke Matsusaka and Geoffrey Biggs + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to display component documentation. + +''' + + +import docutils.core +import optparse +import os +import os.path +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def escape(s): + return s.replace('"', "'") + + +def section(s, level=0): + result = [] + if level == 0: + result.append(s) + result.append('=' * len(s)) + elif level == 1: + result.append(s) + result.append('-' * len(s)) + return result + + +def get_ports_docs(comp): + result = [] + result.append('.. csv-table:: Ports') + result.append(' :header: "Name", "Type", "DataType", "Description"') + result.append(' :widths: 8, 8, 8, 26') + result.append(' ') + for p in comp.ports: + if p.porttype == 'DataInPort' or p.porttype == 'DataOutPort': + datatype = p.properties['dataport.data_type'] + else: + datatype = '' + if 'description' in p.properties: + description = p.properties['description'] + else: + description = '' + result.append(' "{0}", "{1}", "{2}", "{3}"'.format(p.name, + p.porttype, datatype, escape(description))) + return result + + +def get_config_docs(comp): + result = [] + result.append('.. csv-table:: Configuration parameters') + result.append(' :header: "Name", "Description"') + result.append(' :widths: 12, 38') + result.append(' ') + + desc_set = None + if '__description__' in comp.conf_sets: + desc_set = comp.conf_sets['__description__'] + for n in comp.conf_sets['default'].data: + if desc_set and desc_set.has_param(n): + description = desc_set.data[n] + else: + description = '' + result.append(' "{0}", "{1}"'.format(n, escape(description))) + return result + + +from rtstodot import port_name as dot_port_name +from rtstodot import escape as dot_escape + +def make_comp_graph(comp): + result = [] + result.append('.. digraph:: comp') + result.append('') + result.append(' rankdir=LR;') + result.append(' {0} [shape=Mrecord, label="{1}"];'.format(dot_escape(comp.type_name), comp.type_name)) + for p in comp.ports: + if p.porttype == 'DataInPort': + pname = dot_port_name(p.name) + result.append(' {0} [shape=plaintext, label="{1}"];'.format(dot_escape(pname), pname)) + result.append(' {0} -> {1};'.format(dot_escape(pname), dot_escape(comp.type_name))) + elif p.porttype == 'DataOutPort': + pname = dot_port_name(p.name) + result.append(' {0} [shape=plaintext, label="{1}"];'.format(dot_escape(pname), pname)) + result.append(' {0} -> {1};'.format(dot_escape(comp.type_name), dot_escape(pname))) + return result + + +def get_section_title(sec): + if sec == 'intro': + return 'Introduction' + elif sec == 'reqs': + return 'Pre-requisites' + elif sec == 'install': + return 'Installation' + elif sec == 'usage': + return 'Usage' + elif sec == 'misc': + return 'Miscellaneous' + elif sec == 'changelog': + return 'Changelog' + else: + return sec + + +def do_section(result, comp, doc_set, sec, options): + if sec == 'ports' and comp.ports: + result += section('Ports', 1) + result += get_ports_docs(comp) + result.append('') + if options.graph == True: + result += make_comp_graph(comp) + result.append('') + elif (sec == 'config' and + 'default' in comp.conf_sets and comp.conf_sets['default'].data): + result += section('Configuration parameters', 1) + result += get_config_docs(comp) + result.append('') + elif doc_set and doc_set.has_param(sec): + title = get_section_title(sec) + body = doc_set.data[sec] + result += section(title, 1) + result.append(doc_set.data[sec]) + result.append('') + + +def get_comp_docs(comp, tree, options): + result = [] + result += section(comp.type_name, 0) + result.append(comp.description) + result.append('') + + result.append(':Vendor: {0}'.format(comp.vendor)) + result.append(':Version: {0}'.format(comp.version)) + result.append(':Category: {0}'.format(comp.category)) + + doc_set = None + order = ['intro', 'reqs', 'install', 'usage', 'ports', 'config', 'misc', + 'changelog'] + sections = ['ports', 'config'] + if '__doc__' in comp.conf_sets: + doc_set = comp.conf_sets['__doc__'] + if doc_set.has_param('__order__') and doc_set.data['__order__']: + order = doc_set.data['__order__'].split(',') + sections += [k for k in doc_set.data.keys() if not k.startswith('__')] + + if doc_set: + if doc_set.has_param('__license__'): + result.append(':License: {0}'.format( + comp.conf_sets['__doc__'].data['__license__'])) + if doc_set.has_param('__contact__'): + result.append(':Contact: {0}'.format( + comp.conf_sets['__doc__'].data['__contact__'])) + if doc_set.has_param('__url__'): + result.append(':URL: {0}'.format( + comp.conf_sets['__doc__'].data['__url__'])) + result.append('') + + # Add sections specified in the ordering first + for s in order: + if s not in sections: + if doc_set: + print >>sys.stderr, ('{0}: Unknown section in order: ' + '{1}'.format(os.path.basename(sys.argv[0]), s)) + continue + do_section(result, comp, doc_set, s, options) + + # Add any sections that were not in the ordering last + for s in [s for s in sections if s not in order]: + do_section(result, comp, doc_set, s, options) + + return result + + +def get_docs(cmd_path, full_path, options, tree=None): + path, port = rtctree.path.parse_path(full_path) + if not path[-1]: + # There was a trailing slash + raise rts_exceptions.NotAComponentError(cmd_path) + if port: + raise rts_exceptions.NotAComponentError(cmd_path) + + if not tree: + tree = rtctree.tree.RTCTree(paths=path) + + if not tree.has_path(path): + raise rts_exceptions.NoSuchObjectError(cmd_path) + object = tree.get_node(path) + + if object.is_component: + return get_comp_docs(object, tree, options) + elif object.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_path) + else: + raise rts_exceptions.NotAComponentError(cmd_path) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Display component documentation.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-f', '--format', dest='format', type='choice', + choices=('rst', 'html', 'latex'), default='html', + help='Output format (one of "rst", "html" or "latex"). ' + '[Default: %default]') + parser.add_option('-g', '--graph', dest='graph', action='store_true', + default=False, + help='Draw component graph. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if not args: + # If no path given then can't do anything. + print >>sys.stderr, '{0}: No component specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + elif len(args) == 1: + cmd_path = args[0] + else: + print >>sys.stderr, usage + return 1 + full_path = path.cmd_path_to_full_path(cmd_path) + + try: + docs = '\n'.join(get_docs(cmd_path, full_path, options, tree=tree)) + if options.format == 'rst': + print docs + else: + print docutils.core.publish_string(docs, writer_name=options.format) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtexit.py b/rtshell/rtexit.py new file mode 100644 index 0000000..fd8c6fc --- /dev/null +++ b/rtshell/rtexit.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to make a component exit. + +''' + + +import optparse +import os +import os.path +import rtctree.tree +import rtctree.path +import RTC +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def exit_target(cmd_path, full_path, options, tree=None): + path, port = rtctree.path.parse_path(full_path) + if port: + raise rts_exceptions.NotAComponentError(cmd_path) + + trailing_slash = False + if not path[-1]: + raise rts_exceptions.NotAComponentError(cmd_path) + + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + if not tree.has_path(path): + raise rts_exceptions.NoSuchObjectError(cmd_path) + object = tree.get_node(path) + if object.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_path) + if not object.is_component: + raise rts_exceptions.NotAComponentError(cmd_path) + + object.exit() + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Make a component exit.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if not args: + # If no path given then can't do anything. + print >>sys.stderr, '{0}: No component specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + elif len(args) == 1: + cmd_path = args[0] + else: + print >>sys.stderr, usage + return 1 + full_path = path.cmd_path_to_full_path(cmd_path) + + try: + exit_target(cmd_path, full_path, options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtfind.py b/rtshell/rtfind.py new file mode 100644 index 0000000..0264c7d --- /dev/null +++ b/rtshell/rtfind.py @@ -0,0 +1,171 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to find components, managers, etc. + +''' + + +import optparse +import os +import os.path +import re +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def search(cmd_path, full_path, options, tree=None): + def get_result(node, args): + if node.full_path_str.startswith(cmd_path): + result = node.full_path_str[len(cmd_path):] + if not result: + # This will happen if the search root is a component + return node.name + return node.full_path_str + else: + return node.full_path_str + + + def matches_search(node): + # Filter out types + if options.type: + if node.is_component and 'c' not in options.type: + return False + if node.is_manager and 'm' not in options.type and \ + 'd' not in options.type: + return False + if node.is_nameserver and 'n' not in options.type and \ + 'd' not in options.type: + return False + if node.is_directory and 'd' not in options.type and \ + (not node.is_nameserver and not node.is_manager): + return False + if node.is_zombie and 'z' not in options.type: + return False + # Filter out depth + if max_depth > 0 and node.depth > max_depth: + return False + if not name_res: + return True + # Check for name matches + for name_re in name_res: + if name_re.search(node.full_path_str): + return True + return False + + path, port = rtctree.path.parse_path(full_path) + if port: + raise rts_exceptions.NotADirectoryError(cmd_path) + + trailing_slash = False + if not path[-1]: + # There was a trailing slash + trailing_slash = True + path = path[:-1] + + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + # Find the root node of the search + root = tree.get_node(path) + if not root: + raise rts_exceptions.NoSuchObjectError(cmd_path) + if root.is_component and trailing_slash: + raise rts_exceptions.NotADirectoryError(cmd_path) + + if options.max_depth: + max_depth = options.max_depth + len(path) - 1 # The root is 1-long + else: + max_depth = 0 + + name_res = [] + for name in options.name: + # Replace regex special characters + name = re.escape (name) + # * goes to .*? + name = name.replace (r'\*', '.*?') + # ? goes to . + name = name.replace (r'\?', r'.') + name_res.append(re.compile(name)) + for name in options.iname: + # Replace regex special characters + name = re.escape (name) + # * goes to .*? + name = name.replace (r'\*', '.*?') + # ? goes to . + name = name.replace (r'\?', r'.') + name_res.append(re.compile(name, re.IGNORECASE)) + + return root.iterate(get_result, filter=[matches_search]) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Find entries in the RTC tree matching given constraints.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-i', '--iname', dest='iname', action='append', + type='string', default=[], help='Case-insensitive name pattern. ' + 'This option can be specified multiple times.') + parser.add_option('-m', '--maxdepth', dest='max_depth', action='store', + type='int', default=0, help='Maximum depth to search down to in ' + 'the tree. Set to 0 to disable. [Default: %default]') + parser.add_option('-n', '--name', dest='name', action='append', + type='string', default=[], help='Case-sensitive name pattern. ' + 'This option can be specified multiple times.') + parser.add_option('-t', '--type', dest='type', action='store', + type='string', default='', help='Type of object: c (component), ' + 'd (directory), m (manager), n (name server), z (zombie). ' + 'Multiple types can be specified in a single entry, e.g. ' + '"--type=dmn".') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1, [] + + if len(args) == 1: + cmd_path = args[0] + else: + print >>sys.stderr, usage + return 1, [] + full_path = path.cmd_path_to_full_path(cmd_path) + + matches = [] + try: + matches = search(cmd_path, full_path, options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1, [] + return 0, matches + + +# vim: tw=79 + diff --git a/rtshell/rtinject.py b/rtshell/rtinject.py new file mode 100644 index 0000000..428d139 --- /dev/null +++ b/rtshell/rtinject.py @@ -0,0 +1,185 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to print data sent by ports to the console. + +''' + + +import optparse +import os.path +import rtctree.tree +import rtctree.utils +import sys +import threading +import time +import traceback +import OpenRTM_aist +import RTC + +import comp_mgmt +import modmgr +import path +import port_types +import rtinject_comp +import rtshell + + +def write_to_ports(raw_paths, options, tree=None): + event = threading.Event() + + mm = modmgr.ModuleMgr(verbose=options.verbose, paths=options.paths) + mm.load_mods_and_poas(options.modules) + if options.verbose: + print >>sys.stderr, \ + 'Pre-loaded modules: {0}'.format(mm.loaded_mod_names) + + if options.const: + val = mm.evaluate(options.const) + if options.verbose: + print >>sys.stderr, 'Evaluated value to {0}'.format(val) + else: + if options.verbose: + print >>sys.stderr, 'Reading values from stdin.' + + if options.timeout == -1: + max = options.max + if options.verbose: + print >>sys.stderr, 'Will run {0} times.'.format(max) + else: + max = -1 + if options.verbose: + print >>sys.stderr, 'Will stop after {0}s'.format(options.timeout) + + targets = port_types.parse_targets(raw_paths) + if not tree: + paths = [t[0] for t in targets] + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + port_specs = port_types.make_port_specs(targets, mm, tree) + port_types.require_all_output(port_specs) + if options.verbose: + print >>sys.stderr, \ + 'Port specifications: {0}'.format([str(p) for p in port_specs]) + + if options.const: + comp_name, mgr = comp_mgmt.make_comp('rtinject_writer', tree, + rtinject_comp.Writer, port_specs, event=event, rate=options.rate, + max=max, val=val) + else: + buffer = [] + mutex = threading.RLock() + comp_name, mgr = comp_mgmt.make_comp('rtinject_writer', tree, + rtinject_comp.StdinWriter, port_specs, event=event, + rate=options.rate, max=max, buf=buffer, mutex=mutex) + if options.verbose: + print >>sys.stderr, 'Created component {0}'.format(comp_name) + comp = comp_mgmt.find_comp_in_mgr(comp_name, mgr) + comp_mgmt.connect(comp, port_specs, tree) + comp_mgmt.activate(comp) + if options.const: + try: + if options.timeout != -1: + event.wait(options.timeout) + elif options.max > -1: + event.wait() + else: + raw_input() + except KeyboardInterrupt: + pass + except EOFError: + pass + else: + # Read stdin until we receive max number of values or Ctrl-C is hit + val_cnt = 0 + try: + while val_cnt < max or max < 0: + l = sys.stdin.readline() + if not l: + break + if l[0] == '#': + continue + val = mm.evaluate(l) + with mutex: + buffer.append(val) + val_cnt += 1 + except KeyboardInterrupt: + pass + # Wait until the buffer has been cleared + while True: + with mutex: + if not buffer: + break + comp_mgmt.disconnect(comp) + comp_mgmt.deactivate(comp) + tree.give_away_orb() + del tree + comp_mgmt.shutdown(mgr) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] : [:...] +Write a constant value to one or more ports.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-c', '--const', dest='const', action='store', + type='string', default='', + help='The constant value to send, as a Python expression. If ' + 'not specified, values will be read from standard in.') + parser.add_option('-m', '--mod', dest='modules', action='append', + type='string', default=[], + help='Extra modules to import. If automatic module loading ' + 'struggles with your data types, try listing the modules here. ' + 'The module and its __POA partner will be imported.') + parser.add_option('-n', '--number', dest='max', action='store', + type='int', default='1', + help='Specify the number of times to write to the port. ' + '[Default: %default]') + parser.add_option('-p', '--path', dest='paths', action='append', + type='string', default=[], + help='Extra module search paths to add to the PYTHONPATH.') + parser.add_option('-r', '--rate', dest='rate', action='store', + type='float', default=1.0, + help='Specify the rate in Hertz at which to emit data. ' + '[Default: %default]') + parser.add_option('-t', '--timeout', dest='timeout', action='store', + type='float', default=-1, help='Write data for this many seconds, ' + 'then stop. This option overrides --number. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if len(args) < 1: + print >>sys.stderr, usage + return 1 + + try: + write_to_ports([path.cmd_path_to_full_path(p) \ + for p in args], options, tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + diff --git a/rtshell/rtinject_comp.py b/rtshell/rtinject_comp.py new file mode 100644 index 0000000..36ad2b2 --- /dev/null +++ b/rtshell/rtinject_comp.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Writer component used by rtinject + +''' + + +import gen_comp + +import OpenRTM_aist +import RTC +import sys + + +############################################################################### +## Writer component for rtinject + +class Writer(gen_comp.GenComp): + def __init__(self, mgr, port_specs, val=None, *args, **kwargs): + gen_comp.GenComp.__init__(self, mgr, port_specs, *args, **kwargs) + self._val = val + + def _behv(self, ec_id): + for p in self._ports.values(): + p.port.write(self._val) + return RTC.RTC_OK, 1 + + +############################################################################### +## From-standard-input writer component for rtinject + +class StdinWriter(Writer): + def __init__(self, mgr, port_specs, buf=None, mutex=None, *args, + **kwargs): + Writer.__init__(self, mgr, port_specs, *args, **kwargs) + if buf is None: + raise ValueError('buf cannot be None.') + if mutex is None: + raise ValueError('mutex cannot be None.') + self._val_buffer = buf + self._mutex = mutex + + def _behv(self, ec_id): + with self._mutex: + if self._val_buffer: + self._val = self._val_buffer.pop(0) + result = Writer._behv(self, ec_id) + return result + else: + return RTC.RTC_OK, 0 + diff --git a/rtshell/rtlog.py b/rtshell/rtlog.py new file mode 100644 index 0000000..fc6af47 --- /dev/null +++ b/rtshell/rtlog.py @@ -0,0 +1,403 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the logging command. + +''' + + +import optparse +import os +import os.path +import rtctree.tree +import rtctree.utils +import sys +import threading +import time +import traceback +import OpenRTM_aist +import RTC + +import comp_mgmt +import modmgr +import path +import port_types +import rtlog_comps +import rts_exceptions +import rtshell +import simpkl_log +import text_log + + +def record_log(raw_paths, options, tree=None): + event = threading.Event() + + if options.end is not None and options.end < 0: + raise rts_exceptions.BadEndPointError + if options.end is None and options.index: + print >>sys.stderr, '{0}: WARNING: --index has no effect without '\ + '--end'.format(os.path.basename(sys.argv[0])) + + mm = modmgr.ModuleMgr(verbose=options.verbose, paths=options.paths) + mm.load_mods_and_poas(options.modules) + if options.verbose: + print >>sys.stderr, \ + 'Pre-loaded modules: {0}'.format(mm.loaded_mod_names) + + if options.timeout is not None: + print >>sys.stderr, 'Recording for {0}s.'.format(options.timeout) + else: + if options.end is not None: + if options.index: + print >>sys.stderr, 'Recording {0} entries.'.format( + int(options.end)) + else: + end_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(options.end)) + print >>sys.stderr, 'Recording until {0} ({1}).'.format( + end_str, options.end) + + if options.logger == 'simpkl': + l_type = simpkl_log.SimplePickleLog + elif options.logger == 'text': + l_type = text_log.TextLog + else: + raise rts_exceptions.BadLogTypeError(options.logger) + + sources = port_types.parse_targets(raw_paths) + if not tree: + paths = [s[0] for s in sources] + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + port_specs = port_types.make_port_specs(sources, mm, tree) + port_types.require_all_input(port_specs) + if options.verbose: + print >>sys.stderr, \ + 'Port specifications: {0}'.format([str(p) for p in port_specs]) + + if options.end is None: + end = -1 # Send -1 as the default + else: + end = options.end + comp_name, mgr = comp_mgmt.make_comp('rtlog_recorder', tree, + rtlog_comps.Recorder, port_specs, event=event, + logger_type=l_type, filename=options.filename, + lims_are_ind=options.index, end=end, + verbose=options.verbose, rate=options.exec_rate) + if options.verbose: + print >>sys.stderr, 'Created component {0}'.format(comp_name) + try: + comp = comp_mgmt.find_comp_in_mgr(comp_name, mgr) + comp_mgmt.connect(comp, port_specs, tree) + comp_mgmt.activate(comp) + except Exception, e: + #comp_mgmt.shutdown(mgr) + raise e + try: + if options.timeout is not None: + event.wait(options.timeout) + comp_mgmt.disconnect(comp) + comp_mgmt.deactivate(comp) + elif options.end is not None: + event.wait() + comp_mgmt.disconnect(comp) + comp_mgmt.deactivate(comp) + else: + while True: + raw_input() + # The manager will catch the Ctrl-C and shut down itself, so don't + # disconnect/deactivate the component + except KeyboardInterrupt: + pass + except EOFError: + pass + tree.give_away_orb() + del tree + comp_mgmt.shutdown(mgr) + + +def play_log(raw_paths, options, tree=None): + event = threading.Event() + + if not options.filename: + raise rts_exceptions.NoLogFileNameError + if options.start is not None and options.start < 0: + raise rts_exceptions.BadStartPointError + if options.end is not None and options.end < 0: + raise rts_exceptions.BadEndPointError + if options.end is None and options.start is None and options.index: + print >>sys.stderr, '{0}: WARNING: --index has no effect without '\ + '--start or --end'.format(os.path.basename(sys.argv[0])) + + mm = modmgr.ModuleMgr(verbose=options.verbose, paths=options.paths) + mm.load_mods_and_poas(options.modules) + if options.verbose: + print >>sys.stderr, \ + 'Pre-loaded modules: {0}'.format(mm.loaded_mod_names) + + if options.timeout is not None: + print >>sys.stderr, 'Playing for {0}s.'.format(options.timeout) + else: + if options.end is not None: + if options.start is not None: + if options.index: + print >>sys.stderr, 'Playing from entry {0} to entry '\ + '{1}.'.format(int(options.start), int(options.end)) + else: + start_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(options.start)) + end_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(options.end)) + print >>sys.stderr, 'Playing from {0} ({1}) until {2} '\ + '({3}).'.format(start_str, options.start, end_str, + options.end) + else: + if options.index: + print >>sys.stderr, 'Playing {0} entries.'.format( + int(options.end)) + else: + end_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(options.end)) + print >>sys.stderr, 'Playing until {0} ({1}).'.format( + end_str, options.end) + elif options.start is not None: + if options.index: + print >>sys.stderr, 'Playing from entry {0}.'.format( + int(options.start)) + else: + start_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(options.start)) + print >>sys.stderr, 'Playing from {0} ({1}).'.format(start_str, + options.start) + + if options.logger == 'simpkl': + l_type = simpkl_log.SimplePickleLog + elif options.logger == 'text': + raise rts_exceptions.UnsupportedLogTypeError('text', 'playback') + else: + raise rts_exceptions.BadLogTypeError(options.logger) + + targets = port_types.parse_targets(raw_paths) + if not tree: + paths = [t[0] for t in targets] + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + port_specs = port_types.make_port_specs(targets, mm, tree) + if options.verbose: + print >>sys.stderr, \ + 'Port specifications: {0}'.format([str(p) for p in port_specs]) + port_types.require_all_output(port_specs) + + if options.start is None: + start = 0 # Send 0 as the default + else: + start = options.start + if options.end is None: + end = -1 # Send -1 as the default + else: + end = options.end + comp_name, mgr = comp_mgmt.make_comp('rtlog_player', tree, + rtlog_comps.Player, port_specs, event=event, logger_type=l_type, + filename=options.filename, lims_are_ind=options.index, start=start, + end=end, scale_rate=options.rate, abs_times=options.abs_times, + ignore_times=options.ig_times, verbose=options.verbose, + rate=options.exec_rate) + if options.verbose: + print >>sys.stderr, 'Created component {0}'.format(comp_name) + comp = comp_mgmt.find_comp_in_mgr(comp_name, mgr) + comp_mgmt.connect(comp, port_specs, tree) + comp_mgmt.activate(comp) + try: + if options.timeout is not None: + event.wait(options.timeout) + comp_mgmt.disconnect(comp) + try: + comp_mgmt.deactivate(comp) + except rts_exceptions.DeactivateError: + # Don't care about this because the component will be shut down + # soon anyway + pass + #elif options.end is not None: + else: + event.wait() + comp_mgmt.disconnect(comp) + try: + comp_mgmt.deactivate(comp) + except rts_exceptions.DeactivateError: + # Don't care about this because the component will be shut down + # soon anyway + pass + #else: + #while True: + #raw_input() + # The manager will catch the Ctrl-C and shut down itself, so don't + # disconnect/deactivate the component + except KeyboardInterrupt: + pass + except EOFError: + pass + tree.give_away_orb() + del tree + comp_mgmt.shutdown(mgr) + + +def display_info(options): + if not options.filename: + raise rts_exceptions.NoLogFileNameError + + if options.logger == 'simpkl': + l_type = simpkl_log.SimplePickleLog + elif options.logger == 'text': + raise rts_exceptions.UnsupportedLogTypeError('text', 'inspection') + else: + raise rts_exceptions.BadLogTypeError(options.logger) + + mm = modmgr.ModuleMgr(verbose=options.verbose, paths=options.paths) + mm.load_mods_and_poas(options.modules) + if options.verbose: + print >>sys.stderr, \ + 'Pre-loaded modules: {0}'.format(mm.loaded_mod_names) + + statinfo = os.stat(options.filename) + size = statinfo.st_size + if size > 1024 * 1024 * 1024: # GiB + size_str = '{0:.2f}GiB ({1}B)'.format(size / (1024.0 * 1024 * 1024), size) + elif size > 1024 * 1024: # MiB + size_str = '{0:.2f}MiB ({1}B)'.format(size / (1024.0 * 1024), size) + elif size > 1024: # KiB + size_str = '{0:.2f}KiB ({1}B)'.format(size / 1024.0, size) + else: + size_str = '{0}B'.format(size) + log = l_type(filename=options.filename, mode='r', verbose=options.verbose) + + start_time, port_specs = log.metadata + start_time_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(start_time)) + first_ind, first_time = log.start + first_time_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(first_time.float)) + end_ind, end_time = log.end + end_time_str = time.strftime('%Y-%m-%d %H:%M:%S', + time.localtime(end_time.float)) + + print 'Name: {0}'.format(options.filename) + print 'Size: ' + size_str + print 'Start time: {0} ({1})'.format(start_time_str, start_time) + print 'First entry time: {0} ({1})'.format(first_time_str, first_time) + print 'End time: {0} ({1})'.format(end_time_str, end_time) + print 'Number of entries: {0}'.format(end_ind + 1) + for ii, p in enumerate(port_specs): + print 'Channel {0}'.format(ii + 1) + print ' Name: {0}'.format(p.name) + print ' Data type: {0} ({1})'.format(p.type_name, p.type) + print ' Sources:' + for r in p.raw: + print ' {0}'.format(r) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] : [:...] +Record data from output ports, or replay data into input ports.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-a', '--absolute-times', dest='abs_times', + action='store_true', default=False, + help='Times from the logged data are sent as recorded during ' + 'replay, rather than adjusted to the current timeframe. ' + '[Default: %default]') + parser.add_option('-d', '--display-info', dest='display_info', + action='store_true', default=False, help='Display the log ' + 'information and exit.') + parser.add_option('-e', '--end', dest='end', action='store', type='float', + default=None, + help='Time or entry index to stop recording or playback. Must be ' + 'within the bounds of the log. Specify -1 to record forever or ' + 'replay to the end of the log. Use --index to specify that this ' + 'value is an index. [Default: %default]') + parser.add_option('-f', '--filename', dest='filename', action='store', + type='string', default='', help='File name of the log file to ' + 'record to/playback from. If not specified for recording, a ' + 'default will be created based on the current time. Must be ' + 'specified for playback.') + parser.add_option('--path', dest='paths', action='append', type='string', + default=[], help='Extra module search paths to add to the ' + 'PYTHONPATH.') + parser.add_option('-i', '--index', dest='index', action='store_true', + default=False, help='Interpret the start and end values as entry ' + 'indices. [Default: %default]') + parser.add_option('-l', '--logger', dest='logger', action='store', + type='string', default='simpkl', help='The type of logger to ' + 'use. The default is the SimplePickle logger. Alternatively, ' + 'the text logger (specify using "text") may be used. The text ' + 'logger does not support playback.') + parser.add_option('-m', '--mod', dest='modules', action='append', + type='string', default=[], + help='Extra modules to import. If automatic module loading ' + 'struggles with your data types, try listing the modules here. ' + 'The module and its __POA partner will be imported.') + parser.add_option('-n', '--ignore-times', dest='ig_times', + action='store_true', default=False, help='Ignore the log ' + 'timestamps and play back a fixed number of entries per ' + 'execution. Use --rate to change the number played back per ' + 'execution. The value of --rate will be treated as an integer ' + 'in this case.') + parser.add_option('-p', '--play', dest='play', action='store_true', + default=False, help='Replay mode. [Default: %default]') + parser.add_option('-r', '--rate', dest='rate', action='store', + type='float', default=1.0, + help='Scale the playback speed of the log. [Default: %default]') + parser.add_option('-s', '--start', dest='start', action='store', + type='float', default=None, + help='Time or entry index to start playback from. Must be within ' + 'the bounds of the log. Use --index to specify that this value ' + 'is an index. [Default: %default]') + parser.add_option('-t', '--timeout', dest='timeout', action='store', + type='float', default=None, help='Record/replay data for this ' + 'many seconds. This option overrides --start/--end.') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-x', '--exec-rate', dest='exec_rate', action='store', + type='float', default=100.0, + help='Specify the rate in Hertz at which to run the component. ' + '[Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if len(args) < 1 and not options.display_info: + print >>sys.stderr, usage + return 1 + + try: + if options.display_info: + display_info(options) + elif options.play: + play_log([path.cmd_path_to_full_path(p) for p in args], + options, tree) + else: + record_log([path.cmd_path_to_full_path(p) for p in args], + options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + diff --git a/rtshell/rtlog_comps.py b/rtshell/rtlog_comps.py new file mode 100644 index 0000000..0e8b5a0 --- /dev/null +++ b/rtshell/rtlog_comps.py @@ -0,0 +1,271 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Log recording and playing components used by rtlog + +''' + + +import OpenRTM_aist +import os.path +import RTC +import sys +import time +import traceback + +import gen_comp +import ilog +import rts_exceptions + + +############################################################################### +## Recorder component for rtlog + +class Recorder(gen_comp.GenComp): + def __init__(self, mgr, port_specs, logger_type=None, filename='', + lims_are_ind=False, end=-1, verbose=False, *args, **kwargs): + if lims_are_ind: + max = end + self._end = -1 + else: + max = -1 + self._end = end + try: + del kwargs['max'] + except KeyError: + pass + gen_comp.GenComp.__init__(self, mgr, port_specs, max=max, *args, + **kwargs) + self._logger_type = logger_type + self._fn = filename + self._verb = verbose + + def onActivated(self, ec_id): + start = time.time() + # Add activated time to meta data + # Add port specs to meta data (include names) + meta = (start, self._port_specs) + # Make file name from activated time + if not self._fn: + self._fn = 'rtlog_{0}.rtlog'.format(int(start)) + # Create log, record meta data + self._l = self._logger_type(filename=self._fn, mode='w', meta=meta, verbose=self._verb) + return RTC.RTC_OK + + def onFinalize(self): + # Finalise and close log + self._l.close() + return RTC.RTC_OK + + def _behv(self, ec_id): + execed = 0 + result = RTC.RTC_OK + for name in self._ports: + p = self._ports[name] + if p.port.isNew(): + execed += 1 + p.read() + ts = self._log(p, name) + if self._end > -1 and ts >= self._end: + # Reached the end time + self._set() + if self._max > -1 and self._count >= self._max: + # Reached the max entries + return result, execed + return result, execed + + def _log(self, port, port_name): + if port.standard_type: + ts = ilog.EntryTS(sec=port.data.tm.sec, nsec=port.data.tm.nsec) + else: + ts = ilog.EntryTS(time=time.time()) + self._l.write(ts, (port_name, port.data)) + return ts + + +############################################################################### +## Player component for rtlog + +class Player(gen_comp.GenComp): + def __init__(self, mgr, port_specs, logger_type=None, filename='', + lims_are_ind=False, start=0, end=-1, scale_rate=1.0, abs_times=False, + ignore_times=False, verbose=False, *args, **kwargs): + if end >= 0: + if lims_are_ind: + if start == 0: + max = end + else: + max = end - (start - 1) + self._end = -1 + else: + max = -1 + self._end = end + else: + self._end = -1 + max = -1 + self._lims_ind = lims_are_ind + self._start = start + try: + del kwargs['max'] + except KeyError: + pass + gen_comp.GenComp.__init__(self, mgr, port_specs, max=max, *args, + **kwargs) + self._logger_type = logger_type + self._fn = filename + self._rate = scale_rate + self._abs = abs_times + self._ig_times = ignore_times + self._verb = verbose + + def onActivated(self, ec_id): + try: + self._l = self._logger_type(filename=self._fn, mode='r', + verbose=self._verb) + # Read the metadata block + start, log_port_specs = self._l.metadata + self._vprint('Log started at {0}'.format(start)) + self._vprint('Log port specs are {0}'.format( + [str(s) for s in log_port_specs])) + + # Check ports match + for name in self._ports: + matches = [s for s in log_port_specs if s.name == name] + if len(matches) == 0: + print >>sys.stderr, 'WARNING: Port {0} not found in '\ + 'log.'.format(name) + continue + elif len(matches) != 1: + print >>sys.stderr, 'WARNING: Port {0} occurs multiple '\ + 'times in the log.'.format(name) + continue + m = matches[0] + if m.type != self._ports[name].raw.type: + print >>sys.stderr, 'ERROR: Port {0} is incorrect data '\ + 'type; should be {1}.'.format(name, + type(self._ports[name].data)) + self._set() + return RTC.RTC_ERROR + + # Sanity-check the end time + if self._end >= 0 and self._end < self._l.start[1]: + print >>sys.stderr, 'WARNING: Specified end time is before '\ + 'the first entry time.' + + self._start_time = time.time() + # Fast-forward to the start time (with a sanity-check) + if self._start > 0: # If 0 index, already there; if 0 time... hmm + if self._lims_ind: + if self._start > self._l.end[0]: + print >>sys.stderr, 'ERROR: Specified start index is '\ + 'after the last entry index.' + self._set() + return RTC.RTC_ERROR + self._l.seek(index=self._start) + self._log_start = self._l.pos[1].float + else: + if self._start > self._l.end[1]: + print >>sys.stderr, 'ERROR: Specified start time is '\ + 'after the last entry time.' + self._set() + return RTC.RTC_ERROR + self._l.seek(timestamp=self._start) + self._log_start = self._l.pos[1].float + else: + self._log_start = start + self._offset = self._start_time - self._log_start + self._vprint('Play start time is {0}, log start time is {1}'.format( + self._start_time, self._log_start)) + self._vprint('Time offset is {0}'.format(self._offset)) + except: + traceback.print_exc() + return RTC.RTC_ERROR + return RTC.RTC_OK + + def onDeactivated(self, ec_id): + # Close log + self._l.close() + return RTC.RTC_OK + + def _behv(self, ec_id): + execed = 0 + result = RTC.RTC_OK + try: + if self._ig_times: + # Read self._rate items from the log and write them + for ii in range(int(self._rate)): + self._vprint('Playing {0} entries.'.format(int(self._rate))) + if not self._pub_log_item(): + print >>sys.stderr, '{0}: End of log reached.'.format( + os.path.basename(sys.argv[0])) + self._set() + result = RTC.RTC_ERROR + else: + execed += 1 + else: + # Calculate the current time in log-time + now = (((time.time() - self._start_time) * self._rate) + + self._log_start) + self._vprint('Current time in logspace is {0}'.format(now)) + if self._end >= 0 and now > self._end: + self._vprint('Reached end time (current position: '\ + '{0}).'.format(self._l.pos)) + self._set() + return RTC.RTC_OK, 0 + # Read until past it - read one at a time to avoid huge memory + # spikes if the log contains large-sized data + while self._l.pos[1] <= now: + if self._max > -1 and execed >= self._max: + self._vprint( + 'Reached maximum number of results to play.') + self._set() + break + if self._end >= 0 and self._l.pos[1] > self._end: + self._vprint('Reached end time (current position: '\ + '{0}).'.format(self._l.pos)) + self._set() + break + if not self._pub_log_item(): + print >>sys.stderr, '{0}: End of log reached.'.format( + os.path.basename(sys.argv[0])) + self._set() + result = RTC.RTC_ERROR + break + else: + execed += 1 + except: + traceback.print_exc() + return RTC.RTC_ERROR, 0 + return result, execed + + def _pub_log_item(self): + # Read an item from the log file + entries = self._l.read() + if len(entries) == 0: + return False # End of file + index, ts, entry = entries[0] + p_name, data = entry + if p_name in self._ports: + if not self._abs and self._ports[p_name].standard_type: + data.tm.sec += int(self._offset) + data.tm.nsec += int((self._offset % 1) * 1000000000) + self._ports[p_name].port.write(data) + return True + + def _vprint(self, text): + if self._verb: + print >>sys.stderr, text + diff --git a/rtshell/rtls.py b/rtshell/rtls.py new file mode 100644 index 0000000..140b922 --- /dev/null +++ b/rtshell/rtls.py @@ -0,0 +1,356 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to list naming contexts. + +''' + + +import optparse +import os +import os.path +import rtctree.tree +import rtctree.path +import rtctree.utils +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def get_node_long_lines(nodes, use_colour=True): + info_strings = [] + state_width = 0 + total_width = 0 + in_width = 0 + out_width = 0 + svc_width = 0 + for node in nodes: + if node.is_directory: + if state_width == 0: + state_width = 1 + if total_width == 0: + total_width = 1 + if in_width == 0: + in_width = 1 + if out_width == 0: + out_width = 1 + if svc_width == 0: + svc_width = 1 + name = (rtctree.utils.build_attr_string(['bold', 'blue'], + supported=use_colour) + node.name + + rtctree.utils.build_attr_string(['reset'], + supported=use_colour)) + info_strings.append((('-', 0), ('-', 0), ('-', 0), + ('-', 0), ('-', 0), name)) + elif node.is_manager: + # Managers are not handled yet + if state_width == 0: + state_width = 1 + if total_width == 0: + total_width = 1 + if in_width == 0: + in_width = 1 + if out_width == 0: + out_width = 1 + if svc_width == 0: + svc_width = 1 + name = (rtctree.utils.build_attr_string(['bold', 'green'], + supported=use_colour) + node.name + + rtctree.utils.build_attr_string(['reset'], + supported=use_colour)) + info_strings.append((('-', 0), ('-', 0), ('-', 0), + ('-', 0), ('-', 0), name)) + elif node.is_component: + state = node.state + state_string = node.plain_state_string + if len(state_string) > state_width: + state_width = len(state_string) + state_string = (node.get_state_string(add_colour=use_colour), + len(node.get_state_string(add_colour=use_colour)) - \ + len(state_string)) + + num_ports = len(node.ports) + num_connected = len(node.connected_ports) + total_string = '{0}/{1}'.format(num_ports, num_connected) + if len(total_string) > total_width: + total_width = len(total_string) + coloured_string = (rtctree.utils.build_attr_string('bold', + supported=use_colour) + str(num_ports) + + rtctree.utils.build_attr_string('reset', + supported=use_colour) + '/' + str(num_connected)) + total_string = (coloured_string, + len(coloured_string) - len(total_string)) + + num_ports = len(node.inports) + num_connected = len(node.connected_inports) + in_string = '{0}/{1}'.format(num_ports, num_connected) + if len(in_string) > in_width: + in_width = len(in_string) + coloured_string = (rtctree.utils.build_attr_string('bold', + supported=use_colour) + str(num_ports) + + rtctree.utils.build_attr_string('reset', + supported=use_colour) + '/' + str(num_connected)) + in_string = (coloured_string, + len(coloured_string) - len(in_string)) + + num_ports = len(node.outports) + num_connected = len(node.connected_outports) + out_string = '{0}/{1}'.format(num_ports, num_connected) + if len(out_string) > out_width: + out_width = len(out_string) + coloured_string = (rtctree.utils.build_attr_string('bold', + supported=use_colour) + str(num_ports) + + rtctree.utils.build_attr_string('reset', + supported=use_colour) + '/' + str(num_connected)) + out_string = (coloured_string, len(coloured_string) - \ + len(out_string)) + + num_ports = len(node.svcports) + num_connected = len(node.connected_svcports) + svc_string = '{0}/{1}'.format(num_ports, num_connected) + if len(svc_string) > svc_width: + svc_width = len(svc_string) + coloured_string = (rtctree.utils.build_attr_string('bold', + supported=use_colour) + str(num_ports) + + rtctree.utils.build_attr_string('reset', + supported=use_colour) + '/' + str(num_connected)) + svc_string = (coloured_string, len(coloured_string) - \ + len(svc_string)) + + info_strings.append((state_string, total_string, in_string, + out_string, svc_string, node.name)) + elif node.is_zombie: + # Zombies are treated like unknowns, but tagged with * + if state_width == 0: + state_width = 1 + if total_width == 0: + total_width = 1 + if in_width == 0: + in_width = 1 + if out_width == 0: + out_width = 1 + if svc_width == 0: + svc_width = 1 + name = (rtctree.utils.build_attr_string(['faint', 'white'], + supported=use_colour) + '*' + node.name + + rtctree.utils.build_attr_string(['reset'], + supported=use_colour)) + info_strings.append((('-', 0), ('-', 0), ('-', 0), + ('-', 0), ('-', 0), name)) + else: + # Other types are unknowns + if state_width == 0: + state_width = 1 + if total_width == 0: + total_width = 1 + if in_width == 0: + in_width = 1 + if out_width == 0: + out_width = 1 + if svc_width == 0: + svc_width = 1 + name = (rtctree.utils.build_attr_string(['faint', 'white'], + supported=use_colour) + node.name + + rtctree.utils.build_attr_string(['reset'], + supported=use_colour)) + info_strings.append((('-', 0), ('-', 0), ('-', 0), + ('-', 0), ('-', 0), name)) + state_width += 2 + total_width += 2 + in_width += 2 + out_width += 2 + svc_width += 2 + + result = [] + for string in info_strings: + result.append('{0}{1}{2}{3}{4}{5}'.format( + string[0][0].ljust(state_width + string[0][1]), + string[1][0].ljust(total_width + string[1][1]), + string[2][0].ljust(in_width + string[2][1]), + string[3][0].ljust(out_width + string[3][1]), + string[4][0].ljust(svc_width + string[4][1]), + string[5])) + return result + + +def format_items_list(items): + gap = ' ' + term_rows, term_cols = rtctree.utils.get_terminal_size() + nrows, ncols, col_widths = rtctree.utils.get_num_columns_and_rows( + [len(ii[1]) for ii in items], len(gap), term_cols) + rows = [items[s:s + ncols] for s in range(0, len(items), ncols)] + lines = [] + for r in rows: + new_line = '' + for ii, c in enumerate(r): + new_line += '{0:{1}}'.format(c[0], col_widths[ii] + \ + (len(c[0]) - len(c[1]))) + gap + lines.append(new_line.rstrip()) + return lines + + +def list_directory(dir_node, long=False): + listing = dir_node.children + use_colour = rtctree.utils.colour_supported(sys.stdout) + if long: + lines = get_node_long_lines(listing, use_colour=use_colour) + return lines + else: + items = [] + for entry in listing: + if entry.is_directory: + items.append((rtctree.utils.build_attr_string(['bold', 'blue'], + supported=use_colour) + entry.name + '/' + \ + rtctree.utils.build_attr_string(['reset'], + supported=use_colour), entry.name)) + elif entry.is_component: + items.append((entry.name, entry.name)) + elif entry.is_manager: + items.append((rtctree.utils.build_attr_string(['bold', + 'green'], supported=use_colour) + entry.name + \ + rtctree.utils.build_attr_string(['reset'], + supported=use_colour), entry.name)) + elif entry.is_zombie: + items.append((rtctree.utils.build_attr_string(['faint', + 'white'], supported=use_colour) + '*' + entry.name + \ + rtctree.utils.build_attr_string(['reset'], + supported=use_colour), '*' + entry.name)) + else: + items.append((rtctree.utils.build_attr_string(['faint', + 'white'], supported=use_colour) + entry.name + \ + rtctree.utils.build_attr_string(['reset'], + supported=use_colour), entry.name)) + return format_items_list(items) + + +def list_target(cmd_path, full_path, options, tree=None): + use_colour = rtctree.utils.colour_supported(sys.stdout) + + path, port = rtctree.path.parse_path(full_path) + if port: + raise rts_exceptions.CannotDoToPortError('list') + + trailing_slash = False + if not path[-1]: + # There was a trailing slash + trailing_slash = True + path = path[:-1] + + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + if not tree.has_path(path): + raise rts_exceptions.NoSuchObjectError(cmd_path) + if tree.is_component(path) or tree.is_unknown(path) or \ + tree.is_zombie(path): + # Path points to a single object: print it like 'ls '. + if trailing_slash: + # If there was a trailing slash, complain that the object is not a + # directory. + raise rts_exceptions.NoSuchObjectError(cmd_path) + if options.long: + return get_node_long_lines([tree.get_node(path)], use_colour) + else: + if tree.is_component(path): + return [path[-1]] + elif tree.is_zombie(path): + return [(rtctree.utils.build_attr_string(['faint', 'white'], + supported=use_colour) + '*' + path[-1] + + rtctree.utils.build_attr_string(['reset'], + supported=use_colour))] + else: + # Assume unknown + return [(rtctree.utils.build_attr_string(['faint', 'white'], + supported=use_colour) + path[-1] + + rtctree.utils.build_attr_string(['reset'], + supported=use_colour))] + elif tree.is_directory(path): + # If recursing, need to list this directory and all its children + if options.recurse: + recurse_root = tree.get_node(path) + recurse_root_path = recurse_root.full_path_str + def get_name(node, args): + if node.full_path_str.startswith(recurse_root_path): + result = node.full_path_str[len(recurse_root_path):] + else: + result = node.full_path_str + return result.lstrip('/') + dir_names = ['.'] + recurse_root.iterate(get_name, + args=options.long, filter=['is_directory'])[1:] + listings = recurse_root.iterate(list_directory, + args=options.long, filter=['is_directory']) + result = [] + for dir, listing in zip(dir_names, listings): + if dir == '.': + result.append('.:') + else: + result.append('./' + dir + ':') + result += listing + result.append('') + return result + else: + dir_node = tree.get_node(path) + return list_directory(dir_node, options.long) + else: + raise rts_exceptions.UnknownObjectError(cmd_path) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [path] +List a name server, directory, manager or component.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-l', dest='long', action='store_true', default=False, + help='Use a long listing format.') + parser.add_option('-R', '--recurse', dest='recurse', action='store_true', + default=False, help='List recursively. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1, [] + + if not args: + cmd_path = '' + elif len(args) == 1: + cmd_path = args[0] + else: + print >>sys.stderr, usage + return 1, [] + full_path = path.cmd_path_to_full_path(cmd_path) + + result = [] + try: + result = list_target(cmd_path, full_path, options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1, [] + return 0, result + + +# vim: tw=79 + diff --git a/rtshell/rtmgr.py b/rtshell/rtmgr.py new file mode 100644 index 0000000..9732494 --- /dev/null +++ b/rtshell/rtmgr.py @@ -0,0 +1,223 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command for controlling managers. + +''' + + +import rtctree +import rtctree.exceptions +import rtctree.path +import rtctree.tree +import CosNaming +import omniORB +import optparse +import os +import os.path +import re +import OpenRTM_aist +import RTC +import RTM +import sys +import traceback + +import rtshell +import rts_exceptions +import path + + +class DirectManager(object): + def __init__(self, address): + self._connect(self._fix_address(address)) + + def _connect(self, address): + if rtctree.ORB_ARGS_ENV_VAR in os.environ: + orb_args = os.environ[ORB_ARGS_ENV_VAR].split(';') + else: + orb_args = [] + self._orb = omniORB.CORBA.ORB_init(orb_args) + try: + self._obj = self._orb.string_to_object(address) + except omniORB.CORBA.ORB.InvalidName: + raise rts_exceptions.BadMgrAddressError + try: + self._mgr = self._obj._narrow(RTM.Manager) + except omniORB.CORBA.TRANSIENT, e: + if e.args[0] == omniORB.TRANSIENT_ConnectFailed: + raise rts_exceptions.BadMgrAddressError + else: + raise + if omniORB.CORBA.is_nil(self._mgr): + raise rts_exceptions.FailedToNarrowError + + def _fix_address(self, address): + parts = address.split(':') + if len(parts) == 3: + # No port + host, sep, id_ = parts[2].partition('/') + if not id_: + # No ID + id_ = 'manager' + parts[2] = '{0}:2810/{1}'.format(host, id_) + elif len(parts) == 4: + # Have a port + port, sep, id_ = parts[3].partition('/') + if not id_: + # No ID + id_ = 'manager' + parts[3] = '{0}/{1}'.format(port, id_) + else: + raise rts_exceptions.BadMgrAddressError + return ':'.join(parts) + + def load_module(self, path, init_func): + try: + if self._mgr.load_module(path, init_func) != RTC.RTC_OK: + raise rtctree.exceptions.FailedToLoadModuleError(path) + except omniORB.CORBA.UNKNOWN, e: + if e.args[0] == UNKNOWN_UserException: + raise rtctree.exceptions.FailedToLoadModuleError(path, + 'CORBA User Exception') + else: + raise + + def unload_module(self, path): + if self._mgr.unload_module(path) != RTC.RTC_OK: + raise rtctree.exceptions.FailedToUnloadModuleError(path) + + def create_component(self, module_name): + if not self._mgr.create_component(module_name): + raise rtctree.exceptions.FailedToCreateComponentError(module_name) + + def delete_component(self, instance_name): + if not self._mgr.delete_component(instance_name) != RTC.RTC_OK: + raise rtctree.exceptions.FailedToDeleteComponentError(instance_name) + + +def get_manager(cmd_path, full_path, tree=None): + path, port = rtctree.path.parse_path(full_path) + if port: + raise rts_exceptions.NotAManagerError(cmd_path) + + if not path[-1]: + # There was a trailing slash - ignore it + path = path[:-1] + + if not tree: + tree = rtctree.tree.RTCTree(paths=path, filter=[path]) + + object = tree.get_node(path) + if not object: + raise rts_exceptions.NoSuchObjectError(cmd_path) + if object.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_path) + if not object.is_manager: + raise rts_exceptions.NotAManagerError(cmd_path) + return tree, object + +def load_module(mgr, module_info): + module_path, init_func = module_info + mgr.load_module(module_path, init_func) + + +def unload_module(mgr, module_path): + mgr.unload_module(module_path) + + +def create_component(mgr, module_name): + mgr.create_component(module_name) + + +def delete_component(mgr, instance_name): + mgr.delete_component(instance_name) + + +def main(argv=None, tree=None): + def cmd_cb(option, opt, val, parser): + if not hasattr(parser.values, 'cmds'): + setattr(parser.values, 'cmds', []) + if opt == '-l' or opt == '--load': + # Check the module path is correct before executing any commands + items = re.split(':([^/]+)', val) + if len(items) != 3: + raise optparse.OptionValueError('No initialisation function ' + 'specified.') + parser.values.cmds.append((load_module, items[0:2])) + elif opt == '-c' or opt == '--create': + parser.values.cmds.append((create_component, val)) + elif opt == '-d' or opt == '--delete': + parser.values.cmds.append((delete_component, val)) + elif opt == '-u' or opt == '--unload': + parser.values.cmds.append((unload_module, val)) + + usage = '''Usage: %prog [options] +Create and remove components with a manager.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-c', '--create', action='callback', callback=cmd_cb, + type='string', help='Create a new component instance from the ' + 'specified loaded module. Properties of the new component an be ' + 'specified after the module name prefixed with a question mark. ' + 'e.g. ConsoleIn?instance_name=bleg&another_param=value') + parser.add_option('-d', '--delete', action='callback', callback=cmd_cb, + type='string', help='Shut down and delete the specified component ' + 'instance.') + parser.add_option('-l', '--load', action='callback', callback=cmd_cb, + type='string', help='Load the module into the manager. An ' + 'initialisation function must be specified after the module path ' + 'separated by a ":".') + parser.add_option('-u', '--unload', action='callback', callback=cmd_cb, + type='string', help='Unload the module from the manager.') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + options, args = parser.parse_args() + + if len(args) != 1: + print >>sys.stderr, '{0}: No manager specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + + try: + if args[0].startswith('corbaloc::'): + # Direct connection to manager + mgr = DirectManager(args[0]) + else: + # Access via the tree + full_path = path.cmd_path_to_full_path(args[0]) + tree, mgr = get_manager(args[0], full_path, tree) + + if not hasattr(options, 'cmds'): + print >>sys.stderr, '{0}: No commands specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + + for c in options.cmds: + c[0](mgr, c[1]) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtprint.py b/rtshell/rtprint.py new file mode 100644 index 0000000..0718a51 --- /dev/null +++ b/rtshell/rtprint.py @@ -0,0 +1,147 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to print data sent by ports to the console. + +''' + + +import optparse +import os.path +import rtctree.tree +import rtctree.utils +import sys +import threading +import time +import traceback +import OpenRTM_aist +import RTC + +import comp_mgmt +import modmgr +import path +import port_types +import rtprint_comp +import rtshell + + +def read_from_ports(raw_paths, options, tree=None): + event = threading.Event() + + mm = modmgr.ModuleMgr(verbose=options.verbose, paths=options.paths) + mm.load_mods_and_poas(options.modules) + if options.verbose: + print >>sys.stderr, \ + 'Pre-loaded modules: {0}'.format(mm.loaded_mod_names) + if options.timeout == -1: + max = options.max + if options.verbose: + print >>sys.stderr, 'Will run {0} times.'.format(max) + else: + max = -1 + if options.verbose: + print >>sys.stderr, 'Will stop after {0}s'.format(options.timeout) + + targets = port_types.parse_targets(raw_paths) + if not tree: + paths = [t[0] for t in targets] + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + port_specs = port_types.make_port_specs(targets, mm, tree) + port_types.require_all_input(port_specs) + if options.verbose: + print >>sys.stderr, \ + 'Port specifications: {0}'.format([str(p) for p in port_specs]) + + comp_name, mgr = comp_mgmt.make_comp('rtprint_reader', tree, + rtprint_comp.Reader, port_specs, event=event, rate=options.rate, + max=max) + if options.verbose: + print >>sys.stderr, 'Created component {0}'.format(comp_name) + comp = comp_mgmt.find_comp_in_mgr(comp_name, mgr) + comp_mgmt.connect(comp, port_specs, tree) + comp_mgmt.activate(comp) + try: + if options.timeout != -1: + event.wait(options.timeout) + comp_mgmt.disconnect(comp) + comp_mgmt.deactivate(comp) + elif options.max > -1: + event.wait() + comp_mgmt.disconnect(comp) + comp_mgmt.deactivate(comp) + else: + while True: + raw_input() + # The manager will catch the Ctrl-C and shut down itself, so don't + # disconnect/deactivate the component + except KeyboardInterrupt: + pass + except EOFError: + pass + tree.give_away_orb() + del tree + comp_mgmt.shutdown(mgr) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] : [:...] +Print the data being sent by one or more output ports.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-m', '--mod', dest='modules', action='append', + type='string', default=[], + help='Extra modules to import. If automatic module loading '\ + 'struggles with your data types, try listing the modules here. '\ + 'The module and its __POA partner will be imported.') + parser.add_option('-n', '--number', dest='max', action='store', + type='int', default='-1', help='Specify the number of times to '\ + 'read from any ports. [Default: infinity]') + parser.add_option('-p', '--path', dest='paths', action='append', + type='string', default=[], + help='Extra module search paths to add to the PYTHONPATH.') + parser.add_option('-r', '--rate', dest='rate', action='store', + type='float', default=100.0, help='Specify the rate in Hertz at '\ + 'which to read and print. [Default: %default]') + parser.add_option('-t', '--timeout', dest='timeout', action='store', + type='float', default=-1, help='Read data for this many seconds, '\ + 'then stop. Specify -1 for no timeout. This option overrides '\ + '--number. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if len(args) < 1: + print >>sys.stderr, usage + return 1 + + try: + read_from_ports( + [path.cmd_path_to_full_path(p) for p in args], options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + diff --git a/rtshell/rtprint_comp.py b/rtshell/rtprint_comp.py new file mode 100644 index 0000000..57cb61c --- /dev/null +++ b/rtshell/rtprint_comp.py @@ -0,0 +1,42 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Reader component used by rtprint + +''' + + +import gen_comp +import OpenRTM_aist +import RTC + + +############################################################################### +## Reader component for rtprint + +class Reader(gen_comp.GenComp): + def __init__(self, mgr, port_specs, *args, **kwargs): + gen_comp.GenComp.__init__(self, mgr, port_specs, *args, **kwargs) + + def _behv(self, ec_id): + execed = 0 + for p in self._ports.values(): + if p.port.isNew(): + execed = 1 + p.read() + print p.format() + return RTC.RTC_OK, execed + diff --git a/rtshell/rtreset.py b/rtshell/rtreset.py new file mode 100644 index 0000000..8e49b4e --- /dev/null +++ b/rtshell/rtreset.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to move a component from the error state to the +inactive state. + +''' + + +import state_control_base + + +def reset_action(object, ec_index): + object.reset_in_ec(ec_index) + + +def main(argv=None, tree=None): + return state_control_base.base_main('Reset a component.', reset_action, + argv) + + +# vim: tw=79 + diff --git a/rtshell/rtresurrect.py b/rtshell/rtresurrect.py new file mode 100644 index 0000000..ca3893f --- /dev/null +++ b/rtshell/rtresurrect.py @@ -0,0 +1,281 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtresurrect library. + +''' + + +import optparse +import os +import os.path +import rtctree.path +import rtctree.tree +import rtsprofile.rts_profile +import sys +import traceback + +import actions +import option_store +import rtshell + + +def check_required_component_actions(rtsprofile): + checks = [] + # First perform a sanity check of the system. + # All required components must be present + for comp in [c for c in rtsprofile.components if c.is_required]: + checks.append(actions.CheckForRequiredCompAct('/' + comp.path_uri, + comp.id, comp.instance_name, + callbacks=[actions.RequiredActionCB()])) + return checks + + +def get_data_conn_props(conn): + return {'dataport.dataflow_type': str(conn.data_flow_type), + 'dataport.interface_type': str(conn.interface_type), + 'dataport.subscription_type': str(conn.subscription_type), + 'dataport.data_type': str(conn.data_type)} + + +def clean_props(props): + '''Clean properties of dangerous values and wrong data types. + + Make sure the properties don't have IORs or similar in them, because + they will confuse the notify_connect calls. + + Make sure that all keys are not unicode. + + ''' + new_props = {} + for p in props: + if p == 'dataport.corba_cdr.inport_ior': + continue + if p == 'dataport.corba_cdr.inport_ref': + continue + if p == 'dataport.corba_cdr.outport_ior': + continue + if p == 'dataport.corba_cdr.outport_ref': + continue + new_props[str(p)] = str(props[p]) + return new_props + + +def data_connection_actions(rtsprofile): + # The ports on those components in any required connections must also be + # present. + checks = [] + make_connections = [] + for conn in rtsprofile.required_data_connections(): + source_comp = rtsprofile.find_comp_by_target(conn.source_data_port) + source_path = '/' + source_comp.path_uri + source_port = conn.source_data_port.port_name + prefix = source_comp.instance_name + '.' + if source_port.startswith(prefix): + source_port = source_port[len(prefix):] + dest_comp = rtsprofile.find_comp_by_target(conn.target_data_port) + dest_path = '/' + dest_comp.path_uri + dest_port = conn.target_data_port.port_name + prefix = dest_comp.instance_name + '.' + if dest_port.startswith(prefix): + dest_port = dest_port[len(prefix):] + checks.append(actions.CheckForPortAct(source_path, source_port, + callbacks=[actions.RequiredActionCB()])) + checks.append(actions.CheckForPortAct(dest_path, dest_port, + callbacks=[actions.RequiredActionCB()])) + props = get_data_conn_props(conn) + props.update(conn.properties) + props = clean_props(props) + make_connections.append(actions.ConnectPortsAct(source_path, + source_port, dest_path, dest_port, str(conn.name), + str(conn.connector_id), props, + callbacks=[actions.RequiredActionCB()])) + + # Add the other connections to the list + for conn in rtsprofile.optional_data_connections(): + source_comp = rtsprofile.find_comp_by_target(conn.source_data_port) + source_path = '/' + source_comp.path_uri + source_port = conn.source_data_port.port_name + prefix = source_comp.instance_name + '.' + if source_port.startswith(prefix): + source_port = source_port[len(prefix):] + dest_comp = rtsprofile.find_comp_by_target(conn.target_data_port) + dest_path = '/' + dest_comp.path_uri + dest_port = conn.target_data_port.port_name + prefix = dest_comp.instance_name + '.' + if dest_port.startswith(prefix): + dest_port = dest_port[len(prefix):] + props = get_data_conn_props(conn) + props.update(conn.properties) + props = clean_props(props) + make_connections.append(actions.ConnectPortsAct(source_path, + source_port, dest_path, dest_port, str(conn.name), + str(conn.connector_id), props)) + + return checks, make_connections + + +def service_connection_actions(rtsprofile): + # The ports on those components in any required connections must also be + # present. + checks = [] + make_connections = [] + for conn in rtsprofile.required_service_connections(): + source_comp = rtsprofile.find_comp_by_target(conn.source_service_port) + source_path = '/' + source_comp.path_uri + source_port = conn.source_service_port.port_name + prefix = source_comp.instance_name + '.' + if source_port.startswith(prefix): + source_port = source_port[len(prefix):] + dest_comp = rtsprofile.find_comp_by_target(conn.target_service_port) + dest_path = '/' + dest_comp.path_uri + dest_port =conn.target_service_port.port_name + prefix = dest_comp.instance_name + '.' + if dest_port.startswith(prefix): + dest_port = dest_port[len(prefix):] + checks.append(actions.CheckForPortAct(source_path, source_port, + callbacks=[actions.RequiredActionCB()])) + checks.append(actions.CheckForPortAct(dest_path, dest_port, + callbacks=[actions.RequiredActionCB()])) + make_connections.append(actions.ConnectPortsAct(source_path, + source_port, dest_path, dest_port, str(conn.name), + str(conn.connector_id), {}, + callbacks=[actions.RequiredActionCB()])) + + # Add the other connections to the list + for conn in rtsprofile.optional_service_connections(): + source_comp = rtsprofile.find_comp_by_target(conn.source_service_port) + source_path = '/' + source_comp.path_uri + source_port = conn.source_service_port.port_name + prefix = source_comp.instance_name + '.' + if source_port.startswith(prefix): + source_port = source_port[len(prefix):] + dest_comp = rtsprofile.find_comp_by_target(conn.target_service_port) + dest_path = '/' + dest_comp.path_uri + dest_port =conn.target_service_port.port_name + prefix = dest_comp.instance_name + '.' + if dest_port.startswith(prefix): + dest_port = dest_port[len(prefix):] + make_connections.append(actions.ConnectPortsAct(source_path, + source_port, dest_path, dest_port, str(conn.name), + str(conn.connector_id), {})) + + return checks, make_connections + + +def config_set_actions(rtsprofile): + set_active = [] + # For each component, if there is an active set, add an action for it + for comp in rtsprofile.components: + if comp.active_configuration_set: + set_active.append(actions.SetActiveConfigSetAct( + '/' + comp.path_uri, comp.active_configuration_set)) + + set_values = [] + for comp in rtsprofile.components: + for cs in comp.configuration_sets: + for p in cs.configuration_data: + set_values.append(actions.SetConfigParamValueAct( + '/' + comp.path_uri, cs.id, p.name, p.data)) + + return set_values + set_active + + +def rebuild_system_actions(rtsprofile): + checks = check_required_component_actions(rtsprofile) + data_conn_checks, data_connections = data_connection_actions(rtsprofile) + svc_conn_checks, svc_connections = service_connection_actions(rtsprofile) + config_actions = config_set_actions(rtsprofile) + + return checks + data_conn_checks + svc_conn_checks + data_connections + \ + svc_connections + config_actions + + +def resurrect(profile=None, xml=True, dry_run=False, tree=None): + # Load the profile + if profile: + # Read from a file + with open(profile) as f: + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f) + else: + # Read from standard input + lines = sys.stdin.read() + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines) + + # Build a list of actions to perform that will reconstruct the system + actions = rebuild_system_actions(rtsp) + if dry_run: + for a in actions: + print a + else: + if not tree: + # Load the RTC Tree, using the paths from the profile + tree = rtctree.tree.RTCTree(paths=[rtctree.path.parse_path( + '/' + c.path_uri)[0] for c in rtsp.components]) + for a in actions: + a(tree) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] +Recreate an RT system using an RTSProfile.''' + parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION) + parser.add_option('--dry-run', dest='dry_run', action='store_true', + default=False, help="Print what will be done but don't actually " + "do anything. [Default: %default]") + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML input format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML input format. [Default: False]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError: ', e + return 1 + option_store.OptionStore().verbose = options.verbose + + if not args: + profile = None + elif len(args) == 1: + profile = args[0] + else: + print >>sys.stderr, usage + return 1 + + try: + resurrect(profile=profile, xml=options.xml, dry_run=options.dry_run, + tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + +# vim: tw=79 + diff --git a/rtshell/rts_exceptions.py b/rtshell/rts_exceptions.py new file mode 100644 index 0000000..b5f8870 --- /dev/null +++ b/rtshell/rts_exceptions.py @@ -0,0 +1,563 @@ +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Exceptions that may occur. + +''' + + +import rtctree.path + + +class RtShellError(Exception): + '''Base error for all errors that may occur.''' + pass + + +class CallFailedError(Exception): + '''An interface call failed.''' + def __init__(self, msg): + self._msg = msg + + def __str__(self): + return 'Interface call failed: {0}'.format(self._msg) + + +class RequiredActionFailedError(RtShellError): + '''Error raised when an action that must succeed fails.''' + def __init__(self, msg): + self._msg = msg + + def __str__(self): + return 'Required action failed: {0}'.format(self._msg) + + +class PrecedingTimeoutError(RtShellError): + '''The time limit on a preceding condition being met has elapsed.''' + def __init__(self, msg): + self._msg = msg + + def __str__(self): + return 'Preceding condition timed out: {0}'.format(self._msg) + + +class PlanExecutionError(RtShellError): + '''An error occurred executing a plan.''' + def __init__(self, error): + self._error = error + + def __str__(self): + return 'Error executing plan:\n{0}'.format(self._error) + + +class EmptyConstExprError(RtShellError): + '''A constant expression that should be evaluated is empty.''' + def __str__(self): + return 'Empty constant expression ' + + +class AmbiguousTypeError(RtShellError): + '''A data type is ambiguous.''' + def __init__(self, type): + self._type = type + + def __str__(self): + return 'Ambiguous port type: {0}'.format(self._type) + + +class TypeNotFoundError(RtShellError): + '''A data type was not found.''' + def __init__(self, type): + self._type = type + + def __str__(self): + return 'Type not found: {0}'.format(self._type) + + +class BadPortSpecError(RtShellError): + '''A port specification is badly formatted.''' + def __init__(self, ps): + self._ps = ps + + def __str__(self): + return 'Bad port specification: {0}'.format(self._ps) + + +class SameNameDiffSpecError(RtShellError): + '''A port spec has a different property from another with the same name.''' + def __init__(self, ps): + self._ps = ps + + def __str__(self): + return 'Port specification with same name has different properties: '\ + '{0}'.format(self._ps) + + +class NoSuchObjectError(RtShellError): + '''The given path does not point to the necessary object.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'No such object: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'No such object: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'No such object: {0}'.format(self._path) + + +class NotAComponentOrManagerError(RtShellError): + '''A given path is not a component nor a manager.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a component or manager: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a component or manager: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a component or manager: {0}'.format(self._path) + + +class NotAComponentError(RtShellError): + '''A given path is not a component.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a component: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a component: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a component: {0}'.format(self._path) + + +class NotACompositeComponentError(RtShellError): + '''A given path is not a composite component.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a composite component: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a composite component: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a composite component: {0}'.format(self._path) + + +class NotAPortError(RtShellError): + '''A given path is not a port.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a port: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a port: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a port: {0}'.format(self._path) + + +class ParentNotADirectoryError(RtShellError): + '''A given path's parent is not a directory.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Parent not a directory: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Parent not a directory: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Parent not a directory: {0}'.format(self._path) + + +class NotADirectoryError(RtShellError): + '''A given path is not a directory.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a directory: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a directory: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a directory: {0}'.format(self._path) + + +class NotAPortError(RtShellError): + '''A given path is not a port.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a port: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a port: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a port: {0}'.format(self._path) + + +class NotAManagerError(RtShellError): + '''A given path is not a manager.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a manager: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a manager: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a manager: {0}'.format(self._path) + + +class NotInManagerError(RtShellError): + '''A component name does not exist in a manager.''' + def __init__(self, name): + self._name = name + + def __str__(self): + return '{0} is not in the manager.'.format(self._name) + + +class UndeletableObjectError(RtShellError): + '''Some objects cannot be deleted.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Undeletable object: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Undeletable object: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Undeletable object: {0}'.format(self._path) + + +class NotZombieObjectError(RtShellError): + '''A given path does not point to a zombie.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Not a zombie object: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Not a zombie object: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Not a zombie object: {0}'.format(self._path) + + +class ZombieObjectError(RtShellError): + '''A given path points to a zombie.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Zombie object: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Zombie object: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Zombie object: {0}'.format(self._path) + + +class UnknownObjectError(RtShellError): + '''A given path points to an unknown object.''' + def __init__(self, path): + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'Unknown object: {0}'.format( + rtctree.path.format_path(self._path)) + elif type(self._path) == list: + return 'Unknown object: {0}'.format( + rtctree.path.format_path((self._path, None))) + else: + return 'Unknown object: {0}'.format(self._path) + + +class NoDestPortError(RtShellError): + '''A required destination port was not specified.''' + def __str__(self): + return 'No destination port specified.' + + +class NoSourcePortError(RtShellError): + '''A required source port was not specified.''' + def __str__(self): + return 'No source port specified.' + + +class CannotDoToPortError(RtShellError): + '''The action cannot be performed on a port.''' + def __init__(self, action): + self._action = action + + def __str__(self): + return 'Cannot {0} ports.'.format(self._action) + + +class PortNotFoundError(RtShellError): + '''The port was not found on the component.''' + def __init__(self, rtc, port): + self._rtc = rtc + self._port = port + + def __str__(self): + return 'Port not found: {0}'.format( + rtctree.path.format_path((self._rtc, self._port))) + + +class ConnectionNotFoundError(RtShellError): + '''A connection between two ports was not found.''' + def __init__(self, path1, path2): + self._path1 = path1 + self._path2 = path2 + + def __str__(self): + if type(self._path1) == tuple: + path1_str = rtctree.path.format_path(self._path1) + elif type(self._path1) == list: + path1_str = rtctree.path.format_path((self._path1, None)) + else: + path1_str = self._path1 + if type(self._path2) == tuple: + path2_str = rtctree.path.format_path(self._path2) + elif type(self._path2) == list: + path2_str = rtctree.path.format_path((self._path2, None)) + else: + path2_str = self._path2 + return 'No connection from {0} to {1}'.format(path1_str, path2_str) + + +class MultiConnectionNotFoundError(RtShellError): + '''A connection between ports was not found.''' + def __str__(self): + return 'No connection found involving the specified ports.''' + + +class ConnectionIDNotFoundError(RtShellError): + '''The port was not found on the component.''' + def __init__(self, id, path): + self._id = id + self._path = path + + def __str__(self): + if type(self._path) == tuple: + return 'No connection from {0} with ID {1}.'.format( + rtctree.path.format_path(self._path), self._id) + elif type(self._path) == list: + return 'No connection from {0} with ID {1}.'.format( + rtctree.path.format_path((self._path, None)), self._id) + else: + return 'No connection from {0} with ID {1}'.format(self._path, + self._id) + + +class BadPortTypeError(RtShellError): + '''The port type is not defined.''' + def __init__(self, rtc, port): + self._rtc = rtc + self._port = port + + def __str__(self): + return 'Incorrect port type: {0}'.format( + rtctree.path.format_path((self._rtc, self._port))) + + +class MissingCompError(RtShellError): + '''An expected component is missing.''' + def __init__(self, path): + self._path = path + + def __str__(self): + return 'Expected component missing: {0}'.format(self._path) + + +class ConnectFailedError(RtShellError): + '''An error occured connecting two ports.''' + def __init__(self, rtc, port): + self._rtc = rtc + self._port = port + + def __str__(self): + return 'Failed to connect port: {0}'.format( + rtctree.path.format_path((self._rtc, self._port))) + + +class ActivateError(RtShellError): + '''An error occured activating a component.''' + def __init__(self, comp): + self._comp = comp + + def __str__(self): + return 'Error activating component: {0}'.format(self._comp) + + +class DeactivateError(RtShellError): + '''An error occured deactivating a component.''' + def __init__(self, comp): + self._comp = comp + + def __str__(self): + return 'Error deactivating component: {0}'.format(self._comp) + + +class PortNotInputError(RtShellError): + '''A port is not an input that should be.''' + def __init__(self, name): + self._name = name + + def __str__(self): + return 'Port is not input: {0}'.format(self._name) + + +class PortNotOutputError(RtShellError): + '''A port is not an output that should be.''' + def __init__(self, name): + self._name = name + + def __str__(self): + return 'Port is not output: {0}'.format(self._name) + + +class ImportFormatterError(RtShellError): + '''An error occured importing a formatting function.''' + def __init__(self, exc): + self._exc = exc + + def __str__(self): + return 'Error importing formatter: {0}'.format(self._exc) + + +class BadFormatterError(RtShellError): + '''The imported formatter is bad (most likely not a function).''' + def __init__(self, fun): + self._fun = fun + + def __str__(self): + return 'Bad formatter: {0}'.format(self._fun) + + +class MissingPOAError(RtShellError): + '''A data type from a module was used without a matching POA loaded.''' + def __init__(self, mod): + self._mod = mod + + def __str__(self): + return 'Missing POA module: {0}'.format(self._mod) + + +class NoConfSetError(RtShellError): + '''The specified configuration set does not exist.''' + def __init__(self, name): + self._name = name + + def __str__(self): + return 'No such configuration set: {0}'.format(self._name) + + +class BadStartPointError(RtShellError): + '''A given start point for the log is outside the bounds.''' + def __str__(self): + return 'Start time/index out of bounds.' + + +class BadEndPointError(RtShellError): + '''A given end point for the log is outside the bounds.''' + def __str__(self): + return 'End time/index out of bounds.' + + +class BadLogTypeError(RtShellError): + '''An invalid logger type was chosen.''' + def __init__(self, type): + self._type = type + + def __str__(self): + return 'Invalid logger type: {0}'.format(self._type) + + +class UnsupportedLogTypeError(RtShellError): + '''The selected log type doesn't support the desired feature.''' + def __init__(self, type, feature): + self._type = type + self._feature = feature + + def __str__(self): + return 'Log type "{0}" does not support feature {1}.'.format( + self._type, self._feature) + + +class NoLogFileNameError(RtShellError): + '''An expected file name was not provided.''' + def __str__(self): + return 'No log file specified.' + + +class BadMgrAddressError(RtShellError): + '''A bad corbaloc address was given.''' + def __str__(self): + return 'Invalid corbaloc URL.' + + +class FailedToNarrowError(RtShellError): + '''Failed to narrow a CORBA object reference.''' + def __str__(self): + return 'Failed to narrow CORBA object reference.' + + +class CannotRemoveFromNewCompositionError(RtShellError): + '''Cannot remove components/ports from a new composition.''' + def __str__(self): + return 'Cannot remove components/ports from a new composition.' + + +# vim: tw=79 + diff --git a/rtshell/rtstart.py b/rtshell/rtstart.py new file mode 100644 index 0000000..110f544 --- /dev/null +++ b/rtshell/rtstart.py @@ -0,0 +1,152 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstart library. + +''' + + +import optparse +import os +import os.path +import rtctree.component +import rtctree.path +import rtctree.tree +import rtsprofile.rts_profile +import sys +import traceback + +import actions +import option_store +import plan +import rts_exceptions +import rtshell + + +def check_required_component_actions(rtsprofile): + checks = [] + # First perform a sanity check of the system. + # All required components must be present + for comp in [c for c in rtsprofile.components if c.is_required]: + checks.append(actions.CheckForRequiredCompAct('/' + comp.path_uri, + comp.id, comp.instance_name, + callbacks=[actions.RequiredActionCB()])) + return checks + + +def activate_actions(rtsprofile): + checks = check_required_component_actions(rtsprofile) + + activates = [] + for comp in [c for c in rtsprofile.components if c.is_required]: + for ec in comp.execution_contexts: + activates.append(actions.ActivateCompAct('/' + comp.path_uri, + comp.id, comp.instance_name, ec.id, + callbacks=[actions.RequiredActionCB()])) + + for comp in [c for c in rtsprofile.components if not c.is_required]: + for ec in comp.execution_contexts: + activates.append(actions.ActivateCompAct('/' + comp.path_uri, + comp.id, comp.instance_name, ec.id)) + + return checks, activates + + +def start(profile=None, xml=True, dry_run=False, tree=None): + # Load the profile + if profile: + # Read from a file + with open(profile) as f: + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f) + else: + # Read from standard input + lines = sys.stdin.read() + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines) + + # Build a list of actions to perform that will start the system + checks, activates = activate_actions(rtsp) + p = plan.Plan() + p.make(rtsp, activates, rtsp.activation, + rtctree.component.Component.ACTIVE) + if dry_run: + for a in checks: + print a + print p + else: + if not tree: + # Load the RTC Tree, using the paths from the profile + tree = rtctree.tree.RTCTree(paths=[rtctree.path.parse_path( + '/' + c.path_uri)[0] for c in rtsp.components]) + try: + for a in checks: + a(tree) + p.execute(tree) + except rts_exceptions.RequiredActionFailedError: + p.cancel() + raise + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [RTSProfile file] +Start an RT system using an RTSProfile.''' + parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION) + parser.add_option('--dry-run', dest='dry_run', action='store_true', + default=False, help="Print what will be done but don't actually " + "do anything. [Default: %default]") + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML input format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML input format. [Default: False]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError: ', e + return 1 + option_store.OptionStore().verbose = options.verbose + + if not args: + profile = None + elif len(args) == 1: + profile = args[0] + else: + print >>sys.stderr, usage + return 1 + + try: + start(profile=profile, xml=options.xml, dry_run=options.dry_run, + tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtstodot.py b/rtshell/rtstodot.py new file mode 100644 index 0000000..10fb640 --- /dev/null +++ b/rtshell/rtstodot.py @@ -0,0 +1,154 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Yosuke Matsusaka and Geoffrey Biggs + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the RT System visualisation command. + +''' + + +import optparse +import os.path +import rtsprofile.rts_profile +import sys +import traceback + +import rtshell + + +def port_name(s): + parts = s.split('.') + if len(parts) == 1: + return s + else: + return parts[-1] + + +def escape(s): + return s.replace('.', '_dot_').replace('/', '_slash_') + + +def get_ports(rtsp): + in_ports = [] + out_ports = [] + for dp in rtsp.data_port_connectors: + in_ports.append((dp.source_data_port.instance_name, + port_name(dp.source_data_port.port_name))) + out_ports.append((dp.target_data_port.instance_name, + port_name(dp.target_data_port.port_name))) + for sp in rtsp.service_port_connectors: + out_ports.append((dp.source_data_port.instance_name, + port_name(dp.source_data_port.port_name))) + in_ports.append((dp.target_data_port.instance_name, + port_name(dp.target_data_port.port_name))) + return in_ports, out_ports + + +def make_comp_str(c, in_ports, out_ports): + in_ports_str = '' + out_ports_str = '' + for dp in c.data_ports: + if (c.instance_name, dp.name) in in_ports: + in_ports_str += '<{0}>{0}|'.format(port_name(dp.name)) + if (c.instance_name, dp.name) in out_ports: + out_ports_str += '<{0}>{0}|'.format(port_name(dp.name)) + for sp in c.service_ports: + if (c.instance_name, sp.name) in in_ports: + in_ports_str += '<{0}>{0}|'.format(port_name(sp.name)) + if (c.instance_name, sp.name) in out_ports: + out_ports_str += '<{0}>{0}|'.format(port_name(sp.name)) + label_str = '{{{{{0}}}|{1}|{{{2}}}}}'.format(in_ports_str[:-1], c.instance_name, + out_ports_str[:-1]) + return ' {0} [label="{1}"];'.format(escape(c.instance_name), label_str) + + +def make_conn_str(s_port, d_port): + return ' {0}:{1} -> {2}:{3}'.format( + escape(s_port.instance_name), port_name(s_port.port_name), + escape(d_port.instance_name), port_name(d_port.port_name)) + + +def visualise(profile=None, xml=True, tree=None): + # Load the profile + if profile: + # Read from a file + with open(profile) as f: + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f) + else: + # Read from standard input + lines = sys.stdin.read() + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines) + + result = ['digraph rtsprofile {', ' rankdir=LR;', ' node [shape=Mrecord];'] + in_ports, out_ports = get_ports(rtsp) + for comp in rtsp.components: + result.append(make_comp_str(comp, in_ports, out_ports)) + for conn in rtsp.data_port_connectors: + result.append(make_conn_str(conn.source_data_port, + conn.target_data_port) + ';') + for conn in rtsp.service_port_connectors: + result.append(make_conn_str(conn.source_service_port, + conn.target_service_port) + ' [arrowhead="odot"];') + result.append('}') + return result + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [RTSProfile file] +Visualise RT Systems using dot files.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML input format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML input format. [Default: False]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if not args: + profile = None + elif len(args) == 1: + profile = args[0] + else: + print >>sys.stderr, usage + return 1 + + try: + for l in visualise(profile=profile, xml=options.xml, tree=tree): + print l + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtstop.py b/rtshell/rtstop.py new file mode 100644 index 0000000..8eb12e7 --- /dev/null +++ b/rtshell/rtstop.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstop library. + +''' + + +import optparse +import os +import os.path +import rtctree.component +import rtctree.path +import rtctree.tree +import rtsprofile.rts_profile +import sys +import traceback + +import actions +import option_store +import plan +import rts_exceptions +import rtshell + + +def deactivate_actions(rtsprofile): + deactivates = [] + for comp in rtsprofile.components: + for ec in comp.execution_contexts: + deactivates.append(actions.DeactivateCompAct( + '/' + comp.path_uri, comp.id, comp.instance_name, ec.id)) + return deactivates + + +def stop(profile=None, xml=True, dry_run=False, tree=None): + # Load the profile + if profile: + # Read from a file + with open(profile) as f: + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f) + else: + # Read from standard input + lines = sys.stdin.read() + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines) + + # Build a list of actions to perform that will stop the system + deactivates = deactivate_actions(rtsp) + p = plan.Plan() + p.make(rtsp, deactivates, rtsp.deactivation, + rtctree.component.Component.INACTIVE) + if dry_run: + print p + else: + if not tree: + # Load the RTC Tree, using the paths from the profile + tree = rtctree.tree.RTCTree(paths=[rtctree.path.parse_path( + '/' + c.path_uri)[0] for c in rtsp.components]) + try: + p.execute(tree) + except rts_exceptions.RequiredActionFailedError, e: + p.cancel() + raise + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [RTSProfile file] +Stop an RT system using an RTSProfile.''' + parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION) + parser.add_option('--dry-run', dest='dry_run', action='store_true', + default=False, help="Print what will be done but don't actually " + "do anything. [Default: %default]") + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML input format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML input format. [Default: False]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError: ', e + return 1 + option_store.OptionStore().verbose = options.verbose + + if not args: + profile = None + elif len(args) == 1: + profile = args[0] + else: + print >>sys.stderr, usage + return 1 + + try: + stop(profile=profile, xml=options.xml, dry_run=options.dry_run, + tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtteardown.py b/rtshell/rtteardown.py new file mode 100644 index 0000000..e8428ee --- /dev/null +++ b/rtshell/rtteardown.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtteardown library. + +''' + + +import optparse +import os +import os.path +import rtctree.path +import rtctree.tree +import rtsprofile.rts_profile +import sys +import traceback + +import actions +import option_store +import rtshell + + +def disconnect_actions(rtsprofile): + disconnects = [] + for conn in rtsprofile.data_port_connectors: + source_comp = rtsprofile.find_comp_by_target(conn.source_data_port) + source_path = '/' + source_comp.path_uri + source_port = conn.source_data_port.port_name + prefix = source_comp.instance_name + '.' + if source_port.startswith(prefix): + source_port = source_port[len(prefix):] + dest_comp = rtsprofile.find_comp_by_target(conn.target_data_port) + dest_path = '/' + dest_comp.path_uri + dest_port =conn.target_data_port.port_name + prefix = dest_comp.instance_name + '.' + if dest_port.startswith(prefix): + dest_port = dest_port[len(prefix):] + disconnects.append(actions.DisconnectPortsAct(source_path, source_port, + dest_path, dest_port, conn.connector_id)) + + for conn in rtsprofile.service_port_connectors: + source_comp = rtsprofile.find_comp_by_target(conn.source_service_port) + source_path = '/' + source_comp.path_uri + source_port = conn.source_service_port.port_name + prefix = source_comp.instance_name + '.' + if source_port.startswith(prefix): + source_port = source_port[len(prefix):] + dest_comp = rtsprofile.find_comp_by_target(conn.target_service_port) + dest_path = '/' + dest_comp.path_uri + dest_port = conn.target_service_port.port_name + prefix = dest_comp.instance_name + '.' + if dest_port.startswith(prefix): + dest_port = dest_port[len(prefix):] + disconnects.append(actions.DisconnectPortsAct(source_path, source_port, + dest_path, dest_port, conn.connector_id)) + return disconnects + + +def teardown(profile=None, xml=True, dry_run=False, tree=None): + # Load the profile + if profile: + # Read from a file + with open(profile) as f: + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=f) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=f) + else: + # Read from standard input + lines = sys.stdin.read() + if xml: + rtsp = rtsprofile.rts_profile.RtsProfile(xml_spec=lines) + else: + rtsp = rtsprofile.rts_profile.RtsProfile(yaml_spec=lines) + + # Build a list of actions to perform that will destroy the system + actions = disconnect_actions(rtsp) + if dry_run: + for a in actions: + print a + else: + if not tree: + # Load the RTC Tree, using the paths from the profile + tree = rtctree.tree.RTCTree(paths=[rtctree.path.parse_path( + '/' + c.path_uri)[0] for c in rtsp.components]) + for a in actions: + a(tree) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [RTSProfile file] +Destroy an RT system using an RTSProfile.''' + parser = optparse.OptionParser(usage=usage, version=rtshell.RTSH_VERSION) + parser.add_option('--dry-run', dest='dry_run', action='store_true', + default=False, + help="Print what will be done but don't actually do anything. \ +[Default: %default]") + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, help='Verbose output. [Default: %default]') + parser.add_option('-x', '--xml', dest='xml', action='store_true', + default=True, help='Use XML input format. [Default: True]') + parser.add_option('-y', '--yaml', dest='xml', action='store_false', + help='Use YAML input format. [Default: False]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError: ', e + return 1 + option_store.OptionStore().verbose = options.verbose + + + if not args: + profile = None + elif len(args) == 1: + profile = args[0] + else: + print >>sys.stderr, usage + return 1 + + try: + teardown(profile=profile, xml=options.xml, dry_run=options.dry_run, + tree=tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/rtvlog.py b/rtshell/rtvlog.py new file mode 100644 index 0000000..46ec5ec --- /dev/null +++ b/rtshell/rtvlog.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Implementation of the command to make a component exit. + +''' + + +import optparse +import os +import os.path +import rtctree.exceptions +import rtctree.tree +import rtctree.path +import RTC +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def log_cb(rtc, time, source, level, msg): + print '[{0} {1}] {2} <{3}> {4}'.format(rtc, time, level, source, msg) + + +def print_logs(paths, options, tree=None): + for p in paths: + path, port = rtctree.path.parse_path(p[1]) + if port: + raise rts_exceptions.NotAComponentError(p[0]) + if not path[-1]: + raise rts_exceptions.NotAComponentError(p[0]) + p.append(path) + + if not tree: + parsed = [p[2] for p in paths] + tree = rtctree.tree.RTCTree(paths=parsed, filter=parsed) + + filters = ','.join(options.filters) + ids = [] + try: + for p in paths: + if not tree.has_path(p[2]): + raise rts_exceptions.NoSuchObjectError(p[0]) + rtc = tree.get_node(p[2]) + if rtc.is_zombie: + raise rts_exceptions.ZombieObjectError(p[0]) + if not rtc.is_component: + raise rts_exceptions.NotAComponentError(p[0]) + + id = rtc.add_logger(log_cb, level=options.level, + filters=filters) + ids.append((rtc, id)) + except rtctree.exceptions.AddLoggerError, e: + # Remove all the loggers that were added + for i in ids: + i[0].remove_logger(i[1]) + # Re-raise + raise e + + # Wait for a keyboard interrupt + try: + while True: + raw_input('') + except KeyboardInterrupt: + pass + # Remove all the loggers that were added + for i in ids: + i[0].remove_logger(i[1]) + + +def main(argv=None, tree=None): + usage = '''Usage: %prog [options] [path 2...] +View a component logs.''' + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-f', '--filter', dest='filters', action='append', + type='string', default='ALL', + help='Event source filters. [Default: %default]') + parser.add_option('-l', '--level', dest='level', action='store', + type='string', default='NORMAL', + help='Log level. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if not args: + # If no paths given then can't do anything. + print >>sys.stderr, '{0}: No component specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + paths = [[p, path.cmd_path_to_full_path(p)] for p in args] + + try: + print_logs(paths, options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/simpkl_log.py b/rtshell/simpkl_log.py new file mode 100644 index 0000000..2a9b907 --- /dev/null +++ b/rtshell/simpkl_log.py @@ -0,0 +1,406 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Pickle-based log. + +''' + + +import copy +import os +import pickle +import traceback + +import ilog + + +############################################################################### +## Current position pointer + +class CurPos(object): + def __init__(self, index=0, timestamp=0, prev_pos=0, cache=0, file_pos=0): + super(CurPos, self).__init__() + self.index = index + self.ts = timestamp + self.prev = prev_pos + self.cache = cache + self.fp = file_pos + + def __str__(self): + return 'Index: {0}, timestamp: {1}, previous position: {2}, cache '\ + 'position: {3}, file position: {4}'.format(self.index, self.ts, + self.prev, self.cache, self.fp) + + +############################################################################### +## Simple pickle-based log object. Its support for the full log interface +## is rudimentary and slow (although writing and simple reading should be fast +## enough). +## +## The simple pickle-based format is as follows (each entry is serialised): +## Port specification (in the metadata block) +## [Data entries: (Index, Time stamp, Data)] + +class SimplePickleLog(ilog.Log): + # Indices in data entries for bits of data + INDEX = 0 + TS = 1 + DATA = 2 + FP = 3 + PREV = 4 + # Spare space at the start for pointers + BUFFER_SIZE = 256 + + def __init__(self, filename='', *args, **kwargs): + self._is_open = False + self._fn = filename + self._cur_pos = CurPos() + self._start = None + self._end = None + self._next = None + self._write_ind = 0 + self._prev_pos = 0 + super(SimplePickleLog, self).__init__(*args, **kwargs) + + def __str__(self): + return 'SimplePickleLog({0}, {1}) at position {2}.'.format(self._fn, + self._mode, self._cur_pos) + + def write(self, timestamp, data): + val = (self._write_ind, timestamp, data, self._file.tell(), self._prev_pos) + # Track the start of the last entry for later writing at the file start + self._cur_pos.ts = timestamp + self._end = copy.copy(self._cur_pos) + # Record the new "previous" position before writing + self._prev_pos = self._file.tell() + self._write(val) + # Update the current position to after the new final record + self._cur_pos.index = val[self.INDEX] + 1 + self._cur_pos.ts = -1 + self._cur_pos.prev = self._prev_pos + self._cur_pos.cache = self._prev_pos + self._cur_pos.fp = self._file.tell() + self._write_ind += 1 + self._vb_print('Wrote entry at ({0}, {1}, {2}, {3}).'.format( + val[self.INDEX], val[self.TS], val[self.FP], val[self.PREV])) + + def read(self, timestamp=None, number=None): + if number is not None: + return self._read_number(number) + elif timestamp is not None: + return self._read_to_timestamp(timestamp) + else: + return self._read_single_entry() + + def rewind(self): + self._vb_print('Rewinding log from position {0}.'.format( + self._cur_pos)) + if self._mode == 'r': + self._file.seek(0) + else: + self._file.truncate() + self._write_ind = 0 + self._init_log() + + def seek(self, timestamp=None, index=None): + self._vb_print('Seeking log from position {0}.'.format(self._cur_pos)) + if index is not None: + self._seek_to_index(index) + elif timestamp is not None: + self._seek_to_timestamp(timestamp) + # Do nothing if neither is set + self._vb_print('New current position: {0}.'.format(self._cur_pos)) + + def _backup_one(self): + '''Reverses in the log one entry.''' + self._vb_print('Backing up one entry from {0}.'.format(self._cur_pos)) + if self._cur_pos.index == 0: + # Already at the start + self._vb_print('Backup already at start.') + return + else: + self._next = None + target = self._cur_pos.prev + # Move back in the file one entry + self._file.seek(target) + # Update the next pointer + self._next = self._read() + self._update_cur_pos(self._next) + self._vb_print('New current position: {0}.'.format(self._cur_pos)) + + def _close(self): + if not self._is_open: + return + if self._mode == 'w': + # Go back to the beginning and write the end position + self._file.seek(0) + self._file.seek(self._buf_start) # Skip the meta data + self._write(self._end) + self._vb_print('Wrote end pointer: {0}'.format(self._end)) + self._file.close() + self._is_open = False + self._start = None + self._end = None + self._vb_print('Closed file.') + + def _eof(self): + return self._next is None + + def _get_cur_pos(self): + self._vb_print('Current position: {0}'.format(self._cur_pos)) + return self._cur_pos.index, self._cur_pos.ts + + def _get_start(self): + if self._start is None: + self._set_start() + self._vb_print('Start position: {0}'.format(self._start)) + return (self._start.index, self._start.ts) + + def _get_end(self): + self._vb_print('End position: {0}'.format(self._end)) + return (self._end.index, self._end.ts) + + def _init_log(self): + if self._mode == 'r': + self._vb_print('Initialising log for reading.') + # Read out the metadata + self._meta = self._read() + pos = self._file.tell() + # Read the end marker + self._end = self._read() + # Skip to the start of the data + self._file.seek(pos + self.BUFFER_SIZE) + self._vb_print('Read end position: {0}'.format(self._end)) + # Grab the position of the first entry and make it the current + self._set_start() + self._cur_pos = copy.copy(self._start) + # Get the first entry + self._next = self._read() + else: + self._vb_print('Initialising log for writing.') + # Write the metadata + self._write(self._meta) + self._vb_print('Wrote meta data of length {0}'.format( + self._file.tell())) + self._buf_start = self._file.tell() + # Put some blank space to write the end marker + self._file.write(''.ljust(self.BUFFER_SIZE)) + self._vb_print('Wrote buffer of length {0} at position {1}'.format( + self.BUFFER_SIZE, self._buf_start)) + self._write_ind = 0 + self._prev_pos = 0 + self._cur_pos = CurPos(file_pos=self._file.tell()) + self._vb_print('First entry will be written at {0}'.format( + self._cur_pos)) + + def _open(self): + if self._is_open: + return + if self._mode == 'r': + flags = 'rb' + elif self._mode == 'w': + flags = 'wb' + else: + raise NotImplementedError + self._file = open(self._fn, flags) + self._init_log() + self._is_open = True + self._vb_print('Opened file {0} in mode {1}.'.format(self._fn, + self._mode)) + + def _read(self): + '''Read a single entry from the log.''' + self._vb_print('Reading one data block at {0}.'.format( + self._file.tell())) + try: + data = pickle.load(self._file) + except EOFError: + self._vb_print('End of log reached.') + raise ilog.EndOfLogError + return data + + def _read_number(self, number): + self._vb_print('Reading {0} entries.'.format(number)) + res = [] + if number < 0: + raise ValueError + if not self._next: + self._vb_print('End of log before reading.') + return [] + try: + for ii in range(number): + res.append((self._next[self.INDEX], self._next[self.TS], + self._next[self.DATA])) + self._next = self._read() + if not self._next: + self._set_eof_pos() + self._vb_print('End of log during reading, current '\ + 'position is {1}.'.format(self._cur_pos)) + break + self._update_cur_pos(self._next) + self._vb_print('Read entry {0} of {1}, current position '\ + 'is {2}.'.format(ii + 1, number, self._cur_pos)) + except ilog.EndOfLogError: + self._set_eof_pos() + self._next = None + self._vb_print('End of log while reading, current '\ + 'position is {0}.'.format(self._cur_pos)) + self._vb_print('Finished reading; current position is ' \ + '{0}.'.format(self._cur_pos)) + return res + + def _read_to_timestamp(self, timestamp): + self._vb_print('Reading until time stamp {0}.'.format(timestamp)) + res = [] + if timestamp < 0: + raise ValueError + if not self._next: + self._vb_print('End of log before reading.') + return [] + if self._cur_pos.ts > timestamp: + # The time limit is before the next item - nothing to read + self._vb_print('Current position is beyond the time limit.') + return [] + try: + while self._next[self.TS] <= timestamp: + res.append((self._next[self.INDEX], self._next[self.TS], + self._next[self.DATA])) + self._next = self._read() + if not self._next: + self._set_eof_pos() + self._vb_print('End of log during reading, current '\ + 'position is {1}.'.format(self._cur_pos)) + break + self._update_cur_pos(self._next) + self._vb_print('Read entry at time index {0}, current '\ + 'position is {1}.'.format(res[-1][1], self._cur_pos)) + except ilog.EndOfLogError: + self._set_eof_pos() + self._next = None + self._vb_print('End of log while reading, current '\ + 'position is {0}.'.format(self._cur_pos)) + self._vb_print('Finished reading; current position is ' \ + '{0}.'.format(self._cur_pos)) + return res + + def _read_single_entry(self): + self._vb_print('Reading a single entry.') + if not self._next: + self._vb_print('End of log before reading.') + return [] + else: + res = [(self._next[self.INDEX], self._next[self.TS], + self._next[self.DATA])] + try: + self._next = self._read() + except ilog.EndOfLogError: + self._next = None + if not self._next: + self._set_eof_pos() + self._vb_print('End of log during reading, current '\ + 'position is {0}.'.format(self._cur_pos)) + else: + self._update_cur_pos(self._next) + self._vb_print('Read entry, current position is ' \ + '{0}.'.format(self._cur_pos)) + self._vb_print('Cached next entry is {0}'.format(self._next)) + return res + + def _seek_to_index(self, ind): + '''Seeks forward or backward in the log to find the given index.''' + if ind == self._cur_pos.index: + self._vb_print('Seek by index: already at destination.') + return + if ind < 0: + raise ilog.InvalidIndexError + elif ind < self._cur_pos.index: + # Rewind + # TODO: Rewinding may be more efficient in many cases if done by + # fast-forwarding from the start of the file rather than traversing + # backwards. + self._vb_print('Rewinding to index {0}.'.format(ind)) + while self._cur_pos.index > ind and self._cur_pos.index > 0: + self._backup_one() + else: + # Fast-forward + self._vb_print('Fast-forwarding to index {0}.'.format(ind)) + while self._cur_pos.index < ind: + if not self.read(): + break # EOF + self._vb_print('New current position is {0}.'.format(self._cur_pos)) + + def _seek_to_timestamp(self, ts): + '''Seeks forward or backward in the log to find the given timestamp.''' + if ts == self._cur_pos.ts and not self.eof: + self._vb_print('Seek by timestamp: already at destination.') + return + elif ts < self._cur_pos.ts or self.eof: + # Rewind + self._vb_print('Rewinding to timestamp {0}.'.format(ts)) + while (self._cur_pos.ts > ts and self._cur_pos.index > 0) or \ + self.eof: + self._backup_one() + # Need to move one forward again, unless have hit the beginning + if self._cur_pos.ts < ts: + self.read() + else: + self._vb_print('Fast-forwarding to timestamp {0}.'.format(ts)) + # Fast-forward + while self._cur_pos.ts < ts: + if not self.read(): + break # EOF + self._vb_print('New current position is {0}.'.format(self._cur_pos)) + + def _set_eof_pos(self): + '''Sets the current position to the end-of-file value.''' + self._vb_print('Setting EOF at file position {0}, prev cur pos '\ + '{1}'.format(self._file.tell(), self._cur_pos)) + self._cur_pos.index += 1 # The "next" index + # Don't touch the time stamp (indicates the end time of the file) + self._cur_pos.prev = self._cur_pos.cache # This is the final entry + self._cur_pos.cache = 0 # No valid entry at current file position + self._cur_pos.fp = self._file.tell() # This is the end of the file + + def _set_start(self): + # Save the current position + current = self._file.tell() + # Move to the start + self._file.seek(0) + # Skip the metadata block + self._read() + # Skip the buffer + self._file.seek(self.BUFFER_SIZE, os.SEEK_CUR) + # Read the first entry + pos = self._file.tell() + entry = self._read() + self._start = CurPos(entry[self.INDEX], entry[self.TS], + entry[self.PREV], pos, self._file.tell()) + self._file.seek(current) + self._vb_print('Measured start position: {0}'.format(self._start)) + + def _update_cur_pos(self, val): + '''Updates the current pos from a data entry.''' + self._cur_pos.index = val[self.INDEX] + self._cur_pos.ts = val[self.TS] + self._cur_pos.prev = val[self.PREV] + self._cur_pos.cache = self._cur_pos.fp + self._cur_pos.fp = self._file.tell() + + def _write(self, data): + '''Pickle some data and write it to the file.''' + self._vb_print('Writing one data block.') + pickle.dump(data, self._file, pickle.HIGHEST_PROTOCOL) + diff --git a/rtshell/state_control_base.py b/rtshell/state_control_base.py new file mode 100644 index 0000000..4edc425 --- /dev/null +++ b/rtshell/state_control_base.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Base for the scripts that change component state. + +''' + + +import optparse +import os +import os.path +import rtctree.tree +import rtctree.path +import sys +import traceback + +import path +import rts_exceptions +import rtshell + + +def alter_component_states(action, paths, options, tree=None): + cmd_paths, fps = zip(*paths) + pathports = [rtctree.path.parse_path(fp) for fp in fps] + for ii, p in enumerate(pathports): + if p[1]: + raise rts_exceptions.NotAComponentError(cmd_paths[ii]) + if not p[0][-1]: + raise rts_exceptions.NotAComponentError(cmd_paths[ii]) + paths, ports = zip(*pathports) + + if not tree: + tree = rtctree.tree.RTCTree(paths=paths, filter=paths) + + for ii, p in enumerate(paths): + if not tree.has_path(p): + raise rts_exceptions.NoSuchObjectError(cmd_paths[ii]) + object_ = tree.get_node(p) + if object_.is_zombie: + raise rts_exceptions.ZombieObjectError(cmd_paths[ii]) + if not object_.is_component: + raise rts_exceptions.NotAComponentError(cmd_paths[ii]) + action(object_, options.ec_index) + + +def base_main(description, action, argv=None, tree=None): + usage = '''Usage: %prog [options] [ ...] +{0}'''.format(description) + version = rtshell.RTSH_VERSION + parser = optparse.OptionParser(usage=usage, version=version) + parser.add_option('-e', '--exec_context', dest='ec_index', type='int', + action='store', default=0, help='Index of the execution context '\ + 'to change state in. [Default: %default]') + parser.add_option('-v', '--verbose', dest='verbose', action='store_true', + default=False, + help='Output verbose information. [Default: %default]') + + if argv: + sys.argv = [sys.argv[0]] + argv + try: + options, args = parser.parse_args() + except optparse.OptionError, e: + print >>sys.stderr, 'OptionError:', e + return 1 + + if not args: + # If no path given then can't do anything. + print >>sys.stderr, '{0}: No components specified.'.format( + os.path.basename(sys.argv[0])) + return 1 + paths = [(p, path.cmd_path_to_full_path(p)) for p in args] + + try: + alter_component_states(action, paths, options, tree) + except Exception, e: + if options.verbose: + traceback.print_exc() + print >>sys.stderr, '{0}: {1}'.format(os.path.basename(sys.argv[0]), e) + return 1 + return 0 + + +# vim: tw=79 + diff --git a/rtshell/text_log.py b/rtshell/text_log.py new file mode 100644 index 0000000..1e49f9d --- /dev/null +++ b/rtshell/text_log.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Text-based log. + +''' + + +import copy +import os + +import ilog + + +############################################################################### +## Text-based log object. It only supports writing log files. It relies on +## the data types having suitable __repr__ methods. + +class TextLog(ilog.Log): + def __init__(self, filename='', *args, **kwargs): + self._is_open = False + self._fn = filename + super(TextLog, self).__init__(*args, **kwargs) + + def __str__(self): + if self._is_open: + return 'TextLog({0}, {1}) at position {2}.'.format(self._fn, + self._mode, self._file.tell()) + else: + return 'TextLog({0}, {1}).'.format(self._fn, self._mode) + + def write(self, timestamp, data): + pos = self._file.tell() + self._file.write('{0}\t{1}\n'.format(timestamp, data)) + self._vb_print('Wrote entry at {0}.'.format(pos)) + + def _close(self): + if not self._is_open: + return + self._file.close() + self._is_open = False + self._vb_print('Closed file.') + + def _get_cur_pos(self): + if self._is_open: + self._vb_print('Current position: {0}'.format(self._file.tell())) + return self._file.tell() + else: + self._vb_print('Current position: file closed.') + return 0 + + def _open(self): + if self._is_open: + return + if self._mode == 'w': + flags = 'w' + else: + raise NotImplementedError + self._file = open(self._fn, flags) + self._is_open = True + self._vb_print('Opened file {0} in mode {1}.'.format(self._fn, + self._mode)) + diff --git a/rtstart b/rtstart new file mode 100755 index 0000000..ae1fe5f --- /dev/null +++ b/rtstart @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstart command program. + +''' + + +import sys + +from rtshell import rtstart + + +if __name__ == '__main__': + sys.exit(rtstart.main()) + + +# vim: tw=79 + diff --git a/rtstart.bat b/rtstart.bat new file mode 100644 index 0000000..ab13750 --- /dev/null +++ b/rtstart.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstart.py %* + diff --git a/rtstodot b/rtstodot new file mode 100755 index 0000000..c970812 --- /dev/null +++ b/rtstodot @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to visualise RT Systems. + +''' + + +import sys + +import rtshell.rtstodot + + +if __name__ == '__main__': + sys.exit(rtshell.rtstodot.main()) + + +# vim: tw=79 + diff --git a/rtstodot.bat b/rtstodot.bat new file mode 100644 index 0000000..dee9290 --- /dev/null +++ b/rtstodot.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstodot.py %* + diff --git a/rtstop b/rtstop new file mode 100755 index 0000000..df4bc5c --- /dev/null +++ b/rtstop @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstop command program. + +''' + + +import sys + +from rtshell import rtstop + + +if __name__ == '__main__': + sys.exit(rtstop.main()) + + +# vim: tw=79 + diff --git a/rtstop.bat b/rtstop.bat new file mode 100644 index 0000000..dad7723 --- /dev/null +++ b/rtstop.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtstop.py %* + diff --git a/rtteardown b/rtteardown new file mode 100755 index 0000000..18b62f4 --- /dev/null +++ b/rtteardown @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +rtteardown command. + +''' + + +import sys + +from rtshell import rtteardown + + +if __name__ == '__main__': + sys.exit(rtteardown.main()) + + +# vim: tw=79 + diff --git a/rtteardown.bat b/rtteardown.bat new file mode 100644 index 0000000..91cca69 --- /dev/null +++ b/rtteardown.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtteardown.py %* + diff --git a/rtvlog b/rtvlog new file mode 100755 index 0000000..ecd9d8d --- /dev/null +++ b/rtvlog @@ -0,0 +1,32 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Command to view the log being produced by a component. + +''' + + +import sys + +from rtshell import rtvlog + + +if __name__ == '__main__': + sys.exit(rtvlog.main()) + + +# vim: tw=79 + diff --git a/rtvlog.bat b/rtvlog.bat new file mode 100644 index 0000000..07038bd --- /dev/null +++ b/rtvlog.bat @@ -0,0 +1,13 @@ +@echo off +rem Copyright (C) 2009-2014 +rem Geoffrey Biggs +rem RT-Synthesis Research Group +rem Intelligent Systems Research Institute, +rem National Institute of Advanced Industrial Science and Technology (AIST), +rem Japan +rem All rights reserved. +rem Licensed under the Eclipse Public License -v 1.0 (EPL) +rem http://www.opensource.org/licenses/eclipse-1.0.txt + +rtvlog.py %* + diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..3228d2d --- /dev/null +++ b/setup.py @@ -0,0 +1,237 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2014 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +File: setup.py + +rtshell install script. + +''' + +# $Source$ + + +from distutils.command.install_scripts import install_scripts +from distutils.command.install_data import install_data +from distutils.core import setup +import os +import os.path +import subprocess +import sys + + +# Hacky method of installing the documentation. Need a nice hook for this. +def get_files(dir, ext=None): + files = [os.path.join(dir, f) for f in os.listdir(dir) \ + if os.path.isfile(os.path.join(dir, f))] + if ext: + return [f for f in files if os.path.splitext(f)[1] == ext] + else: + return files + +if sys.platform != 'win32': + cwd = os.path.join(os.getcwd(), 'doc') + s = raw_input('Generate documentation? ') + if s.lower() == 'y' or s.lower() == 'YES': + print 'Generating documentation' + p = subprocess.Popen(['./make_docs', 'man', 'html', 'pdf', '-v'], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) + stdout, stderr = p.communicate() + if p.returncode != 0: + print 'Failed to generate documentation. Check docutils are installed.' + print stderr +try: + man_files_en = get_files(os.path.join(os.getcwd(), 'doc/man/man1')) + html_files_en = get_files(os.path.join(os.getcwd(), 'doc/html')) + pdf_files_en = get_files(os.path.join(os.getcwd(), 'doc/pdf'), ext='.pdf') + man_files_ja = get_files(os.path.join(os.getcwd(), 'doc/man/ja/man1')) + html_files_ja = get_files(os.path.join(os.getcwd(), 'doc/html/ja')) + pdf_files_ja = get_files(os.path.join(os.getcwd(), 'doc/pdf/ja'), ext='.pdf') +except OSError: + man_files_en = [] + html_files_en = [] + pdf_files_en = [] + man_files_ja = [] + html_files_ja = [] + pdf_files_ja = [] + + +base_scripts = ['rtact', + 'rtcat', + 'rtcheck', + 'rtcomp', + 'rtcon', + 'rtconf', + 'rtcryo', + 'rtdeact', + 'rtdel', + 'rtdis', + 'rtexit', + 'rtfind', + 'rtinject', + 'rtlog', + 'rtls', + 'rtdoc', + 'rtmgr', + 'rtprint', + 'rtpwd', + 'rtreset', + 'rtresurrect', + 'rtstart', + 'rtstodot', + 'rtstop', + 'rtteardown', + 'rtvlog'] +if sys.platform == 'win32': + batch_files = ['rtact.bat', + 'rtcat.bat', + 'rtcheck.bat', + 'rtcomp.bat', + 'rtcon.bat', + 'rtconf.bat', + 'rtcryo.bat', + 'rtcwd.bat', + 'rtdeact.bat', + 'rtdel.bat', + 'rtdis.bat', + 'rtdoc.bat', + 'rtexit.bat', + 'rtfind.bat', + 'rtinject.bat', + 'rtlog.bat', + 'rtls.bat', + 'rtmgr.bat', + 'rtprint.bat', + 'rtpwd.bat', + 'rtreset.bat', + 'rtresurrect.bat', + 'rtstart.bat', + 'rtstop.bat', + 'rtteardown.bat', + 'rtvlog.bat'] + scripts = base_scripts + batch_files + data_files = [('Doc/rtshell', html_files_en + pdf_files_en), + ('Doc/rtshell/ja', html_files_ja + pdf_files_ja)] +else: + scripts = base_scripts + data_files = [('share/rtshell', ['bash_completion', 'shell_support.in']), + ('share/man/man1', man_files_en), + ('share/man/ja/man1', man_files_ja), + ('share/doc/rtshell', html_files_en + pdf_files_en), + ('share/doc/rtshell/ja', html_files_ja + pdf_files_ja)] + + +class InstallRename(install_scripts): + def run(self): + install_scripts.run(self) + if sys.platform == 'win32': + # Rename the installed scripts to add .py on the end for Windows + print 'Renaming scripts' + for s in base_scripts: + dest = os.path.join(self.install_dir, s + '.py') + if os.path.exists(dest): + os.remove(dest) + self.move_file(os.path.join(self.install_dir, s), dest) + # Make links for the docs + #print 'Creating Start Menu links' + #rtshell_dir = os.path.join(self._get_start_menu(), 'rtshell') + #if not os.path.exists(rtshell_dir): + #os.mkdir(rtshell_dir) + #docs_en_path = os.path.join(rtshell_dir, + #'Documentation (English).url') + #docs_ja_path = os.path.join(rtshell_dir, + #'Documentation (Japanese).lnk') + + def _get_start_menu(self): + if sys.platform != 'win32': + return '' + import ctypes + import ctypes.wintypes + SHGetFolderPath = ctypes.windll.shell32.SHGetFolderPathW + SHGetFolderPath.argtypes = [ctypes.wintypes.HWND, ctypes.c_int, + ctypes.wintypes.HANDLE, ctypes.wintypes.DWORD, + ctypes.wintypes.LPCWSTR] + path = ctypes.wintypes.create_unicode_buffer(ctypes.wintypes.MAX_PATH) + SHGetFolderPath(0, 2, 0, 0, path) + return path.value + + +class InstallConfigure(install_data): + def run(self): + install_data.run(self) + if sys.platform != 'win32': + cmd = 'echo $SHELL | grep -q bash && source {dir}/bash_completion\n' + dest = os.path.join(self.install_dir, 'share/rtshell', 'shell_support') + if os.path.isfile(dest): + os.remove(dest) + self.move_file(os.path.join(self.install_dir, 'share/rtshell', + 'shell_support.in'), dest) + with open(dest, 'a') as f: + f.writelines((cmd.format(dir=os.path.join(self.install_dir, + 'share/rtshell')), '\n')) + self.config_bash_compl() + + def config_bash_compl(self): + COMPOPT_NOSPACE = 'compopt -o nospace' + COMPOPT_FILENAME = 'compopt -o filenames' + COMPLETE_NOSPACE = '-o nospace' + compl_script = '{0}/bash_completion'.format( + os.path.join(self.install_dir, 'share/rtshell')) + if sys.platform == 'darwin': + replace = ['-e', 's/@COMPOPT_NOSPACE@/:/g', '-e', + 's/@COMPOPT_FILENAME@/:/g', '-e', + 's/@COMPLETE_NOSPACE@/{0}/g'.format(COMPLETE_NOSPACE)] + else: + replace = ['-e', "'s/@COMPOPT_NOSPACE@/{0}/g'".format( + COMPOPT_NOSPACE), '-e', "'s/@COMPOPT_FILENAME@/{0}/g'".format( + COMPOPT_FILENAME), '-e', "'s/@COMPLETE_NOSPACE@//g'"] + p = subprocess.Popen(['sed'] + replace + ['-i', '', compl_script], + stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd) + stdout, stderr = p.communicate() + if p.returncode != 0: + print 'Failed to filter bash_completion.' + print stderr + + +setup(name='rtshell', + version='4.0.0', + description='Shell commands for managing RT Components and RT Systems.', + author='Geoffrey Biggs and contributors', + author_email='git@killbots.net', + url='http://github.com/gbiggs/rtshell', + license='EPL', + long_description='Shell commands for managing RT-Middleware.', + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'License :: OSI Approved :: EPL License', + 'Natural Language :: English', + 'Operating System :: OS Independent', + 'Programming Language :: Python :: 2.6', + 'Programming Language :: Python :: 2.7', + 'Topic :: Software Development', + 'Topic :: Utilities' + ], + packages=['rtshell'], + scripts=scripts, + data_files=data_files, + cmdclass={'install_scripts':InstallRename, + 'install_data':InstallConfigure} + ) + + +# vim: tw=79 + diff --git a/shell_support.in b/shell_support.in new file mode 100644 index 0000000..68e2778 --- /dev/null +++ b/shell_support.in @@ -0,0 +1,20 @@ +# Copyright (C) 2009-2014 +# Geoffrey Biggs +# RT-Synthesis Research Group +# Intelligent Systems Research Institute, +# National Institute of Advanced Industrial Science and Technology (AIST), +# Japan +# All rights reserved. +# Licensed under the Eclipse Public License -v 1.0 (EPL) +# http://www.opensource.org/licenses/eclipse-1.0.txt + +rtcwd() +{ + eval $(python -c "import sys; import rtshell.rtcwd; sys.exit(rtshell.rtcwd.main(['${1}']))") +} + +rtvis() +{ + rtcryo | rtstodot | dot -T xlib +} + diff --git a/test/MyData/__init__.py b/test/MyData/__init__.py new file mode 100644 index 0000000..884b2be --- /dev/null +++ b/test/MyData/__init__.py @@ -0,0 +1,13 @@ +# DO NOT EDIT THIS FILE! +# +# Python module MyData generated by omniidl + +import omniORB +omniORB.updateModule("MyData") + +# ** 1. Stub files contributing to this module +import test_idl + +# ** 2. Sub-modules + +# ** 3. End diff --git a/test/MyData__POA/__init__.py b/test/MyData__POA/__init__.py new file mode 100644 index 0000000..9f8ba84 --- /dev/null +++ b/test/MyData__POA/__init__.py @@ -0,0 +1,13 @@ +# DO NOT EDIT THIS FILE! +# +# Python module MyData__POA generated by omniidl + +import omniORB +omniORB.updateModule("MyData__POA") + +# ** 1. Stub files contributing to this module +import test_idl + +# ** 2. Sub-modules + +# ** 3. End diff --git a/test/blorg.py b/test/blorg.py new file mode 100644 index 0000000..92bd440 --- /dev/null +++ b/test/blorg.py @@ -0,0 +1,5 @@ +a = 'blorg' + +def format(data): + return 'formatted' + diff --git a/test/c1.rtlog b/test/c1.rtlog new file mode 100644 index 0000000000000000000000000000000000000000..f6963ed5ecdf138c777fbc22ad7cfecd183c18ee GIT binary patch literal 1221 zcmchW&2G~`6ovgWcAQBl6ezG{>40!3S;3|%Eka6U6x7Z#vc_hbL^!tZcw8D#q_Bxl z_pEq^K0tT8Kv%p955U-I9YqnM=>o6rwZ~_^d*;kkd%OGVaDVsv)|VbA0T=0jg`tzg zTzF!fuoQP?d62LGgWC8C+5~i)7{xb0fji!(g5uX9>tiqo_KspcqCzkZ<~w3~!zjrF zRKCeSB06GV5fo*k6smG*EQ#HoNg zWTR-Dyz_z+0h^?W`pHWre+pYYctD;tOR0HP>NGD! zUd;uZ0`wuxd^&?i&QvSSNr$84W9Wr(AMa(n8>bi)X^lDo%_iDW0=m0{h%t;luoFNX zL{P%nF&OT-PK~le&q$aDMb!w1juTbnDd5dz2KPP2ro&W#< literal 0 HcmV?d00001 diff --git a/test/c1_comp b/test/c1_comp new file mode 100755 index 0000000..c1eb3d1 --- /dev/null +++ b/test/c1_comp @@ -0,0 +1,89 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + + +import imp +import inspect +import sys +from traceback import print_exc +from time import time +from optparse import OptionParser, OptionError + +import OpenRTM_aist +import RTC + + +class C1(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, mgr): + OpenRTM_aist.DataFlowComponentBase.__init__(self, mgr) + + def onInitialize(self): + try: + f, p, d = imp.find_module('MyData') + self._m = imp.load_module('MyData', f, p, d) + if f: + f.close() + f, p, d = imp.find_module('MyData__POA') + self._m_poa = imp.load_module('MyData__POA', f, p, d) + if f: + f.close() + self._data_type = self._m.Bleg + self._out_data = self._data_type(0, 0) + self._outport = OpenRTM_aist.OutPort('output', self._out_data, + OpenRTM_aist.RingBuffer(8)) + self.registerOutPort('output', self._outport) + self._count = 0 + except: + print_exc() + return RTC.RTC_ERROR + return RTC.RTC_OK + + def onExecute(self, ec_id): + try: + val = eval('self._m.Bleg(1, {0})'.format(self._count)) + self._outport.write(val) + self._count += 1 + except: + print_exc() + return RTC.RTC_ERROR + return RTC.RTC_OK + + +def comp_fact(opts, port, mods): + def fact_fun(mgr): + const = eval_const(opts.const, mods) + if not const: + return None + return C1(mgr, const, port, opts.verbosity) + return fact_fun + + +def init(mgr): + spec = ['implementation_id', 'C1', + 'type_name', 'C1', + 'description', 'Custom data type output component.', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs, AIST', + 'category', 'DataProducer', + 'activity_type', 'DataFlowComponent', + 'max_instance', '999', + 'language', 'Python', + 'lang_type', 'SCRIPT', + ''] + profile = OpenRTM_aist.Properties(defaults_str=spec) + mgr.registerFactory(profile, C1, + OpenRTM_aist.Delete) + comp = mgr.createComponent("C1") + + +def main(): + mgr = OpenRTM_aist.Manager.init(len(sys.argv), sys.argv) + mgr.setModuleInitProc(init) + mgr.activateManager() + mgr.runManager() + return 0 + + +if __name__ == "__main__": + sys.exit(main()) + diff --git a/test/c2_comp b/test/c2_comp new file mode 100755 index 0000000..87af47c --- /dev/null +++ b/test/c2_comp @@ -0,0 +1,94 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +import imp +import OpenRTM_aist +import os +import os.path +import RTC +import sys +import traceback + + +import MyData, MyData__POA + + +class C2(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, mgr): + OpenRTM_aist.DataFlowComponentBase.__init__(self, mgr) + self._df = './test/c2_rcvd' + + def onInitialize(self): + try: + if os.path.exists(self._df): + os.remove(self._df) + + f, p, d = imp.find_module('MyData') + self._m = imp.load_module('MyData', f, p, d) + if f: + f.close() + f, p, d = imp.find_module('MyData__POA') + self._m_poa = imp.load_module('MyData__POA', f, p, d) + if f: + f.close() + self._data_type = self._m.Bleg + self._in_data = self._data_type(0, 0) + self._inport = OpenRTM_aist.InPort('input', self._in_data, + OpenRTM_aist.RingBuffer(8)) + self.registerInPort('input', self._inport) + except: + traceback.print_exc() + return RTC.RTC_ERROR + return RTC.RTC_OK + + def onExecute(self, ec_id): + try: + if self._inport.isNew(): + d = self._inport.read() + with open(self._df, 'a+') as f: + f.write('{0}\n'.format(d)) + print d + except: + traceback.print_exc() + return RTC.RTC_ERROR + return RTC.RTC_OK + + +def comp_fact(opts, port, mods): + def fact_fun(mgr): + const = eval_const(opts.const, mods) + if not const: + return None + return C2(mgr, const, port, opts.verbosity) + return fact_fun + + +def init(mgr): + spec = ['implementation_id', 'C2', + 'type_name', 'C2', + 'description', 'Custom data input component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs, AIST', + 'category', 'DataProducer', + 'activity_type', 'DataFlowComponent', + 'max_instance', '999', + 'language', 'Python', + 'lang_type', 'SCRIPT', + ''] + profile = OpenRTM_aist.Properties(defaults_str=spec) + mgr.registerFactory(profile, C2, + OpenRTM_aist.Delete) + comp = mgr.createComponent("C2") + + +def main(): + mgr = OpenRTM_aist.Manager.init(len(sys.argv), sys.argv) + mgr.setModuleInitProc(init) + mgr.activateManager() + mgr.runManager() + return 0 + + +if __name__ == "__main__": + sys.exit(main()) + diff --git a/test/doc2_comp b/test/doc2_comp new file mode 100755 index 0000000..94c88d5 --- /dev/null +++ b/test/doc2_comp @@ -0,0 +1,70 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Component with nothing to document. + +''' + + +import OpenRTM_aist +import os +import os.path +import RTC +import sys + + +class StdComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + + def onExecute(self, ec_id): + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'Doc2', + 'type_name', 'Doc2', + 'description', 'Documentation component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, StdComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Doc2') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/doc_comp b/test/doc_comp new file mode 100755 index 0000000..8eba0a1 --- /dev/null +++ b/test/doc_comp @@ -0,0 +1,100 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Component with lots of documentation. + +''' + + +import OpenRTM_aist +import os +import os.path +import RTC +import sys + + +class StdComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + self._param = [0] + self._df = './test/std_rcvd' + + def onInitialize(self): + self._data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._inport = OpenRTM_aist.InPort('in', self._data) + self._inport.addProperty('description', 'This port receives stuff.') + self.addInPort('in', self._inport) + self.bindParameter('param', self._param, "0") + if os.path.exists(self._df): + os.remove(self._df) + return RTC.RTC_OK + + def onExecute(self, ec_id): + if self._inport.isNew(): + d = self._inport.read().data + with open(self._df, 'a+') as f: + f.write('{0}\n'.format(d)) + print d + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'Doc', + 'type_name', 'Doc', + 'description', 'Documentation component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + 'conf.__doc__.__order__', '', + 'conf.__doc__.__license__', 'EPL', + 'conf.__doc__.__contact__', 'a@example.com', + 'conf.__doc__.__url__', 'http://www.openrtm.org', + 'conf.__doc__.intro', 'This is the introduction.', + 'conf.__doc__.reqs', 'This component requires nothing.', + 'conf.__doc__.install', 'You cannot install this component.', + 'conf.__doc__.usage', 'You cannot use it, either.', + 'conf.__doc__.misc', 'Miscellaneous is hard to spell.', + 'conf.__doc__.changelog', 'No changes.', + 'conf.__doc__.Another', 'Another section.', + 'conf.default.param', '0', + 'conf.__description__.param', 'A test parameter.', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, StdComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Doc') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/err_comp b/test/err_comp new file mode 100755 index 0000000..a91d058 --- /dev/null +++ b/test/err_comp @@ -0,0 +1,73 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Error state component for tests. + +''' + + +import OpenRTM_aist +import RTC +import sys + + +class ErrComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + + def onInitialize(self): + self._data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._inport = OpenRTM_aist.InPort('in', self._data) + self.addInPort('in', self._inport) + return RTC.RTC_OK + + def onActivated(self, ec_id): + return RTC.RTC_ERROR + + +comp_spec = ['implementation_id', 'Err', + 'type_name', 'Err', + 'description', 'Error component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '1', + 'language', 'Python', + 'lang_type', 'script', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, ErrComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Err') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/logfile_unittests.py b/test/logfile_unittests.py new file mode 100755 index 0000000..fa92793 --- /dev/null +++ b/test/logfile_unittests.py @@ -0,0 +1,1598 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Unit tests for the log classes + +''' + + +import os +import os.path +import sys +import unittest + +import rtshell.ilog +import rtshell.simpkl_log + + +METADATA=[1, 'lot', 'of', ('meta', 'data')] +TIMESTAMPS=[0.2, 0.5, 1, 1.3, 1.7, 2.001, 3.2, 3.3, 3.4, 5.3] +DATA=['Val1', 'Value2', 'Entry 3', 'Data block 4', 'Value 5', 'Entry6', + 'Data 7', 'Val8', 'Entry 9', 'Val 10'] + + +VERBOSITY=False + + +#class WriteBase(unittest.TestCase): +class WriteBase(): + def setUp(self): + self.log = rtshell.simpkl_log.SimplePickleLog(filename='test.log', + mode='w', meta=METADATA, verbose=VERBOSITY) + + def tearDown(self): + self.log.close() + if os.path.isfile(os.path.join(os.getcwd(), 'test.log')): + os.remove(os.path.join(os.getcwd(), 'test.log')) + + +class ReadBase(unittest.TestCase): + def setUp(self): + self.write_test_log() + self.log = rtshell.simpkl_log.SimplePickleLog(filename='test.log', + mode='r', meta=METADATA, verbose=VERBOSITY) + + def tearDown(self): + self.log.close() + if os.path.isfile(os.path.join(os.getcwd(), 'test.log')): + os.remove(os.path.join(os.getcwd(), 'test.log')) + + def write_test_log(self): + log = rtshell.simpkl_log.SimplePickleLog(filename='test.log', mode='w', + meta=METADATA, verbose=VERBOSITY) + for t, d in zip(TIMESTAMPS, DATA): + log.write(t, d) + log.close() + + +class WriteTests(WriteBase): + def test_write(self): + if VERBOSITY: + print >>sys.stderr, '===== write =====' + for t, d in zip(TIMESTAMPS, DATA): + self.log.write(t, d) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + +class ReadTests(ReadBase): + def test_read_whole_log(self): + if VERBOSITY: + print >>sys.stderr, '===== read_whole_log =====' + for ii in range(10): + entry = self.log.read() + if not entry: + # End of log + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + else: + ind, ts, d = entry[0] + self.assertEqual(ind, ii) + self.assertEqual(ts, TIMESTAMPS[ii]) + self.assertEqual(d, DATA[ii]) + if not self.log.eof: + self.assertEqual(self.log.pos, (ii + 1, TIMESTAMPS[ii + 1])) + else: + self.assertEqual(self.log.pos, (ii + 1, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_start_at_start(self): + if VERBOSITY: + print >>sys.stderr, '===== get_start_at_start =====' + self.assertEqual(self.log.start, (0, TIMESTAMPS[0])) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_start_at_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== get_start_at_mid =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.start, (0, TIMESTAMPS[0])) + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 5) + self.assertEqual(ts, TIMESTAMPS[5]) + self.assertEqual(d, DATA[5]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_start_at_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== get_start_at_eof =====' + for ii in range(11): + self.log.read() + self.assertEqual(self.log.start, (0, TIMESTAMPS[0])) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual(self.log.read(), []) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_end_at_start(self): + if VERBOSITY: + print >>sys.stderr, '===== get_end_at_start =====' + self.assertEqual(self.log.end, (9, TIMESTAMPS[-1])) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_end_at_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== get_end_at_mid =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.end, (9, TIMESTAMPS[-1])) + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 5) + self.assertEqual(ts, TIMESTAMPS[5]) + self.assertEqual(d, DATA[5]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_end_at_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== get_end_at_eof =====' + for ii in range(11): + self.log.read() + self.assertEqual(self.log.end, (9, TIMESTAMPS[9])) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual(self.log.read(), []) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_eof =====' + for ii in range(10): + self.log.read() + self.assert_(self.log.eof) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual(self.log.read(), []) + self.assert_(self.log.eof) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_start_start(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.assertEqual([], self.log.read(number=0)) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_start_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(number=4) + self.assertEqual(4, len(d)) + for ii in range(4): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (4, TIMESTAMPS[4])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_start_end(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(number=10) + self.assertEqual(10, len(d)) + for ii in range(10): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_start_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(number=11) + self.assertEqual(10, len(d)) + for ii in range(10): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_mid_start(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_mid_start =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + self.assertRaises(ValueError, self.log.read, number=-1) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_mid_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_mid_mid =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + d = self.log.read(number=4) + self.assertEqual(4, len(d)) + for ii in range(4): + self.assertEqual(d[ii][0], ii + 3) + self.assertEqual(d[ii][1], TIMESTAMPS[ii + 3]) + self.assertEqual(d[ii][2], DATA[ii + 3]) + self.assertEqual(self.log.pos, (7, TIMESTAMPS[7])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_mid_end(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_mid_end =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + d = self.log.read(number=7) + self.assertEqual(7, len(d)) + for ii in range(7): + self.assertEqual(d[ii][0], ii + 3) + self.assertEqual(d[ii][1], TIMESTAMPS[ii + 3]) + self.assertEqual(d[ii][2], DATA[ii + 3]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_mid_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_mid_eof =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + d = self.log.read(number=8) + self.assertEqual(7, len(d)) + for ii in range(7): + self.assertEqual(d[ii][0], ii + 3) + self.assertEqual(d[ii][1], TIMESTAMPS[ii + 3]) + self.assertEqual(d[ii][2], DATA[ii + 3]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_num_end_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_num_end_eof =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read(number=2)) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_start_start(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.assertEqual([], self.log.read(timestamp=0.1)) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(timestamp=0.2) + self.assertEqual(d[0][0], 0) + self.assertEqual(d[0][1], TIMESTAMPS[0]) + self.assertEqual(d[0][2], DATA[0]) + self.assertEqual(self.log.pos, (1, TIMESTAMPS[1])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_start_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(timestamp=1.3) + self.assertEqual(4, len(d)) + for ii in range(4): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (4, TIMESTAMPS[4])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_start_mid_between(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_start_mid_between =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(timestamp=1.45) + self.assertEqual(4, len(d)) + for ii in range(4): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (4, TIMESTAMPS[4])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_start_end(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(timestamp=5.3) + self.assertEqual(10, len(d)) + for ii in range(10): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_start_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_start_mid =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + d = self.log.read(timestamp=5.4) + self.assertEqual(10, len(d)) + for ii in range(10): + self.assertEqual(d[ii][0], ii) + self.assertEqual(d[ii][1], TIMESTAMPS[ii]) + self.assertEqual(d[ii][2], DATA[ii]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_mid_start(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_mid_start =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + self.assertRaises(ValueError, self.log.read, timestamp=-1) + self.assertEqual([], self.log.read(timestamp=0.1)) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_mid_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_mid_mid =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + d = self.log.read(timestamp=3.25) + self.assertEqual(4, len(d)) + for ii in range(4): + self.assertEqual(d[ii][0], ii + 3) + self.assertEqual(d[ii][1], TIMESTAMPS[ii + 3]) + self.assertEqual(d[ii][2], DATA[ii + 3]) + self.assertEqual(self.log.pos, (7, TIMESTAMPS[7])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_mid_end(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_mid_end =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + d = self.log.read(timestamp=5.3) + self.assertEqual(7, len(d)) + for ii in range(7): + self.assertEqual(d[ii][0], ii + 3) + self.assertEqual(d[ii][1], TIMESTAMPS[ii + 3]) + self.assertEqual(d[ii][2], DATA[ii + 3]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_mid_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_mid_eof =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + d = self.log.read(timestamp=5.4) + self.assertEqual(7, len(d)) + for ii in range(7): + self.assertEqual(d[ii][0], ii + 3) + self.assertEqual(d[ii][1], TIMESTAMPS[ii + 3]) + self.assertEqual(d[ii][2], DATA[ii + 3]) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_read_ts_end_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== read_ts_end_eof =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.assertEqual([], self.log.read(timestamp=5.4)) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_backup_start(self): + if VERBOSITY: + print >>sys.stderr, '===== backup_start =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log._backup_one() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assertEqual(self.log.pos, (1, TIMESTAMPS[1])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_backup_to_start(self): + if VERBOSITY: + print >>sys.stderr, '===== backup_to_start =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.read() + self.assertEqual(self.log.pos, (1, TIMESTAMPS[1])) + self.log._backup_one() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.log.read() + self.log._backup_one() + self.log._backup_one() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assertEqual(self.log.pos, (1, TIMESTAMPS[1])) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_backup_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== backup_mid =====' + for ii in range(3): + self.log.read() + self.assertEqual(self.log.pos, (3, TIMESTAMPS[3])) + self.log._backup_one() + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_backup_end(self): + if VERBOSITY: + print >>sys.stderr, '===== backup_end =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log._backup_one() + self.assertEqual(self.log.pos, (8, TIMESTAMPS[8])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 8) + self.assertEqual(ts, TIMESTAMPS[8]) + self.assertEqual(d, DATA[8]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_backup_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== backup_eof =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log._backup_one() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.assert_(not self.log.eof) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_rewind_at_start(self): + if VERBOSITY: + print >>sys.stderr, '===== rewind_at_start =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.rewind() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_rewind_at_mid(self): + if VERBOSITY: + print >>sys.stderr, '===== rewind_at_mid =====' + for ii in range(4): + self.log.read() + self.assertEqual(self.log.pos, (4, TIMESTAMPS[4])) + self.log.rewind() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_rewind_at_end(self): + if VERBOSITY: + print >>sys.stderr, '===== rewind_at_mid =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.rewind() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_rewind_at_eof(self): + if VERBOSITY: + print >>sys.stderr, '===== rewind_at_mid =====' + for ii in range(10): + self.log.read() + self.assert_(self.log.eof) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.log.rewind() + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.assert_(not self.log.eof) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_start_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_start_ind =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(index=0) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_mid_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_mid_ind =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(index=2) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_end_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_end_ind =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(index=9) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_eof_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_eof_ind =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(index=11) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_start_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_start_ind =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(index=0) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_rewind_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_rewind_ind =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(index=2) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_mid_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_mid_ind =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(index=5) + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 5) + self.assertEqual(ts, TIMESTAMPS[5]) + self.assertEqual(d, DATA[5]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_ff_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_ff_ind =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(index=7) + self.assertEqual(self.log.pos, (7, TIMESTAMPS[7])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 7) + self.assertEqual(ts, TIMESTAMPS[7]) + self.assertEqual(d, DATA[7]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_end_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_end_ind =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(index=9) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_eof_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_eof_ind =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(index=10) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_start_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_start_ind =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(index=0) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_mid_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_mid_ind =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(index=2) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_end_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_end_ind =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(index=9) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.assert_(not self.log.eof) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_eof_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_eof_ind =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(index=10) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_start_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_start_ind =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(index=0) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_mid_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_mid_ind =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(index=2) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_end_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_end_ind =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(index=9) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.assert_(not self.log.eof) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_eof_ind(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_eof_ind =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(index=10) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_before_start_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_before_start_ts =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(timestamp=TIMESTAMPS[0] - 1) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_start_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_start_ts =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(timestamp=TIMESTAMPS[0]) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_before_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_before_mid_ts =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(timestamp=TIMESTAMPS[2] - \ + (TIMESTAMPS[2] - TIMESTAMPS[1]) * 0.6) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_mid_ts =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(timestamp=TIMESTAMPS[2]) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_end_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_end_ts =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(timestamp=TIMESTAMPS[9]) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_start_eof_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_start_eof_ts =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + self.log.seek(timestamp=TIMESTAMPS[9] + 1) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_before_start_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_before_start_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[0] - 1) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_start_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_start_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[0]) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_rewind_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_rewind_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[2]) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_before_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_before_mid_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[2] - \ + (TIMESTAMPS[2] - TIMESTAMPS[1]) * 0.6) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_mid_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[5]) + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 5) + self.assertEqual(ts, TIMESTAMPS[5]) + self.assertEqual(d, DATA[5]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_after_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_after_mid_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[7] - \ + (TIMESTAMPS[7] - TIMESTAMPS[6]) * 0.6) + self.assertEqual(self.log.pos, (7, TIMESTAMPS[7])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 7) + self.assertEqual(ts, TIMESTAMPS[7]) + self.assertEqual(d, DATA[7]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_ff_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_ff_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[7]) + self.assertEqual(self.log.pos, (7, TIMESTAMPS[7])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 7) + self.assertEqual(ts, TIMESTAMPS[7]) + self.assertEqual(d, DATA[7]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_end_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_end_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[9]) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_mid_eof_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_mid_eof_ts =====' + for ii in range(5): + self.log.read() + self.assertEqual(self.log.pos, (5, TIMESTAMPS[5])) + self.log.seek(timestamp=TIMESTAMPS[9] + 1) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_start_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_start_ts =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(timestamp=TIMESTAMPS[0]) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_before_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_before_mid_ts =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(timestamp=TIMESTAMPS[2] - \ + (TIMESTAMPS[2] - TIMESTAMPS[1]) * 0.6) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_mid_ts =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(timestamp=TIMESTAMPS[2]) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_end_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_end_ts =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(timestamp=TIMESTAMPS[9]) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.assert_(not self.log.eof) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_end_eof_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_end_eof_ts =====' + for ii in range(9): + self.log.read() + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.log.seek(timestamp=TIMESTAMPS[9] + 1) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_start_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_start_ts =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[9])) + self.assert_(self.log.eof) + self.log.seek(timestamp=TIMESTAMPS[0]) + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 0) + self.assertEqual(ts, TIMESTAMPS[0]) + self.assertEqual(d, DATA[0]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_before_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_before_mid_ts =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(timestamp=TIMESTAMPS[2] - \ + (TIMESTAMPS[2] - TIMESTAMPS[1]) * 0.6) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_mid_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_mid_ts =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(timestamp=TIMESTAMPS[2]) + self.assertEqual(self.log.pos, (2, TIMESTAMPS[2])) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 2) + self.assertEqual(ts, TIMESTAMPS[2]) + self.assertEqual(d, DATA[2]) + self.assert_(not self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_end_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_end_ts =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(timestamp=TIMESTAMPS[9]) + self.assertEqual(self.log.pos, (9, TIMESTAMPS[9])) + self.assert_(not self.log.eof) + ind, ts, d = self.log.read()[0] + self.assertEqual(ind, 9) + self.assertEqual(ts, TIMESTAMPS[9]) + self.assertEqual(d, DATA[9]) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_seek_eof_eof_ts(self): + if VERBOSITY: + print >>sys.stderr, '===== seek_eof_eof_ts =====' + for ii in range(10): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.seek(timestamp=TIMESTAMPS[9] + 1) + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assertEqual([], self.log.read()) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_get_cur_pos(self): + if VERBOSITY: + print >>sys.stderr, '===== get_cur_pos =====' + self.assertEqual(self.log.pos, (0, TIMESTAMPS[0])) + for ii in range(4): + self.log.read() + self.assertEqual(self.log.pos, (4, TIMESTAMPS[4])) + for ii in range(6): + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + self.log.read() + self.assertEqual(self.log.pos, (10, TIMESTAMPS[-1])) + self.assert_(self.log.eof) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + + +class OtherTests(unittest.TestCase): + def setUp(self): + self.write_test_log() + + def tearDown(self): + if os.path.isfile(os.path.join(os.getcwd(), 'test.log')): + os.remove(os.path.join(os.getcwd(), 'test.log')) + + def write_test_log(self): + log = rtshell.simpkl_log.SimplePickleLog(filename='test.log', mode='w', + meta=METADATA, verbose=VERBOSITY) + for t, d in zip(TIMESTAMPS, DATA): + log.write(t, d) + log.close() + + def test_with(self): + if VERBOSITY: + print >>sys.stderr, '===== with =====' + with rtshell.simpkl_log.SimplePickleLog(filename='test.log', + mode='r', meta=METADATA, verbose=VERBOSITY) as log: + for ii in range(10): + entry = log.read() + if not entry: + # End of log + self.assertEqual(log.pos, (10, TIMESTAMPS[-1])) + else: + ind, ts, d = entry[0] + self.assertEqual(ind, ii) + self.assertEqual(ts, TIMESTAMPS[ii]) + self.assertEqual(d, DATA[ii]) + if not log.eof: + self.assertEqual(log.pos, (ii + 1, TIMESTAMPS[ii + 1])) + else: + self.assertEqual(log.pos, (ii + 1, TIMESTAMPS[-1])) + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + def test_iterator(self): + if VERBOSITY: + print >>sys.stderr, '===== iterator =====' + log = rtshell.simpkl_log.SimplePickleLog(filename='test.log', + mode='r', meta=METADATA, verbose=VERBOSITY) + for (ii, entry) in enumerate(log): + if not entry: + # End of log + self.assertEqual(lf.pos, (10, TIMESTAMPS[-1])) + else: + ind, ts, d = entry + self.assertEqual(ind, ii) + self.assertEqual(ts, TIMESTAMPS[ii]) + self.assertEqual(d, DATA[ii]) + if not log.eof: + self.assertEqual(log.pos, (ii + 1, TIMESTAMPS[ii + 1])) + else: + self.assertEqual(log.pos, (ii + 1, TIMESTAMPS[-1])) + log.close() + if VERBOSITY: + print >>sys.stderr, '===== ===== =====' + + +class TimestampTests(unittest.TestCase): + def test_lt(self): + # EntryTS type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < \ + rtshell.ilog.EntryTS(sec=2, nsec=2), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < \ + rtshell.ilog.EntryTS(sec=2, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < \ + rtshell.ilog.EntryTS(sec=1, nsec=2), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) < \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) < \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) < \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + # Float type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < 2.000000002, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < 2.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < 1.000000002, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) < 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) < 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) < 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) < 1.000000001, + False) + + def test_le(self): + # EntryTS type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= \ + rtshell.ilog.EntryTS(sec=2, nsec=2), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= \ + rtshell.ilog.EntryTS(sec=2, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= \ + rtshell.ilog.EntryTS(sec=1, nsec=2), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) <= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) <= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) <= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + # Float type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= 2.000000002, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= 2.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= 1.000000002, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) <= 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) <= 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) <= 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) <= 1.000000001, + False) + + def test_eq(self): + # EntryTS type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == \ + rtshell.ilog.EntryTS(sec=2, nsec=2), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == \ + rtshell.ilog.EntryTS(sec=2, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == \ + rtshell.ilog.EntryTS(sec=1, nsec=2), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) == \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) == \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) == \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + # Float type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == 2.000000002, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == 2.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == 1.000000002, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) == 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) == 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) == 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) == 1.000000001, + False) + + def test_ne(self): + # EntryTS type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != \ + rtshell.ilog.EntryTS(sec=2, nsec=2), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != \ + rtshell.ilog.EntryTS(sec=2, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != \ + rtshell.ilog.EntryTS(sec=1, nsec=2), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) != \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) != \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) != \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + # Float type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != 2.000000002, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != 2.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != 1.000000002, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) != 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) != 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) != 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) != 1.000000001, True) + + def test_gt(self): + # EntryTS type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > \ + rtshell.ilog.EntryTS(sec=2, nsec=2), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > \ + rtshell.ilog.EntryTS(sec=2, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > \ + rtshell.ilog.EntryTS(sec=1, nsec=2), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > \ + rtshell.ilog.EntryTS(sec=1, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) > \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) > \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) > \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + # Float type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > 2.000000002, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > 2.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > 1.000000002, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) > 1.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) > 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) > 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) > 1.000000001, + True) + + def test_gt(self): + # EntryTS type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= \ + rtshell.ilog.EntryTS(sec=2, nsec=2), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= \ + rtshell.ilog.EntryTS(sec=2, nsec=1), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= \ + rtshell.ilog.EntryTS(sec=1, nsec=2), False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) >= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) >= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) >= \ + rtshell.ilog.EntryTS(sec=1, nsec=1), True) + # Float type + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= 2.000000002, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= 2.000000001, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= 1.000000002, + False) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=1) >= 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=1, nsec=2) >= 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=1) >= 1.000000001, + True) + self.assertEqual(rtshell.ilog.EntryTS(sec=2, nsec=2) >= 1.000000001, + True) + + def test_construction(self): + ts = rtshell.ilog.EntryTS(sec=1, nsec=2) + self.assertEqual(ts.sec, 1) + self.assertEqual(ts.nsec, 2) + ts = rtshell.ilog.EntryTS(time=1.000000002) + self.assertEqual(ts.sec, 1) + self.assertEqual(ts.nsec, 2) + + def test_to_float(self): + ts = rtshell.ilog.EntryTS(sec=1, nsec=0) + self.assertEqual(ts.float, 1.0) + ts = rtshell.ilog.EntryTS(sec=1, nsec=2) + self.assertEqual(ts.float, 1.000000002) + ts = rtshell.ilog.EntryTS(sec=0, nsec=200) + self.assertEqual(ts.float, 0.0000002) + + +def write_suite(): + return unittest.TestLoader().loadTestsFromTestCase(WriteTests) + + +def read_suite(): + return unittest.TestLoader().loadTestsFromTestCase(ReadTests) + + +def other_suite(): + return unittest.TestLoader().loadTestsFromTestCase(OtherTests) + + +def suite(): + return unittest.TestSuite([write_suite(), read_suite(), other_suite()]) + + +if __name__ == '__main__': + unittest.main() + diff --git a/test/mp1_comp b/test/mp1_comp new file mode 100755 index 0000000..c44782d --- /dev/null +++ b/test/mp1_comp @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Component with multiple ports for tests. + +''' + + +import OpenRTM_aist +import os +import os.path +import RTC +import sys + + +class MPComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + + def onInitialize(self): + self._in_data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._inport = OpenRTM_aist.InPort('in', self._in_data) + self.addInPort('in', self._inport) + self._out_data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._outport = OpenRTM_aist.OutPort('out', self._out_data) + self.addOutPort('out', self._outport) + return RTC.RTC_OK + + def onExecute(self, ec_id): + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'MP', + 'type_name', 'MP', + 'description', 'Standard component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + 'conf.default.param', '0', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, MPComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('MP') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/output.rtlog b/test/output.rtlog new file mode 100644 index 0000000000000000000000000000000000000000..1841bd3a5a273ee88a78feebb6d1c1423da00997 GIT binary patch literal 1446 zcmchXKX21O7{(p@^2e7n4NxdzLh529Qb0(bSpCk-6DEF z2BUe7NY;;f^cYYB5fmr%4P=}9a@KRbA%&c(b=h)$sp>1eXOT!o?L!O&DQJ!XTLd|r zdQhwnim#f=S2ZftwGXYmw3~MAyZ`B#=vHGDnRVDz_j6dI?p=UIb?xlOowWNq3t8)O zka7(2V<<@PLhU$9jM3Wk-DxaXwU(Jlt?76~)?S__ir%-7=)*G6P zhWuMrBl8z)|D^4$(|)?YyJ1>Mu4sSi5_o~T%GbZlrR%sYb7#Z2`W*Mvki-jIxcjJiYAkTkm2oegGa234IooJ-(H!?2$vZ*e{sOC5wyXdE literal 0 HcmV?d00001 diff --git a/test/output_comp b/test/output_comp new file mode 100755 index 0000000..a5654e1 --- /dev/null +++ b/test/output_comp @@ -0,0 +1,78 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Simple data-producing component for tests. + +''' + + +import OpenRTM_aist +import RTC +import sys + + +class OutputComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + + def onInitialize(self): + self._data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._outport = OpenRTM_aist.OutPort('out', self._data) + self.addOutPort('out', self._outport) + self._count = 0 + return RTC.RTC_OK + + def onExecute(self, ec_id): + self._data.data = self._count + self._outport.write() + self._count += 1 + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'Output', + 'type_name', 'Output', + 'description', 'Standard component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'Test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, OutputComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Output') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/output_noport_comp b/test/output_noport_comp new file mode 100755 index 0000000..9df9069 --- /dev/null +++ b/test/output_noport_comp @@ -0,0 +1,68 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Simple data-producing component for tests. + +''' + + +import OpenRTM_aist +import RTC +import sys + + +class OutputComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + + def onInitialize(self): + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'Output', + 'type_name', 'Output', + 'description', 'Standard component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'Test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, OutputComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Output') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/rtc.conf b/test/rtc.conf new file mode 100644 index 0000000..b246f18 --- /dev/null +++ b/test/rtc.conf @@ -0,0 +1,13 @@ +corba.nameservers: localhost +naming.formats: local.host_cxt/%n.rtc +logger.enable: NO +test.Std.config_file: ./test/std.conf +manager.naming_formats: local.host_cxt/%n.mgr +exec_cxt.periodic.rate: 1000.0 + + +## If you want to try to run Composite component, uncomment the following lines. +# manager.modules.load_path: ./.libs/ +# manager.modules.preload: Controller.so, Motor.so, Sensor.so +# manager.components.precreate: Controller, Motor, Sensor, PeriodicECSharedComposite +# composite.PeriodicECShared.PeriodicECSharedComposite0.config_file: composite.conf diff --git a/test/rtsystem.xml b/test/rtsystem.xml new file mode 100644 index 0000000..4fb3f3e --- /dev/null +++ b/test/rtsystem.xml @@ -0,0 +1,112 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/std.conf b/test/std.conf new file mode 100644 index 0000000..bf572c1 --- /dev/null +++ b/test/std.conf @@ -0,0 +1,10 @@ +configuration.active_config: default + +conf.default.param: 0 + +conf.set1.param: 1 + +conf.set2.param: 2 + +conf.__hidden__.param: 3 + diff --git a/test/std_comp b/test/std_comp new file mode 100755 index 0000000..55dce94 --- /dev/null +++ b/test/std_comp @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Simple output component for tests. + +''' + + +import OpenRTM_aist +import os +import os.path +import RTC +import sys + + +class StdComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + self._param = [0] + self._df = './test/std_rcvd' + + def onInitialize(self): + self._data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._inport = OpenRTM_aist.InPort('in', self._data) + self.addInPort('in', self._inport) + self.bindParameter('param', self._param, "0") + if os.path.exists(self._df): + os.remove(self._df) + return RTC.RTC_OK + + def onExecute(self, ec_id): + if self._inport.isNew(): + d = self._inport.read().data + with open(self._df, 'a+') as f: + f.write('{0}\n'.format(d)) + print d + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'Std', + 'type_name', 'Std', + 'description', 'Standard component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + 'conf.default.param', '0', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, StdComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Std') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() + diff --git a/test/sys.dot b/test/sys.dot new file mode 100644 index 0000000..fab93b7 --- /dev/null +++ b/test/sys.dot @@ -0,0 +1,7 @@ +digraph rtsprofile { + rankdir=LR; + node [shape=Mrecord]; + Std0 [label="{{}|Std0|{in}}"]; + Output0 [label="{{out}|Output0|{}}"]; + Output0:out -> Std0:in; +} diff --git a/test/sys.rtsys b/test/sys.rtsys new file mode 100644 index 0000000..0094f86 --- /dev/null +++ b/test/sys.rtsys @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test.idl b/test/test.idl new file mode 100644 index 0000000..c870499 --- /dev/null +++ b/test/test.idl @@ -0,0 +1,8 @@ +module MyData { + struct Bleg + { + unsigned long val1; + unsigned long val2; + }; +}; + diff --git a/test/test_cmds.py b/test/test_cmds.py new file mode 100755 index 0000000..aa4c72e --- /dev/null +++ b/test/test_cmds.py @@ -0,0 +1,3483 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Tests for the commands. + +''' + + +import os +import os.path +import re +import rtctree +import rtctree.tree +import rtsprofile.rts_profile +import subprocess +import sys +import tempfile +import time +import unittest + + +COMP_LIB_PATH='/usr/local/share/openrtm-1.1/example/rtcs' + + +class RTCLaunchFailedError(Exception): + pass + + +def load_file(fn): + with open(fn, 'r') as f: + return f.read() + +def call_process(args): + p = subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + output = p.communicate() + output = (output[0].strip(), output[1].strip()) + return_code = p.returncode + return output[0], output[1], return_code + + +def start_process(args): + return subprocess.Popen(args, stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + + +def find_omninames(): + # If on Windows, ... + # Else use ps + procs, stderr, ret_code = call_process(['ps', '-e']) + for p in procs.split('\n'): + if 'omniNames' in p: + return p.split()[0] + return None + + +def launch_comp(name): + p = subprocess.Popen([os.path.join('./test', name), + '-f', './test/rtc.conf'], stdout=subprocess.PIPE) + p.poll() + if p.returncode is not None: + raise RTCLaunchFailedError + return (p, name) + + +def stop_comp(comp): + comp[0].terminate() + comp[0].wait() + call_process(['killall', comp[1]]) + + +def start_ns(): + # Check if omniNames is running + pid = find_omninames() + if pid: + # Kill the name server to get a clean one for the test + call_process(['killall', 'omniNames']) + # Start omniNames and return the PID + return start_process('rtm-naming') + + +def stop_ns(p): + call_process(['killall', 'omniNames']) + + +def wait_for_comp(comp, state='Inactive', tries=40, res=0.01): + while tries > 0: + stdout, stderr, ret = call_process(['./rtls', '-l', + os.path.join('/localhost/local.host_cxt', comp)]) + if stdout != '': + if stdout.split()[0] == state: + return + tries -= 1 + time.sleep(res) + raise RTCLaunchFailedError + + +def make_zombie(comp='zombie_comp'): + c = launch_comp(comp) + wait_for_comp('Zombie0.rtc') + c[0].kill() + c[0].wait() + call_process(['killall', c[1]]) + + +def clean_zombies(): + call_process(['./rtdel', '-z']) + + +def launch_manager(tries=40, res=0.01): + p = start_process(['rtcd', '-d', '-f', './test/rtc.conf']) + while tries > 0: + stdout, stderr, ret = call_process(['./rtls', + '/localhost/local.host_cxt/manager.mgr']) + if stdout == '' and stderr == '': + return p + tries -= 1 + time.sleep(res) + raise RTCLaunchFailedError + + +def stop_manager(mgr): + mgr.terminate() + mgr.wait() + call_process(['killall', 'rtcd']) + + +def add_obj_strs(args, obj1=None, obj2=None): + if obj1 is not None: + args.append('/localhost/local.host_cxt/{0}'.format(obj1)) + if obj2 is not None: + args.append('/localhost/local.host_cxt/{0}'.format(obj2)) + return args + + +def test_notacomp(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: Not a component: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj1)) + tester.assertEqual(ret, 1) + + +def test_notacomp2(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: Not a component: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj2)) + tester.assertEqual(ret, 1) + + +def test_noobject(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: No such object: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj1)) + tester.assertEqual(ret, 1) + + +def test_noobject2(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: No such object: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj2)) + tester.assertEqual(ret, 1) + + +def test_zombie(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: Zombie object: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj1)) + tester.assertEqual(ret, 1) + + +def test_portnotfound(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: Port not found: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj1)) + tester.assertEqual(ret, 1) + + +def test_port2notfound(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: Port not found: /localhost/local.host_cxt/{1}'.format( + os.path.basename(cmd), obj2)) + tester.assertEqual(ret, 1) + + +def test_sourceportnotfound(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: No source port specified.'.format(os.path.basename(cmd))) + tester.assertEqual(ret, 1) + + +def test_destportnotfound(tester, cmd, obj1=None, obj2=None, extra_opts=[]): + stdout, stderr, ret = call_process(add_obj_strs(['./{0}'.format(cmd)], + obj1=obj1, obj2=obj2) + extra_opts) + tester.assertEqual(stdout, '') + tester.assertEqual(stderr, + '{0}: No destination port specified.'.format(os.path.basename(cmd))) + tester.assertEqual(ret, 1) + + +class rtactTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = launch_comp('output_comp') + make_zombie() + self._mgr = launch_manager() + wait_for_comp('Std0.rtc') + wait_for_comp('Output0.rtc') + + def tearDown(self): + stop_comp(self._std) + stop_comp(self._output) + clean_zombies() + stop_manager(self._mgr) + stop_ns(self._ns) + + def test_success(self): + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + + def test_context(self): + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, + 'rtact: Not a component: /localhost/local.host_cxt') + self.assertEqual(ret, 1) + + def test_manager(self): + test_notacomp(self, './rtact', obj1='manager.mgr') + + def test_port(self): + test_notacomp(self, './rtact', obj1='Std0.rtc:in') + + def test_trailing_slash(self): + test_notacomp(self, './rtact', obj1='Std0.rtc/') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + + def test_no_object(self): + test_noobject(self, './rtact', obj1='NotAComp0.rtc') + + def test_zombie_object(self): + test_zombie(self, './rtact', obj1='Zombie0.rtc') + + def test_no_arg(self): + stdout, stderr, ret = call_process('./rtact') + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtact: No components specified.') + self.assertEqual(ret, 1) + + def test_multiple(self): + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Std0.rtc', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + + def test_multiple_one_port(self): + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Std0.rtc', + '/localhost/local.host_cxt/Output0.rtc:in']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtact: Not a component: ' + '/localhost/local.host_cxt/Output0.rtc:in') + self.assertEqual(ret, 1) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + +def rtact_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtactTests) + + +class rtcatTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + make_zombie() + self._mgr = launch_manager() + wait_for_comp('Std0.rtc') + + def tearDown(self): + stop_comp(self._std) + clean_zombies() + stop_manager(self._mgr) + stop_ns(self._ns) + + def test_context(self): + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtcat: No such object: ' + '/localhost/local.host_cxt') + self.assertEqual(ret, 1) + + def test_no_object(self): + test_noobject(self, './rtcat', obj1='NotAComp0.rtc') + + def test_no_object_port(self): + test_noobject(self, './rtcat', obj1='NotAComp0.rtc:notaport') + + def test_no_arg(self): + stdout, stderr, ret = call_process('./rtcat') + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtcat: Cannot cat a directory.') + self.assertEqual(ret, 1) + + def test_rtc(self): + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assert_(stdout.startswith('Std0.rtc')) + self.assert_('Inactive' in stdout) + self.assert_('Category' in stdout) + self.assert_('Execution Context' in stdout) + self.assert_('DataInPort: in' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_manager(self): + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + self.assert_(stdout.startswith('Name: manager')) + self.assert_('Modules:' in stdout) + self.assert_('Loaded modules:' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_port(self): + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assertEqual(stdout, '+DataInPort: in') + stdout, stderr, ret = call_process(['./rtcat', '-l', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_(stdout.startswith('-DataInPort: in')) + self.assert_('dataport.data_type' in stdout) + self.assert_('TimedLong' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_port_not_rtc(self): + test_notacomp(self, './rtcat', obj1='manager.mgr:in') + + def test_port_trailing_slash(self): + test_noobject(self, './rtcat', obj1='Std0.rtc:in/') + + def test_bad_port(self): + test_portnotfound(self, './rtcat', obj1='Std0.rtc:out') + + def test_rtc_trailing_slash(self): + test_noobject(self, './rtcat', obj1='Std0.rtc/') + + def test_zombie_object(self): + test_zombie(self, './rtcat', obj1='Zombie0.rtc') + + +def rtcat_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtcatTests) + + +class rtcheckTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = launch_comp('output_comp') + wait_for_comp('Std0.rtc') + wait_for_comp('Output0.rtc') + + def tearDown(self): + stop_comp(self._std) + stop_comp(self._output) + stop_ns(self._ns) + + def test_noprobs(self): + call_process(['./rtresurrect', './test/sys.rtsys']) + call_process(['./rtstart', './test/sys.rtsys']) + stdout, stderr, ret = call_process(['./rtcheck', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_not_activated(self): + call_process(['./rtresurrect', './test/sys.rtsys']) + call_process(['./rtstart', './test/sys.rtsys']) + call_process(['./rtdeact', '/localhost/local.host_cxt/Std0.rtc']) + wait_for_comp('Std0.rtc', state='Inactive') + stdout, stderr, ret = call_process(['./rtcheck', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, + 'Component /localhost/local.host_cxt/Std0.rtc '\ + 'is in incorrect state Inactive') + self.assertEqual(ret, 1) + + def test_not_connected(self): + call_process(['./rtresurrect', './test/sys.rtsys']) + call_process(['./rtstart', './test/sys.rtsys']) + call_process(['./rtdis', '/localhost/local.host_cxt/Std0.rtc']) + stdout, stderr, ret = call_process(['./rtcheck', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'No connection between '\ + '/localhost/local.host_cxt/Output0.rtc:out and '\ + '/localhost/local.host_cxt/Std0.rtc:in') + self.assertEqual(ret, 1) + + +def rtcheck_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtcheckTests) + + +class rtcompTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._mp = launch_comp('mp1_comp') + self._mgr = launch_manager() + wait_for_comp('Std0.rtc') + wait_for_comp('MP0.rtc') + + def tearDown(self): + stop_comp(self._std) + stop_comp(self._mp) + stop_manager(self._mgr) + stop_ns(self._ns) + + def test_create(self): + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr',]) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('CompositeRTC.rtc') + self._assert_comp_is_composite('CompositeRTC.rtc') + + def test_create_with_name(self): + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent',]) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_is_composite('MrComponent.rtc') + + def test_create_with_members(self): + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + + def test_create_with_members_and_one_port(self): + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_exports_port('MrComponent.rtc', 'MP0.in') + + def test_create_with_members_and_ports(self): + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in,out']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_exports_port('MrComponent.rtc', 'MP0.in') + self._assert_comp_exports_port('MrComponent.rtc', 'MP0.out') + + def test_add_more_members(self): + call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in,out']) + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/MrComponent.rtc', + '-a', '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_has_member('MrComponent.rtc', 'Std0') + + def test_add_more_ports(self): + call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in']) + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/MrComponent.rtc', + '-a', '/localhost/local.host_cxt/MP0.rtc:out']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_exports_port('MrComponent.rtc', 'MP0.in') + self._assert_comp_exports_port('MrComponent.rtc', 'MP0.out') + + def test_remove_ports(self): + call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in,out']) + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/MrComponent.rtc', + '-r', '/localhost/local.host_cxt/MP0.rtc:out']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_exports_port('MrComponent.rtc', 'MP0.in') + self._assert_comp_not_exports_port('MrComponent.rtc', 'MP0.out') + + def test_remove_all_ports(self): + call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in,out']) + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/MrComponent.rtc', + '-r', '/localhost/local.host_cxt/MP0.rtc:in,out']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_not_exports_port('MrComponent.rtc', 'MP0.in') + self._assert_comp_not_exports_port('MrComponent.rtc', 'MP0.out') + + def test_remove_members(self): + call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in,out', + '-a', '/localhost/local.host_cxt/Std0.rtc']) + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/MrComponent.rtc', + '-r', '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_not_has_member('MrComponent.rtc', 'Std0') + + def test_remove_all_members(self): + call_process(['./rtcomp', + '/localhost/local.host_cxt/manager.mgr:MrComponent', + '-a', '/localhost/local.host_cxt/MP0.rtc:in,out', + '-a', '/localhost/local.host_cxt/Std0.rtc']) + stdout, stderr, ret = call_process(['./rtcomp', + '/localhost/local.host_cxt/MrComponent.rtc', + '-r', '/localhost/local.host_cxt/MP0.rtc', + '-r', '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self._assert_comp_exists('MrComponent.rtc') + self._assert_comp_not_has_member('MrComponent.rtc', 'MP0') + self._assert_comp_not_has_member('MrComponent.rtc', 'Std0') + + def _assert_comp_exists(self, name): + wait_for_comp(name) + stdout, stderr, ret = call_process(['./rtls', + '/localhost/local.host_cxt/{0}'.format(name)]) + self.assertEqual(stdout, name) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def _assert_comp_is_composite(self, comp): + p = ['/', 'localhost', 'local.host_cxt', comp] + t = rtctree.tree.RTCTree(paths=p) + c = t.get_node(p) + self.assertNotEqual(c, None) + self.assert_(c.is_composite) + + def _assert_comp_has_member(self, comp, member): + p = ['/', 'localhost', 'local.host_cxt', comp] + t = rtctree.tree.RTCTree(paths=p) + c = t.get_node(p) + self.assertNotEqual(c, None) + has_member = False + for m in c.members[c.organisations[0].org_id]: + if m.get_component_profile().instance_name == member: + has_member = True + break + self.assert_(has_member) + + def _assert_comp_not_has_member(self, comp, member): + p = ['/', 'localhost', 'local.host_cxt', comp] + t = rtctree.tree.RTCTree(paths=p) + c = t.get_node(p) + self.assertNotEqual(c, None) + has_member = False + for m in c.members[c.organisations[0].org_id]: + if m.get_component_profile().instance_name == member: + has_member = True + break + self.assert_(not has_member) + + def _assert_comp_exports_port(self, comp, port): + p = ['/', 'localhost', 'local.host_cxt', comp] + t = rtctree.tree.RTCTree(paths=p) + c = t.get_node(p) + self.assertNotEqual(c, None) + ports = c.conf_sets['default'].data['exported_ports'].split(',') + self.assert_(port in ports) + + def _assert_comp_not_exports_port(self, comp, port): + p = ['/', 'localhost', 'local.host_cxt', comp] + t = rtctree.tree.RTCTree(paths=p) + c = t.get_node(p) + self.assertNotEqual(c, None) + ports = c.conf_sets['default'].data['exported_ports'].split(',') + self.assert_(port not in ports) + + +def rtcomp_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtcompTests) + + +class rtconTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = launch_comp('output_comp') + self._err = launch_comp('err_comp') + self._mgr = launch_manager() + wait_for_comp('Std0.rtc') + wait_for_comp('Output0.rtc') + wait_for_comp('Err0.rtc') + + def tearDown(self): + stop_comp(self._std) + stop_comp(self._output) + stop_comp(self._err) + stop_manager(self._mgr) + stop_ns(self._ns) + + def test_connect(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-l', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_('/localhost/local.host_cxt/Output0.rtc:out' in stdout) + stdout, stderr, ret = call_process(['./rtcat', '-l', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assert_('/localhost/local.host_cxt/Std0.rtc:in' in stdout) + + def test_set_props(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out', + '-p', 'dataport.subscription_type=new']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-ll', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_('dataport.subscription_type new' in stdout) + stdout, stderr, ret = call_process(['./rtcat', '-ll', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assert_('dataport.subscription_type new' in stdout) + + def test_bad_prop(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out', + '-p', 'dataport.subscription_type']) + self.assertEqual(stdout, '') + self.assert_( + 'Bad property format: dataport.subscription_type' in stderr) + self.assertEqual(ret, 2) + stdout, stderr, ret = call_process(['./rtcat', '-l', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_('Connected to: /localhost/local.host_cxt/Output0.rtc:out'\ + not in stdout) + + def test_set_name(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out', + '-n', 'test_conn']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-ll', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_('test_conn' in stdout) + stdout, stderr, ret = call_process(['./rtcat', '-ll', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assert_('test_conn' in stdout) + + def test_set_id(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out', + '-i', 'conn_id']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-ll', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_('conn_id' in stdout) + stdout, stderr, ret = call_process(['./rtcat', '-ll', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assert_('conn_id' in stdout) + + def test_no_source_port(self): + test_sourceportnotfound(self, './rtcon', obj1='Std0.rtc', + obj2='Output0.rtc:out') + test_sourceportnotfound(self, './rtcon', obj1='Output0.rtc', + obj2='Std0.rtc:in') + + def test_not_enough_targets(self): + stdout, stderr, ret = call_process(['./rtcon', 'Std0.rtc:in']) + self.assertEqual(stdout, '') + self.assert_('Usage:' in stderr) + self.assertEqual(ret, 1) + + def test_too_many_targets(self): + stdout, stderr, ret = call_process(['./rtcon', 'Std0.rtc:in', + 'Output0.rtc:out', 'Err0.rtc:in']) + self.assertEqual(stdout, '') + self.assert_('Usage:' in stderr) + self.assertEqual(ret, 1) + + def test_no_dest_port(self): + test_destportnotfound(self, './rtcon', obj1='Std0.rtc:in', + obj2='Output0.rtc') + test_destportnotfound(self, './rtcon', obj1='Output0.rtc:out', + obj2='Std0.rtc') + + def test_bad_source_port(self): + test_portnotfound(self, './rtcon', obj1='Std0.rtc:noport', + obj2='Output0.rtc:out') + test_portnotfound(self, './rtcon', obj1='Output0.rtc:noport', + obj2='Std0.rtc:in') + + def test_bad_source_rtc(self): + test_noobject(self, './rtcon', obj1='NotAComp0.rtc:in', + obj2='Output0.rtc:out') + test_noobject(self, './rtcon', + obj1='NotAComp0.rtc:out', + obj2='Std0.rtc:in') + + def test_bad_dest_port(self): + test_port2notfound(self, './rtcon', obj1='Std0.rtc:in', + obj2='Output0.rtc:noport') + test_port2notfound(self, './rtcon', obj1='Output0.rtc:out', + obj2='Std0.rtc:noport') + + def test_bad_dest_rtc(self): + test_noobject2(self, './rtcon', obj1='Std0.rtc:in', + obj2='NotAComp0.rtc:out') + test_noobject2(self, './rtcon', obj1='Output0.rtc:out', + obj2='NotAComp0.rtc:in') + + def test_bad_polarity(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Err0.rtc:in']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtcon: Wrong port type.') + self.assertEqual(ret, 1) + + def test_context(self): + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt:port', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, + 'rtcon: Not a component: /localhost/local.host_cxt:port') + self.assertEqual(ret, 1) + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Output0.rtc:out', + '/localhost/local.host_cxt:port']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, + 'rtcon: Not a component: /localhost/local.host_cxt:port') + self.assertEqual(ret, 1) + + def test_manager(self): + test_sourceportnotfound(self, './rtcon', obj1='manager.mgr', + obj2='Output0.rtc:out') + test_destportnotfound(self, './rtcon', obj1='Std0.rtc:in', obj2='manager.mgr') + test_notacomp(self, './rtcon', obj1='manager.mgr:port', + obj2='Output0.rtc:out') + test_notacomp2(self, './rtcon', obj1='Std0.rtc:in', + obj2='manager.mgr:port') + + +def rtcon_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtconTests) + + +class rtconfTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + make_zombie() + wait_for_comp('Std0.rtc') + + def tearDown(self): + stop_comp(self._std) + clean_zombies() + stop_ns(self._ns) + + def test_list(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'list']) + self.assert_('+default*' in stdout) + self.assert_('+set1' in stdout) + self.assert_('+set2' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_list_long(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'list', '-l']) + self.assertEqual(stdout, + '-default*\n param 0\n'\ + '-set1\n param 1\n'\ + '-set2\n param 2') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_list_hidden_set_error(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '/localhost/local.host_cxt/Std0.rtc', 'list']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: __hidden__') + self.assertEqual(ret, 1) + + def test_list_hidden_set_ok(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '-a', '/localhost/local.host_cxt/Std0.rtc', 'list']) + self.assertEqual(stdout, '+__hidden__') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_list_bad_set(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', 'noset', + '/localhost/local.host_cxt/Std0.rtc', 'list']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: noset') + self.assertEqual(ret, 1) + + def test_set_default(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'set', 'param', '42']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '42') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set1', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '1') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set2', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '2') + + def test_set_other(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set1', + '/localhost/local.host_cxt/Std0.rtc', 'set', 'param', '42']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtconf', '-s', 'default', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '0') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set1', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '42') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set2', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '2') + + def test_set_hidden_error(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '/localhost/local.host_cxt/Std0.rtc', 'set', 'param', '42']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: __hidden__') + self.assertEqual(ret, 1) + + def test_set_hidden_ok(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '-a', '/localhost/local.host_cxt/Std0.rtc', 'set', 'param', '42']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '-a', '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '42') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'default', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '0') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set1', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '1') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set2', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '2') + + def test_get_default(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '0') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_get_other(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set2', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '2') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_get_bad_set(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', 'noset', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: noset') + self.assertEqual(ret, 1) + + def test_get_bad_param(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'noparam']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, + 'rtconf: No such configuration parameter: noparam') + self.assertEqual(ret, 1) + + def test_get_hidden_error(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: __hidden__') + self.assertEqual(ret, 1) + + def test_get_hidden_ok(self): + stdout, stderr, ret = call_process(['./rtconf', '-s', '__hidden__', + '-a', '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '3') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_act(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'act', '-s', 'set1']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'list']) + self.assertEqual(stdout, '+default\n+set1*\n+set2') + + def test_act_bad_set(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'act', '-s', 'noset']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: noset') + self.assertEqual(ret, 1) + + def test_act_hidden_error(self): + stdout, stderr, ret = call_process(['./rtconf', + '/localhost/local.host_cxt/Std0.rtc', 'act', '-s', '__hidden__']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtconf: No such configuration set: __hidden__') + self.assertEqual(ret, 1) + + def test_act_hidden_ok(self): + stdout, stderr, ret = call_process(['./rtconf', '-a', + '/localhost/local.host_cxt/Std0.rtc', 'act', '-s', '__hidden__']) + self.assertEqual(stdout, '') + self.assert_('SDOPackage.InternalError' in stderr) + self.assertEqual(ret, 1) + + def test_context(self): + test_noobject(self, './rtconf', obj1='') + + def test_manager(self): + test_noobject(self, './rtconf', obj1='manager.rtc', + extra_opts=['list']) + + def test_port(self): + test_notacomp(self, './rtconf', obj1='Std0.rtc:in') + + def test_trailing_slash(self): + test_noobject(self, './rtconf', obj1='Std0.rtc/') + + def test_bad_comp(self): + test_noobject(self, './rtconf', obj1='NotAComp0.rtc') + + def test_zombie(self): + test_zombie(self, './rtconf', obj1='Zombie0.rtc') + + +def rtconf_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtconfTests) + + +class rtcryoTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = launch_comp('output_comp') + wait_for_comp('Std0.rtc') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def tearDown(self): + stop_comp(self._std) + stop_comp(self._output) + stop_ns(self._ns) + + def _check_rtsys_xml(self, rtsys): + self.assert_(rtsys.startswith(' 0) + self.assert_(self._log_start(stdout) > now) + + def _test_record_limit_index(self): + logger = start_process(['./rtlog', + '/localhost/local.host_cxt/Output0.rtc:out', + '-f', './test/test.rtlog', '-i', '-e', '5']) + call_process(['./rtact', '/localhost/local.host_cxt/Output0.rtc']) + wait_for_comp('Output0.rtc', 'Active') + stdout, stderr = logger.communicate() + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Recording 5 entries.\n') + self.assertEqual(logger.returncode, 0) + stdout, stderr, ret = call_process(['./rtlog', '-d', '-f', + './test/test.rtlog']) + self.assert_(self._num_recorded(stdout) == 5) + + def _test_record_limit_time(self): + limit = time.time() + 3 + logger = start_process(['./rtlog', + '/localhost/local.host_cxt/Output0.rtc:out', + '-f', './test/test.rtlog', '-e', '{0}'.format(limit)]) + call_process(['./rtact', '/localhost/local.host_cxt/Output0.rtc']) + wait_for_comp('Output0.rtc', 'Active') + stdout, stderr = logger.communicate() + self.assertEqual(stdout, '') + m = re.match(r'Recording until \d{4}-\d{2}-\d{2} ' + '\d{2}:\d{2}:\d{2} \((\d+.\d+)\)\.', stderr) + self.assert_(m is not None) + self.assert_(abs(float(m.group(1)) - limit) < 0.01) + self.assertEqual(logger.returncode, 0) + stdout, stderr, ret = call_process(['./rtlog', '-d', '-f', + './test/test.rtlog']) + self.assert_(self._num_recorded(stdout) > 0) + + def _test_record_timeout(self): + call_process(['./rtact', '/localhost/local.host_cxt/Output0.rtc']) + wait_for_comp('Output0.rtc', 'Active') + stdout, stderr, ret = call_process(['./rtlog', + '/localhost/local.host_cxt/Output0.rtc:out', + '-f', './test/test.rtlog', '-t', '3']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Recording for 3.0s.') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtlog', '-d', '-f', + './test/test.rtlog']) + self.assert_(self._num_recorded(stdout) > 0) + log_length = self._log_end(stdout) - self._log_start(stdout) + self.assert_(log_length < 3.5) + self.assert_(log_length > 2.5) + + def _test_display_info(self): + stdout, stderr, ret = call_process(['./rtlog', '-d', '-f', + './test/output.rtlog']) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self.assert_('Size: 1.41KiB (1446B)' in stdout) + self.assert_('Start time: 2011-02-08 18:22:42 (1297156962.58)' in + stdout) + self.assert_('First entry time: 2011-02-08 18:22:43 ' + '(1297156963.450684160)' in stdout) + self.assert_('End time: 2011-02-08 18:22:47 ' + '(1297156967.592355840)' in stdout) + self.assert_('Number of entries: 5' in stdout) + self.assert_('Channel 1' in stdout) + self.assert_('Name: nums' in stdout) + self.assert_('Data type: TimedLong (RTC.TimedLong)' in stdout) + self.assert_('/localhost/odyssey.host_cxt/ConsoleIn0.rtc:out.nums' in + stdout) + + def test_playback_usermod(self): + stdout, stderr, ret = call_process(['./rtlog', + '/localhost/local.host_cxt/C20.rtc:input.nums', + '-f', './test/c1.rtlog', '-p', '--path=./test', '-m', 'MyData']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtlog: End of log reached.') + self.assertEqual(ret, 0) + time.sleep(0.5) + self.assertEqual(self._get_comp_output('c2'), + 'MyData.Bleg(val1=1L, val2=0L)\n' + 'MyData.Bleg(val1=1L, val2=1L)\n' + 'MyData.Bleg(val1=1L, val2=2L)\n' + 'MyData.Bleg(val1=1L, val2=3L)\n' + 'MyData.Bleg(val1=1L, val2=4L)\n') + + def _test_record_usermod(self): + call_process(['./rtact', '/localhost/local.host_cxt/C10.rtc']) + wait_for_comp('C10.rtc', 'Active') + stdout, stderr, ret = call_process(['./rtlog', + '/localhost/local.host_cxt/C10.rtc:output', + '-f', './test/test.rtlog', '-i', '-e', '5', '--path=./test', '-m', + 'MyData']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Recording 5 entries.') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtlog', '-d', '-f', + './test/test.rtlog', '--path=./test', '-m', 'MyData']) + self.assert_(self._num_recorded(stdout) == 5) + + def _test_record_text(self): + call_process(['./rtact', '/localhost/local.host_cxt/Output0.rtc']) + wait_for_comp('Output0.rtc', 'Active') + stdout, stderr, ret = call_process(['./rtlog', '-l', 'text', + '/localhost/local.host_cxt/Output0.rtc:out', + '-f', './test/test.rtlog', '-i', '-e', '5']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Recording 5 entries.') + self.assertEqual(ret, 0) + self.assert_(re.match(r"\d+.\d+\s+\('input0', " + "RTC\.TimedLong\(tm=RTC\.Time\(sec=0L, nsec=0L\), data=\d+\)\)\n", + load_file('./test/test.rtlog')) is not None) + + +def rtlog_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtlogTests) + + +class rtlsTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = launch_comp('output_comp') + make_zombie() + self._mgr = launch_manager() + wait_for_comp('Std0.rtc') + wait_for_comp('Output0.rtc') + self._load_mgr() + + def tearDown(self): + stop_comp(self._std) + stop_comp(self._output) + clean_zombies() + stop_manager(self._mgr) + stop_ns(self._ns) + + def _load_mgr(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Controller.so'), '-i', + 'ControllerInit', '-c', 'Controller']) + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Sensor.so'), '-i', + 'SensorInit', '-c', 'Sensor']) + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so'), '-i', + 'MotorInit', '-c', 'Motor']) + self.assertEqual(ret, 0) + + def test_ls_nothing(self): + stdout, stderr, ret = call_process(['./rtls']) + self.assertEqual(stdout, 'localhost/') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', '/']) + self.assertEqual(stdout, 'localhost/') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_ns(self): + stdout, stderr, ret = call_process(['./rtls', 'localhost']) + self.assertEqual(stdout, 'local.host_cxt/') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', '/localhost']) + self.assertEqual(stdout, 'local.host_cxt/') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_hc(self): + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt']) + self.assert_('Std0.rtc' in stdout) + self.assert_('Output0.rtc' in stdout) + self.assert_('*Zombie0.rtc' in stdout) + self.assert_('manager.mgr' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', + '/localhost/local.host_cxt']) + self.assert_('Std0.rtc' in stdout) + self.assert_('Output0.rtc' in stdout) + self.assert_('*Zombie0.rtc' in stdout) + self.assert_('manager.mgr' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_mgr_dir(self): + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Motor0.rtc' in stdout) + self.assert_('Controller0.rtc' in stdout) + self.assert_('Sensor0.rtc' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', + '/localhost/local.host_cxt/manager.mgr']) + self.assert_('Motor0.rtc' in stdout) + self.assert_('Controller0.rtc' in stdout) + self.assert_('Sensor0.rtc' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_rtc(self): + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout, 'Std0.rtc') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_zombie(self): + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/Zombie0.rtc']) + self.assertEqual(stdout, '*Zombie0.rtc') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_mgr_obj(self): + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Controller0.rtc' in stdout) + self.assert_('Motor0.rtc' in stdout) + self.assert_('Sensor0.rtc' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_ns_long(self): + stdout, stderr, ret = call_process(['./rtls', '-l', + 'localhost']) + self.assertEqual(stdout, '- - - - - local.host_cxt') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_hc_long(self): + stdout, stderr, ret = call_process(['./rtls', '-l', + 'localhost/local.host_cxt']) + self.assert_('Inactive 1/0 1/0 0/0 0/0 Std0.rtc' in stdout) + self.assert_('Inactive 2/0 1/0 1/0 0/0 Motor0.rtc' in stdout) + self.assert_('- - - - - manager.mgr' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_rtc_long(self): + stdout, stderr, ret = call_process(['./rtls', '-l', + 'localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout, 'Inactive 1/0 1/0 0/0 0/0 Std0.rtc') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_zombie_long(self): + stdout, stderr, ret = call_process(['./rtls', '-l', + 'localhost/local.host_cxt/Zombie0.rtc']) + self.assertEqual(stdout, '- - - - - *Zombie0.rtc') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_recurse(self): + stdout, stderr, ret = call_process(['./rtls', '-R']) + self.assert_('/localhost' in stdout) + self.assert_('/localhost/local.host_cxt' in stdout) + self.assert_('Std0.rtc' in stdout) + self.assert_('Motor0.rtc' in stdout) + self.assert_('/localhost/local.host_cxt/manager.mgr' in stdout) + self.assert_('manager.mgr' in stdout) + self.assert_('*Zombie0.rtc' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_recurse_long(self): + stdout, stderr, ret = call_process(['./rtls', '-lR']) + self.assert_('/localhost' in stdout) + self.assert_('/localhost/local.host_cxt' in stdout) + self.assert_('Inactive 1/0 1/0 0/0 0/0 Std0.rtc' in stdout) + self.assert_('Inactive 2/0 1/0 1/0 0/0 Motor0.rtc' in stdout) + self.assert_('/localhost/local.host_cxt/manager.mgr' in stdout) + self.assert_('- - - - - manager.mgr' in stdout) + self.assert_('- - - - - *Zombie0.rtc' in stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_ls_port(self): + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/Std0.rtc:in']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtls: Cannot list ports.') + self.assertEqual(ret, 1) + + def test_ls_noobject(self): + stdout, stderr, ret = call_process(['./rtls', + '/localhost/local.host_cxt/NotAComp0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtls: No such object: ' + '/localhost/local.host_cxt/NotAComp0.rtc') + self.assertEqual(ret, 1) + + def test_ls_notacomp(self): + stdout, stderr, ret = call_process(['./rtls', + '/localhost/local.host_cxt/Std0.rtc/']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtls: No such object: ' + '/localhost/local.host_cxt/Std0.rtc/') + self.assertEqual(ret, 1) + + +def rtls_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtlsTests) + + +class rtmgrTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._mgr = launch_manager() + wait_for_comp('Std0.rtc') + self._load_mgr() + + def tearDown(self): + stop_comp(self._std) + stop_manager(self._mgr) + stop_ns(self._ns) + + def _load_mgr(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Controller.so') + ':ControllerInit']) + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Sensor.so') + ':SensorInit', + '-c', 'Sensor']) + self.assertEqual(ret, 0) + + def _grab_section(self, stdout, sec, next_sec=''): + self.assert_(sec in stdout) + if not next_sec: + next_sec = '$' + return re.match(r'.*?\n{0}\n(.*?){1}'.format(sec, next_sec), stdout, + re.S).groups()[0] + + def test_load_mod(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') in loaded) + + def test_load_mod_no_init(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so')]) + self.assertEqual(stdout, '') + self.assert_(stderr.endswith('rtmgr: error: No initialisation ' + 'function specified.')) + self.assertEqual(ret, 2) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') not in loaded) + + def test_create_rtc(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Controller0.rtc' in stdout) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/']) + self.assert_('Controller0.rtc' in stdout) + + def test_delete_rtc(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-d', 'Sensor0']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Sensor0.rtc' not in stdout) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/']) + self.assert_('Sensor0.rtc' not in stdout) + + def test_unload_mod(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-u', + os.path.join(COMP_LIB_PATH, 'Controller.so')]) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Controller.so') not in loaded) + + def test_no_cmds(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: No commands specified.') + self.assertEqual(ret, 1) + + def test_multi_cmds(self): + # Load a module, unload it, load it again, create a component from it, + # load another module, create a component from it, delete the first + # component, unload its module. + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit', + '-u', os.path.join(COMP_LIB_PATH, 'Motor.so'), '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit', + '-c', 'Motor', '-l', + os.path.join(COMP_LIB_PATH, 'Controller.so') + ':ControllerInit', + '-c', 'Controller', '-d', 'Motor0', '-u', + os.path.join(COMP_LIB_PATH, 'Motor.so')]) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') not in loaded) + self.assert_(os.path.join(COMP_LIB_PATH, 'Controller.so') in loaded) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Controller0.rtc' in stdout) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/']) + self.assert_('Controller0.rtc' in stdout) + + def test_port(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/manager.mgr:port', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: Not a manager: ' + '/localhost/local.host_cxt/manager.mgr:port') + self.assertEqual(ret, 1) + + def test_rtc(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/Std0.rtc', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: Not a manager: ' + '/localhost/local.host_cxt/Std0.rtc') + self.assertEqual(ret, 1) + + def test_context(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: Not a manager: ' + '/localhost/local.host_cxt') + self.assertEqual(ret, 1) + + def test_ns(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: Not a manager: ' + '/localhost') + self.assertEqual(ret, 1) + + def test_zombie(self): + make_zombie() + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/Zombie0.rtc', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: Zombie object: ' + '/localhost/local.host_cxt/Zombie0.rtc') + self.assertEqual(ret, 1) + clean_zombies() + + def test_noobject(self): + stdout, stderr, ret = call_process(['./rtmgr', + '/localhost/local.host_cxt/NotAComp.rtc', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtmgr: No such object: ' + '/localhost/local.host_cxt/NotAComp.rtc') + self.assertEqual(ret, 1) + + def test_load_mod_corbaloc(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost:2810/manager', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') in loaded) + + def test_create_rtc_corbaloc(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost:2810/manager', '-c', 'Controller']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Controller0.rtc' in stdout) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/']) + self.assert_('Controller0.rtc' in stdout) + + def test_delete_rtc_corbaloc(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost:2810/manager', '-d', 'Sensor0']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/manager.mgr']) + self.assert_('Sensor0.rtc' not in stdout) + stdout, stderr, ret = call_process(['./rtls', + 'localhost/local.host_cxt/']) + self.assert_('Sensor0.rtc' not in stdout) + + def test_unload_mod_corbaloc(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost:2810/manager', '-u', + os.path.join(COMP_LIB_PATH, 'Controller.so')]) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Controller.so') not in loaded) + + def test_load_mod_corbaloc_no_port(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost/manager', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') in loaded) + + def test_load_mod_corbaloc_no_id(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost:2810', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') in loaded) + + def test_load_mod_corbaloc_no_port_or_id(self): + stdout, stderr, ret = call_process(['./rtmgr', + 'corbaloc::localhost', '-l', + os.path.join(COMP_LIB_PATH, 'Motor.so') + ':MotorInit']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/manager.mgr']) + loaded = self._grab_section(stdout, 'Loaded modules:') + self.assert_(os.path.join(COMP_LIB_PATH, 'Motor.so') in loaded) + + +def rtmgr_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtmgrTests) + + +class rtstodotTests(unittest.TestCase): + def test_stdin(self): + sys = load_file('./test/sys.rtsys') + p = subprocess.Popen('./rtstodot', stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + stdout, stderr = p.communicate(sys) + self.assertEqual(stderr, '') + self.assertEqual(p.returncode, 0) + sample = load_file('./test/sys.dot') + self.assertEqual(sample, stdout) + + def test_file(self): + stdout, stderr, ret = call_process(['./rtstodot', './test/sys.rtsys']) + sample = load_file('./test/sys.dot') + self.assertEqual(sample.rstrip(), stdout) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + +def rtstodot_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtstodotests) + + +class rtprintTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._output = launch_comp('output_comp') + self._c1 = launch_comp('c1_comp') + wait_for_comp('Output0.rtc') + wait_for_comp('C10.rtc') + call_process(['./rtact', '/localhost/local.host_cxt/Output0.rtc']) + call_process(['./rtact', '/localhost/local.host_cxt/C10.rtc']) + wait_for_comp('Output0.rtc', 'Active') + wait_for_comp('C10.rtc', 'Active') + + def tearDown(self): + stop_comp(self._output) + stop_comp(self._c1) + stop_ns(self._ns) + + def test_print(self): + p = start_process(['./rtprint', + '/localhost/local.host_cxt/Output0.rtc:out']) + time.sleep(3) + p.terminate() + stdout, stderr = p.communicate() + self.assert_(re.match(r'\[0\.0+\]\s\d+\n', stdout) is not None) + self.assertEqual(stderr, '') + self.assertEqual(p.returncode, -15) + + def test_print_count_limit(self): + stdout, stderr, ret = call_process(['./rtprint', + '/localhost/local.host_cxt/Output0.rtc:out', '-n', '2']) + self.assert_(re.match(r'\[0\.0+\]\s\d+\n\[0\.0+\]\s\d+$', stdout) is not None) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_print_time_limit(self): + stdout, stderr, ret = call_process(['./rtprint', + '/localhost/local.host_cxt/Output0.rtc:out', '-t', '1']) + self.assert_(re.match(r'\[0\.0+\]\s\d+\n', stdout) is not None) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_user_mod(self): + stdout, stderr, ret = call_process(['./rtprint', + '/localhost/local.host_cxt/C10.rtc:output', '-n', '1', + '-p', './test', '-m', 'MyData']) + self.assert_(re.match(r'MyData\.Bleg\(val1=1L, val2=\d+L\)', stdout) is not None) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + + def test_mod_no_path(self): + stdout, stderr, ret = call_process(['./rtprint', + '/localhost/local.host_cxt/C10.rtc:output', '-n', '1', + '-m', 'MyData']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtprint: No module named MyData') + self.assertEqual(ret, 1) + + def test_bad_comp(self): + stdout, stderr, ret = call_process(['./rtprint', + '/localhost/local.host_cxt/NotAComp0.rtc:out', '-n', '2']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtprint: No such object: ' + '/localhost/local.host_cxt/NotAComp0.rtc') + self.assertEqual(ret, 1) + + def test_bad_port(self): + stdout, stderr, ret = call_process(['./rtprint', + '/localhost/local.host_cxt/Output0.rtc:noport', '-n', '2']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtprint: Port not found: ' + '/localhost/local.host_cxt/Output0.rtc:noport') + self.assertEqual(ret, 1) + + +def rtprint_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtprintTests) + + +class rtresetTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._err = launch_comp('err_comp') + make_zombie() + self._mgr = launch_manager() + call_process(['./rtact', '/localhost/local.host_cxt/Err0.rtc']) + wait_for_comp('Err0.rtc', state='Error') + + def tearDown(self): + stop_comp(self._err) + clean_zombies() + stop_manager(self._mgr) + stop_ns(self._ns) + + def test_success(self): + stdout, stderr, ret = call_process(['./rtreset', + '/localhost/local.host_cxt/Err0.rtc']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Err0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + + def test_context(self): + stdout, stderr, ret = call_process(['./rtreset', + '/localhost/local.host_cxt']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, + 'rtreset: Not a component: /localhost/local.host_cxt') + self.assertEqual(ret, 1) + + + def test_manager(self): + test_notacomp(self, './rtreset', obj1='manager.mgr') + + def test_port(self): + test_notacomp(self, './rtreset', obj1='Err0.rtc:in') + + def test_trailing_slash(self): + test_notacomp(self, './rtreset', obj1='Err0.rtc/') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Err0.rtc']) + self.assertEqual(stdout.split()[1], 'Error') + + def test_no_object(self): + test_noobject(self, './rtreset', obj1='NotAComp0.rtc') + + def test_zombie_object(self): + test_zombie(self, './rtreset', obj1='Zombie0.rtc') + + def test_no_arg(self): + stdout, stderr, ret = call_process('./rtreset') + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtreset: No components specified.') + self.assertEqual(ret, 1) + + +def rtreset_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtresetTests) + + +class rtresurrectTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = None + wait_for_comp('Std0.rtc') + + def tearDown(self): + stop_comp(self._std) + if self._output: + stop_comp(self._output) + stop_ns(self._ns) + + def test_noprobs(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set2', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '2') + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-l', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assert_('/localhost/local.host_cxt/Std0.rtc:in' in stdout) + stdout, stderr, ret = call_process(['./rtconf', '-s', 'set2', + '/localhost/local.host_cxt/Std0.rtc', 'get', 'param']) + self.assertEqual(stdout, '42') + + def test_missing_comp(self): + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtresurrect: Required action failed: ' + 'Required component missing: ' + '/localhost/local.host_cxt/Output0.rtc') + self.assertEqual(ret, 1) + + def test_missing_port(self): + self._output = launch_comp('output_noport_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtresurrect: Required action failed: ' + 'Required port not found: out') + self.assertEqual(ret, 1) + + def test_dry_run(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys', '--dry-run']) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self.assert_('Check for required component "RTC:Geoffrey ' + 'Biggs:test:Std:1.0", "Std0" at path ' + '/localhost/local.host_cxt/Std0.rtc (Required)' in stdout) + self.assert_('Check for required component "RTC:Geoffrey ' + 'Biggs:Test:Output:1.0", "Output0" at path ' + '/localhost/local.host_cxt/Output0.rtc (Required)' in stdout) + self.assert_('Check for required port "in" on component at path ' + '/localhost/local.host_cxt/Std0.rtc (Required)' in stdout) + self.assert_('Check for required port "out" on component at path ' + '/localhost/local.host_cxt/Output0.rtc (Required)' in stdout) + self.assert_('Connect /localhost/local.host_cxt/Output0.rtc:out to ' + '/localhost/local.host_cxt/Std0.rtc:in with ID ' + 'connection_id0 and properties' in stdout) + self.assert_('Set parameter "param" in set "set2" on component at ' + 'path /localhost/local.host_cxt/Std0.rtc to "42"' in stdout) + self.assert_('Set configuration set "default" active on component at ' + 'path /localhost/local.host_cxt/Std0.rtc' in stdout) + + def test_existing_con_diff_id(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out']) + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-l', + 'localhost/local.host_cxt/Std0.rtc:in']) + self.assertEqual(stdout.count('+Connected to ' + '/localhost/local.host_cxt/Output0.rtc:out'), 2) + + def test_existing_con_same_id(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out', + '-i', 'connection_id0']) + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtresurrect', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-l', + 'localhost/local.host_cxt/Std0.rtc:in']) + self.assertEqual(stdout.count('+Connected to ' + '/localhost/local.host_cxt/Output0.rtc:out'), 1) + + +def rtresurrect_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtresurrectTests) + + +class rtstartTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = None + wait_for_comp('Std0.rtc') + + def tearDown(self): + stop_comp(self._std) + if self._output: + stop_comp(self._output) + stop_ns(self._ns) + + def test_noprobs(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtstart', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(ret, 0) + self.assert_('Activate /localhost/local.host_cxt/Std0.rtc in ' + 'execution context 0 (Required)' in stderr) + self.assert_('Activate /localhost/local.host_cxt/Output0.rtc in ' + 'execution context 0 (Required)' in stderr) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + + def test_missing_comp(self): + stdout, stderr, ret = call_process(['./rtstart', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'rtstart: Required action failed: ' + 'Required component missing: ' + '/localhost/local.host_cxt/Output0.rtc') + self.assertEqual(ret, 1) + + def test_already_active(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Std0.rtc']) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtstart', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(ret, 0) + self.assert_('Activate /localhost/local.host_cxt/Std0.rtc in ' + 'execution context 0 (Required)' in stderr) + self.assert_('Activate /localhost/local.host_cxt/Output0.rtc in ' + 'execution context 0 (Required)' in stderr) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + + def test_dry_run(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtstart', + './test/sys.rtsys', '--dry-run']) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self.assert_('Check for required component "RTC:Geoffrey ' + 'Biggs:test:Std:1.0", "Std0" at path ' + '/localhost/local.host_cxt/Std0.rtc (Required)' in stdout) + self.assert_('Check for required component "RTC:Geoffrey ' + 'Biggs:Test:Output:1.0", "Output0" at path ' + '/localhost/local.host_cxt/Output0.rtc (Required)' in stdout) + self.assert_('Activate /localhost/local.host_cxt/Std0.rtc in ' + 'execution context 0 (Required)' in stdout) + self.assert_('Activate /localhost/local.host_cxt/Output0.rtc in ' + 'execution context 0 (Required)' in stdout) + + +def rtstart_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtstartTests) + + +class rtstopTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = None + wait_for_comp('Std0.rtc') + + def tearDown(self): + stop_comp(self._std) + if self._output: + stop_comp(self._output) + stop_ns(self._ns) + + def test_noprobs(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Std0.rtc']) + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Output0.rtc']) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtstop', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(ret, 0) + self.assert_('Deactivate /localhost/local.host_cxt/Std0.rtc in ' + 'execution context 0' in stderr) + self.assert_('Deactivate /localhost/local.host_cxt/Output0.rtc in ' + 'execution context 0' in stderr) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + + def test_missing_comp(self): + stdout, stderr, ret = call_process(['./rtstop', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assert_('Action failed: Component missing: ' + '/localhost/local.host_cxt/Output0.rtc' in stderr) + self.assertEqual(ret, 0) + + def test_already_inactive(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtact', + '/localhost/local.host_cxt/Std0.rtc']) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Active') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtstop', './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(ret, 0) + self.assert_('Deactivate /localhost/local.host_cxt/Std0.rtc in ' + 'execution context 0' in stderr) + self.assert_('Deactivate /localhost/local.host_cxt/Output0.rtc in ' + 'execution context 0' in stderr) + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Std0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + stdout, stderr, ret = call_process(['./rtcat', + '/localhost/local.host_cxt/Output0.rtc']) + self.assertEqual(stdout.split()[1], 'Inactive') + + def test_dry_run(self): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtstop', + './test/sys.rtsys', '--dry-run']) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self.assert_('Deactivate /localhost/local.host_cxt/Std0.rtc in ' + 'execution context 0' in stdout) + self.assert_('Deactivate /localhost/local.host_cxt/Output0.rtc in ' + 'execution context 0' in stdout) + + +def rtstop_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtstopTests) + + +class rtteardownTests(unittest.TestCase): + def setUp(self): + self._ns = start_ns() + self._std = launch_comp('std_comp') + self._output = None + wait_for_comp('Std0.rtc') + + def tearDown(self): + stop_comp(self._std) + if self._output: + stop_comp(self._output) + stop_ns(self._ns) + + def _setup_comp(self, id=''): + self._output = launch_comp('output_comp') + wait_for_comp('Output0.rtc') + args = ['./rtcon', + '/localhost/local.host_cxt/Std0.rtc:in', + '/localhost/local.host_cxt/Output0.rtc:out'] + if id: + args += ['-i', id] + stdout, stderr, ret = call_process(args) + + def test_noprobs(self): + self._setup_comp('connection_id0') + stdout, stderr, ret = call_process(['./rtteardown', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + stdout, stderr, ret = call_process(['./rtcat', '-l', + '/localhost/local.host_cxt/Std0.rtc:in']) + self.assert_('Connected to' not in stdout) + + def test_missing_comp(self): + stdout, stderr, ret = call_process(['./rtteardown', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Action failed: Source component missing: ' + '/localhost/local.host_cxt/Output0.rtc') + self.assertEqual(ret, 0) + + def test_missing_port(self): + self._output = launch_comp('output_noport_comp') + wait_for_comp('Output0.rtc') + stdout, stderr, ret = call_process(['./rtteardown', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Action failed: Source port missing: ' + '/localhost/local.host_cxt/Output0.rtc:out') + self.assertEqual(ret, 0) + + def test_wrong_id(self): + self._setup_comp('other_id') + stdout, stderr, ret = call_process(['./rtteardown', + './test/sys.rtsys']) + self.assertEqual(stdout, '') + self.assertEqual(stderr, 'Action failed: No connection from ' + '/localhost/local.host_cxt/Output0.rtc:out with ID connection_id0') + self.assertEqual(ret, 0) + + def test_dry_run(self): + self._setup_comp('connection_id0') + stdout, stderr, ret = call_process(['./rtteardown', + './test/sys.rtsys', '--dry-run']) + self.assertEqual(stderr, '') + self.assertEqual(ret, 0) + self.assertEqual(stdout, 'Disconnect ' + '/localhost/local.host_cxt/Output0.rtc:out from ' + '/localhost/local.host_cxt/Std0.rtc:in with ID connection_id0') + + +def rtteardown_suite(): + return unittest.TestLoader().loadTestsFromTestCase(rtteardownTests) + + +def suite(): + return unittest.TestSuite([rtact_suite(), rtdeact_suite(), rtreset_suite(), + rtcat_suite(), rtcheck_suite(), rtcomp_suite(), rtcon_suite(), + rtconf_suite(), rtcryo_suite(), rtcwd_suite(), rtdel_suite(), + rtdis_suite(), rtdoc_suite(), rtexit_suite(), rtfind_suite(), + rtinject_suite(), rtlog_suite(), rtls_suite(), rtmgr_suite(), + rtprint_suite(), rtresurrect_suite(), rtstart_suite(), + rtstodot_suite(), rtstop_suite(), rtteardown_suite()]) + + +if __name__ == '__main__': + if len(sys.argv) >= 2: + COMP_LIB_PATH = sys.argv[1] + sys.argv = [sys.argv[0]] + sys.argv[2:] + unittest.main() + #unittest.TextTestRunner().run(rtcomp_suite()) + diff --git a/test/test_idl.py b/test/test_idl.py new file mode 100644 index 0000000..4400a0c --- /dev/null +++ b/test/test_idl.py @@ -0,0 +1,40 @@ +# Python stubs generated by omniidl from test.idl + +import omniORB, _omnipy +from omniORB import CORBA, PortableServer +_0_CORBA = CORBA + +_omnipy.checkVersion(3,0, __file__) + + +# +# Start of module "MyData" +# +__name__ = "MyData" +_0_MyData = omniORB.openModule("MyData", r"test.idl") +_0_MyData__POA = omniORB.openModule("MyData__POA", r"test.idl") + + +# struct Bleg +_0_MyData.Bleg = omniORB.newEmptyClass() +class Bleg (omniORB.StructBase): + _NP_RepositoryId = "IDL:MyData/Bleg:1.0" + + def __init__(self, val1, val2): + self.val1 = val1 + self.val2 = val2 + +_0_MyData.Bleg = Bleg +_0_MyData._d_Bleg = (omniORB.tcInternal.tv_struct, Bleg, Bleg._NP_RepositoryId, "Bleg", "val1", omniORB.tcInternal.tv_ulong, "val2", omniORB.tcInternal.tv_ulong) +_0_MyData._tc_Bleg = omniORB.tcInternal.createTypeCode(_0_MyData._d_Bleg) +omniORB.registerType(Bleg._NP_RepositoryId, _0_MyData._d_Bleg, _0_MyData._tc_Bleg) +del Bleg + +# +# End of module "MyData" +# +__name__ = "test_idl" + +_exported_modules = ( "MyData", ) + +# The end. diff --git a/test/test_mod1.py b/test/test_mod1.py new file mode 100644 index 0000000..1bca0b0 --- /dev/null +++ b/test/test_mod1.py @@ -0,0 +1,6 @@ +a = '1' + +class Dummy(object): + def __init__(self, param1, param2): + self.param1 = param1 + self.param2 = param2 diff --git a/test/test_mod1__POA.py b/test/test_mod1__POA.py new file mode 100644 index 0000000..b81dea6 --- /dev/null +++ b/test/test_mod1__POA.py @@ -0,0 +1 @@ +a = '1__poa' diff --git a/test/test_mod2.py b/test/test_mod2.py new file mode 100644 index 0000000..2227d34 --- /dev/null +++ b/test/test_mod2.py @@ -0,0 +1 @@ +a = '2' diff --git a/test/test_mod2__POA.py b/test/test_mod2__POA.py new file mode 100644 index 0000000..2e5450e --- /dev/null +++ b/test/test_mod2__POA.py @@ -0,0 +1 @@ +a = '2__poa' diff --git a/test/unittests.py b/test/unittests.py new file mode 100755 index 0000000..5dc8998 --- /dev/null +++ b/test/unittests.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python +# -*- Python -*- +# -*- coding: utf-8 -*- + +'''rtshell + +Copyright (C) 2009-2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Unit tests. + +''' + + +import unittest + +import rtshell.eval_const +import rtshell.rts_exceptions +import rtshell.port_types +import rtshell.user_mods + +import blorg + + +class TestUserMods(unittest.TestCase): + def test_load_mods(self): + mods = rtshell.user_mods.load_mods('test_mod1,test_mod2') + self.assertEqual(len(mods), 2) + self.assertEqual(mods[0].name, 'test_mod1') + self.assertEqual(type(mods[0].mod), type(rtshell.user_mods)) + self.assertEqual(mods[1].name, 'test_mod2') + self.assertEqual(type(mods[1].mod), type(rtshell.user_mods)) + self.assertRaises(ImportError, rtshell.user_mods.load_mods, 'blurgle') + + def test_load_mods_and_poas(self): + mods = rtshell.user_mods.load_mods_and_poas('test_mod1,test_mod2') + self.assertEqual(len(mods), 4) + self.assertEqual(mods[0].name, 'test_mod1') + self.assertEqual(type(mods[0].mod), type(rtshell.user_mods)) + self.assertEqual(mods[1].name, 'test_mod1__POA') + self.assertEqual(type(mods[1].mod), type(rtshell.user_mods)) + self.assertRaises(ImportError, rtshell.user_mods.load_mods_and_poas, + 'blorg') + + +class TestEvalConst(unittest.TestCase): + def setUp(self): + self.mods = [rtshell.user_mods.Module('test_mod1')] + self.const = 'test_mod1.Dummy(4,2)' + + def test_replace_mod_name(self): + self.assertEqual(rtshell.eval_const.replace_mod_name(self.const, + self.mods), 'mods[0].mod.Dummy(4,2)') + + def test_replace_time(self): + const = 'blurgle({time})' + self.assert_(len(rtshell.eval_const.replace_time(const)) > len(const)) + + def test_eval_const(self): + class Data(object): + def __init__(self, val): + self.val = val + + self.assertEqual(rtshell.eval_const.eval_const('1', self.mods), 1) + self.assertEqual(rtshell.eval_const.eval_const('list((1, 2, 3))', + self.mods), [1, 2, 3]) + + +class TestParseTargets(unittest.TestCase): + def setUp(self): + self.p1 = (['/', 'localhost', 'my.host_cxt', 'comp0.rtc'], 'input0', + 'namae', 'blorg.format') + self.p2 = (['/', 'localhost', 'my.host_cxt', 'comp1.rtc'], 'out_put1', + 'namae2', None) + self.p3 = (['/', 'localhost', 'my.host_cxt', 'comp1.rtc'], 'out_put1', + None, 'blorg.format') + self.p4 = (['/', 'localhost', 'my.host_cxt', 'comp0.rtc'], 'input0', + None, None) + + def test_parse_targets(self): + ps = rtshell.port_types.parse_targets(['/localhost/my.host_cxt/comp0.rtc:input0.namae#blorg.format', + '/localhost/my.host_cxt/comp1.rtc:out_put1.namae2', + '/localhost/my.host_cxt/comp1.rtc:out_put1#blorg.format', + '/localhost/my.host_cxt/comp0.rtc:input0']) + self.assertEqual(ps[0], self.p1) + self.assertEqual(ps[1], self.p2) + self.assertEqual(ps[2], self.p3) + self.assertEqual(ps[3], self.p4) + self.assertRaises(rtshell.rts_exceptions.BadPortSpecError, + rtshell.port_types.parse_targets, ['this_is_wrong']) + self.assertRaises(rtshell.rts_exceptions.BadPortSpecError, + rtshell.port_types.parse_targets, ['/localhost/comp0.rtc']) + self.assertRaises(rtshell.rts_exceptions.BadPortSpecError, + rtshell.port_types.parse_targets, ['']) + + +if __name__ == '__main__': + unittest.main() + + +# vim: tw=79 + diff --git a/test/zombie_comp b/test/zombie_comp new file mode 100755 index 0000000..a333aca --- /dev/null +++ b/test/zombie_comp @@ -0,0 +1,77 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# -*- Python -*- + + +'''rtshell + +Copyright (C) 2010 + Geoffrey Biggs + RT-Synthesis Research Group + Intelligent Systems Research Institute, + National Institute of Advanced Industrial Science and Technology (AIST), + Japan + All rights reserved. +Licensed under the Eclipse Public License -v 1.0 (EPL) +http://www.opensource.org/licenses/eclipse-1.0.txt + +Simple output component for tests. + +''' + + +import OpenRTM_aist +import RTC +import sys + + +class ZombieComp(OpenRTM_aist.DataFlowComponentBase): + def __init__(self, manager): + OpenRTM_aist.DataFlowComponentBase.__init__(self, manager) + + def onInitialize(self): + self._data = RTC.TimedLong(RTC.Time(0, 0), 0) + self._outport = OpenRTM_aist.OutPort('out', self._data) + self.addOutPort('out', self._outport) + self._count = 0 + return RTC.RTC_OK + + def onExecute(self, ec_id): + if self._inport.isNew(): + print self._inport.read().data + return RTC.RTC_OK + + +comp_spec = ['implementation_id', 'Zombie', + 'type_name', 'Zombie', + 'description', 'Standard component', + 'version', '1.0', + 'vendor', 'Geoffrey Biggs', + 'category', 'Test', + 'activity_type', 'DataFlowComponent', + 'max_instance', '2', + 'language', 'Python', + 'lang_type', 'script', + ''] + + +def CompInit(manager): + profile = OpenRTM_aist.Properties(defaults_str=comp_spec) + manager.registerFactory(profile, ZombieComp, OpenRTM_aist.Delete) + + +def ModuleInit(manager): + CompInit(manager) + manager.createComponent('Zombie') + + +def main(): + mgr = OpenRTM_aist.Manager.init(sys.argv) + mgr.setModuleInitProc(ModuleInit) + mgr.activateManager() + mgr.runManager() + + +if __name__ == '__main__': + main() +