├── templates
├── pythonapp
│ ├── app
│ │ ├── .metadata
│ │ ├── icon.png
│ │ ├── scripts
│ │ │ ├── stk
│ │ │ │ ├── __init__.py
│ │ │ │ ├── services.py
│ │ │ │ ├── logging.py
│ │ │ │ ├── runner.py
│ │ │ │ └── events.py
│ │ │ └── main.py
│ │ ├── manifest.xml
│ │ ├── pythonapp.pml
│ │ └── behavior.xar
│ └── .gitignore
├── dialog-service
│ ├── app
│ │ ├── .metadata
│ │ ├── dialog-service
│ │ │ ├── dialog-service.dlg
│ │ │ └── dialog-service_enu.top
│ │ ├── icon.png
│ │ ├── scripts
│ │ │ ├── stk
│ │ │ │ ├── __init__.py
│ │ │ │ ├── services.py
│ │ │ │ ├── logging.py
│ │ │ │ ├── runner.py
│ │ │ │ └── events.py
│ │ │ └── myservice.py
│ │ ├── manifest.xml
│ │ ├── dialog-service.pml
│ │ └── testrun
│ │ │ └── behavior.xar
│ ├── .gitignore
│ └── testrun.py
├── python-service
│ ├── app
│ │ ├── .metadata
│ │ ├── icon.png
│ │ ├── scripts
│ │ │ ├── stk
│ │ │ │ ├── __init__.py
│ │ │ │ ├── services.py
│ │ │ │ ├── logging.py
│ │ │ │ └── runner.py
│ │ │ └── myservice.py
│ │ ├── manifest.xml
│ │ └── python-service.pml
│ ├── .gitignore
│ └── testrun.py
├── app-with-tablet
│ ├── app
│ │ ├── .metadata
│ │ ├── icon.png
│ │ ├── scripts
│ │ │ ├── stk
│ │ │ │ ├── __init__.py
│ │ │ │ ├── services.py
│ │ │ │ ├── logging.py
│ │ │ │ ├── runner.py
│ │ │ │ └── events.py
│ │ │ └── myservice.py
│ │ ├── translations
│ │ │ └── translation_en_US.ts
│ │ ├── html
│ │ │ ├── js
│ │ │ │ └── main.js
│ │ │ ├── css
│ │ │ │ └── style.css
│ │ │ └── index.html
│ │ ├── manifest.xml
│ │ ├── app-with-tablet.pml
│ │ └── behavior.xar
│ ├── .gitignore
│ ├── debug
│ │ ├── index.html
│ │ └── js
│ │ │ └── jquery.cookie.js
│ ├── serve.py
│ └── testrun.py
├── service-tabletpage
│ ├── app
│ │ ├── .metadata
│ │ ├── scripts
│ │ │ ├── stk
│ │ │ │ ├── __init__.py
│ │ │ │ ├── services.py
│ │ │ │ ├── logging.py
│ │ │ │ └── runner.py
│ │ │ └── myservice.py
│ │ ├── icon.png
│ │ ├── translations
│ │ │ └── translation_en_US.ts
│ │ ├── manifest.xml
│ │ ├── html
│ │ │ ├── css
│ │ │ │ └── style.css
│ │ │ ├── js
│ │ │ │ └── main.js
│ │ │ └── index.html
│ │ ├── service-tabletpage.pml
│ │ └── behavior.xar
│ ├── .gitignore
│ ├── debug
│ │ ├── index.html
│ │ └── js
│ │ │ └── jquery.cookie.js
│ ├── serve.py
│ └── testrun.py
├── service-webpage-nao
│ ├── app
│ │ ├── .metadata
│ │ ├── icon.png
│ │ ├── scripts
│ │ │ ├── stk
│ │ │ │ ├── __init__.py
│ │ │ │ ├── services.py
│ │ │ │ ├── logging.py
│ │ │ │ └── runner.py
│ │ │ └── myservice.py
│ │ ├── manifest.xml
│ │ ├── html
│ │ │ ├── css
│ │ │ │ └── style.css
│ │ │ ├── index.html
│ │ │ └── js
│ │ │ │ └── main.js
│ │ └── service-webpage-nao.pml
│ ├── .gitignore
│ ├── debug
│ │ ├── index.html
│ │ └── js
│ │ │ └── jquery.cookie.js
│ ├── serve.py
│ └── testrun.py
├── simple-tabletpage
│ ├── app
│ │ ├── .metadata
│ │ ├── icon.png
│ │ ├── html
│ │ │ ├── js
│ │ │ │ └── main.js
│ │ │ ├── css
│ │ │ │ └── style.css
│ │ │ └── index.html
│ │ ├── simple-tabletpage.pml
│ │ ├── manifest.xml
│ │ └── behavior.xar
│ ├── debug
│ │ ├── index.html
│ │ └── js
│ │ │ └── jquery.cookie.js
│ └── serve.py
└── simple-webpage-nao
│ ├── app
│ ├── .metadata
│ ├── icon.png
│ ├── html
│ │ ├── js
│ │ │ └── main.js
│ │ ├── css
│ │ │ └── style.css
│ │ └── index.html
│ ├── simple-webpage-nao.pml
│ └── manifest.xml
│ ├── debug
│ ├── index.html
│ └── js
│ │ └── jquery.cookie.js
│ └── serve.py
├── .gitignore
├── COPYING
├── doc
└── services.md
└── jumpstart.py
/templates/pythonapp/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/python-service/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/.metadata:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/templates/pythonapp/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
3 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
3 |
--------------------------------------------------------------------------------
/templates/dialog-service/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
3 |
--------------------------------------------------------------------------------
/templates/python-service/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
3 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
3 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 |
3 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/dialog-service/dialog-service.dlg:
--------------------------------------------------------------------------------
1 | multilanguage:dialog-service
2 | enu:dialog-service_enu.top
3 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/pythonapp/app/icon.png
--------------------------------------------------------------------------------
/templates/dialog-service/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/dialog-service/app/icon.png
--------------------------------------------------------------------------------
/templates/python-service/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/python-service/app/icon.png
--------------------------------------------------------------------------------
/templates/pythonapp/app/scripts/stk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | STK - A collection of libraries useful for making apps with NAOqi.
3 | """
4 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/app-with-tablet/app/icon.png
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/scripts/stk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | STK - A collection of libraries useful for making apps with NAOqi.
3 | """
4 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/scripts/stk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | STK - A collection of libraries useful for making apps with NAOqi.
3 | """
4 |
--------------------------------------------------------------------------------
/templates/python-service/app/scripts/stk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | STK - A collection of libraries useful for making apps with NAOqi.
3 | """
4 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/scripts/stk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | STK - A collection of libraries useful for making apps with NAOqi.
3 | """
4 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/simple-tabletpage/app/icon.png
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/service-tabletpage/app/icon.png
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/service-webpage-nao/app/icon.png
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/scripts/stk/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | STK - A collection of libraries useful for making apps with NAOqi.
3 | """
4 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/aldebaran/robot-jumpstarter/HEAD/templates/simple-webpage-nao/app/icon.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.pyc
2 | output/*
3 |
4 | *.pkg
5 |
6 | .DS_Store
7 |
8 | *.idea
9 | .floo
10 | .flooignore
11 |
12 | */bower_components/*
13 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/translations/translation_en_US.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/translations/translation_en_US.ts:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/html/js/main.js:
--------------------------------------------------------------------------------
1 | var application = function(){
2 | RobotUtils.onService(function(ALTextToSpeech) {
3 | // Bind button callbacks
4 | $(".bleeper").click(function() {
5 | ALTextToSpeech.say($(this).html());
6 | });
7 | });
8 | }
9 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/html/js/main.js:
--------------------------------------------------------------------------------
1 | var application = function(){
2 | RobotUtils.onService(function(ALTextToSpeech) {
3 | // Bind button callbacks
4 | $(".bleeper").click(function() {
5 | ALTextToSpeech.say($(this).html());
6 | });
7 | });
8 | }
9 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/dialog-service/dialog-service_enu.top:
--------------------------------------------------------------------------------
1 | topic: ~dialog-service()
2 | language: enu
3 |
4 | concept:(numbers) [0 1 2 3 4 5 6 7 8 9 10]
5 |
6 | u:(set {the} counter [to at] _~numbers)
7 | setting counter to $1
8 | ^call(ALMyService.set($1))
9 |
10 | u:(["check counter" "what is the counter?"])
11 | So, ^call(ALMyService.get())
12 | c1:(_*) the counter is $1
13 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/html/js/main.js:
--------------------------------------------------------------------------------
1 | var KEY_TABLETSETATE = "app-with-tablet/TabletState";
2 |
3 | function updateTabletState(stateJson) {
4 | var state = JSON.parse(stateJson);
5 | if (state.title) {
6 | $("#biglabel").show();
7 | $("#biglabel").html(state.title);
8 | } else {
9 | $("#biglabel").hide();
10 | }
11 | }
12 |
13 | RobotUtils.onService(function (ALMemory) {
14 | ALMemory.getData(KEY_TABLETSETATE).then(updateTabletState);
15 | //updateTabletState('{"title": "TEST"}');
16 | });
17 | RobotUtils.subscribeToALMemoryEvent(KEY_TABLETSETATE, updateTabletState);
18 |
--------------------------------------------------------------------------------
/templates/python-service/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | python-service
5 |
6 |
7 | en_US
8 |
9 |
10 | en_US
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/html/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
3 | }
4 |
5 | body{
6 | margin: 0px;
7 | background-color: black;
8 | }
9 |
10 | .centered {
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | margin-right: -50%;
15 | transform: translate(-50%, -50%);
16 | text-align: center;
17 | }
18 |
19 | .tabletsized {
20 | background-color: lightblue;
21 | width: 1280px;
22 | height: 800px;
23 | position: absolute;
24 | }
25 |
26 | #exit {
27 | font-size: 100px;
28 | position: absolute;
29 | top: 0px;
30 | right: 15px;
31 | }
32 |
33 | #biglabel {
34 | font-size: 300px;
35 | }
36 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | service-webpage-nao
5 |
6 |
7 | en_US
8 |
9 |
10 | en_US
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/simple-webpage-nao.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | simple-webpage-nao
5 | servicedriven
6 |
7 |
8 | en_US
9 |
10 |
11 | en_US
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/html/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
3 | }
4 |
5 | body{
6 | margin: 0px;
7 | background-color: lightblue;
8 | }
9 |
10 | .centered {
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | margin-right: -50%;
15 | transform: translate(-50%, -50%);
16 | text-align: center;
17 | }
18 |
19 | .bigfriendlybutton {
20 | border-radius: 25px;
21 | display: inline-block;
22 | width: 300px;
23 | height: 100px;
24 | background-color: blue;
25 | color: white;
26 | text-align: center;
27 | font-family: Arial, Helvetica, sans-serif;
28 | font-size: 35px;
29 | font-style: normal;
30 | font-weight: bold;
31 | line-height: 50px;
32 | }
33 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/html/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
3 | }
4 |
5 | body{
6 | margin: 0px;
7 | background-color: lightblue;
8 | }
9 |
10 | .centered {
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | margin-right: -50%;
15 | transform: translate(-50%, -50%);
16 | text-align: center;
17 | }
18 |
19 | .bigfriendlybutton {
20 | border-radius: 25px;
21 | display: inline-block;
22 | width: 300px;
23 | height: 100px;
24 | background-color: blue;
25 | color: white;
26 | text-align: center;
27 | font-family: Arial, Helvetica, sans-serif;
28 | font-size: 35px;
29 | font-style: normal;
30 | font-weight: bold;
31 | line-height: 50px;
32 | }
33 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | pythonapp
5 |
6 |
7 | en_US
8 |
9 |
10 | en_US
11 |
12 |
13 |
14 |
15 | interactive
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/simple-tabletpage.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | app-with-tablet
5 |
6 |
7 | en_US
8 |
9 |
10 | en_US
11 |
12 |
13 |
14 |
15 | interactive
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | service-tabletpage
5 |
6 |
7 | en_US
8 |
9 |
10 | en_US
11 |
12 |
13 |
14 |
15 | interactive
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/app/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/html/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
3 | }
4 |
5 | body{
6 | margin: 0px;
7 | background-color: black;
8 | }
9 |
10 | .centered {
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | margin-right: -50%;
15 | transform: translate(-50%, -50%);
16 | text-align: center;
17 | }
18 |
19 | .levelbutton {
20 | border-radius: 25px;
21 | display: inline-block;
22 | width: 250px;
23 | height: 100px;
24 | background-color: blue;
25 | color: white;
26 | text-align: center;
27 | font-family: Arial, Helvetica, sans-serif;
28 | font-size: 35px;
29 | font-style: normal;
30 | font-weight: bold;
31 | line-height: 50px;
32 | }
33 |
34 | .levelbutton.clicked {
35 | background-color: grey;
36 | }
37 |
38 | .levelbutton.clicked.highlighted {
39 | background-color: darkblue;
40 | }
41 |
42 | .tabletsized {
43 | background-color: lightblue;
44 | width: 1280px;
45 | height: 800px;
46 | position: absolute;
47 | }
48 |
49 | #exit {
50 | font-size: 100px;
51 | position: absolute;
52 | top: 0px;
53 | right: 15px;
54 | }
55 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/html/css/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
3 | }
4 |
5 | body{
6 | margin: 0px;
7 | background-color: black;
8 | }
9 |
10 | .centered {
11 | position: absolute;
12 | top: 50%;
13 | left: 50%;
14 | margin-right: -50%;
15 | transform: translate(-50%, -50%);
16 | text-align: center;
17 | }
18 |
19 | .levelbutton {
20 | border-radius: 25px;
21 | display: inline-block;
22 | width: 250px;
23 | height: 100px;
24 | background-color: blue;
25 | color: white;
26 | text-align: center;
27 | font-family: Arial, Helvetica, sans-serif;
28 | font-size: 35px;
29 | font-style: normal;
30 | font-weight: bold;
31 | line-height: 50px;
32 | }
33 |
34 | .levelbutton.clicked {
35 | background-color: grey;
36 | }
37 |
38 | .levelbutton.clicked.highlighted {
39 | background-color: darkblue;
40 | }
41 |
42 | .tabletsized {
43 | background-color: lightblue;
44 | width: 1280px;
45 | height: 800px;
46 | position: absolute;
47 | }
48 |
49 | #exit {
50 | font-size: 100px;
51 | position: absolute;
52 | top: 0px;
53 | right: 15px;
54 | }
55 |
--------------------------------------------------------------------------------
/templates/python-service/app/python-service.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/pythonapp.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | Service ALMyService not found :(
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | simple-tabletpage
5 | servicedriven
6 |
7 |
8 | en_US
9 |
10 |
11 | en_US
12 |
13 |
14 |
15 |
16 | interactive
17 |
18 | simple-tabletpage
19 |
20 |
21 | Shows a page on the tablet
22 |
23 |
24 | simple tablet page
25 | Lance servicedriven
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/html/js/main.js:
--------------------------------------------------------------------------------
1 | var application = function(){
2 | RobotUtils.onService(function (ALMyService) {
3 | $("#noservice").hide();
4 | ALMyService.get().then(function(level) {
5 | // Find the button with the right level:
6 | $(".levelbutton").each(function() {
7 | var button = $(this);
8 | if (button.data("level") == level) {
9 | button.addClass("highlighted");
10 | button.addClass("clicked");
11 | }
12 | });
13 | // ... and show all buttons:
14 | $("#buttons").show();
15 | });
16 | $(".levelbutton").click(function() {
17 | // grey out the button, until we hear back that the click worked.
18 | var button = $(this);
19 | var level = button.data("level");
20 | $(".levelbutton").removeClass("highlighted");
21 | $(".levelbutton").removeClass("clicked");
22 | button.addClass("clicked");
23 | ALMyService.set(level).then(function(){
24 | button.addClass("highlighted");
25 | });
26 | })
27 | }, function() {
28 | console.log("Failed to get the service.")
29 | $("#noservice").show();
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/html/js/main.js:
--------------------------------------------------------------------------------
1 | var application = function(){
2 | RobotUtils.onService(function (ALMyService) {
3 | $("#noservice").hide();
4 | ALMyService.get().then(function(level) {
5 | // Find the button with the right level:
6 | $(".levelbutton").each(function() {
7 | var button = $(this);
8 | if (button.data("level") == level) {
9 | button.addClass("highlighted");
10 | button.addClass("clicked");
11 | }
12 | });
13 | // ... and show all buttons:
14 | $("#buttons").show();
15 | });
16 | $(".levelbutton").click(function() {
17 | // grey out the button, until we hear back that the click worked.
18 | var button = $(this);
19 | var level = button.data("level");
20 | $(".levelbutton").removeClass("highlighted");
21 | $(".levelbutton").removeClass("clicked");
22 | button.addClass("clicked");
23 | ALMyService.set(level).then(function(){
24 | button.addClass("highlighted");
25 | });
26 | })
27 | }, function() {
28 | console.log("Failed to get the service.")
29 | $("#noservice").show();
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/html/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Service ALMyService not found :(
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/manifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | dialog-service
5 |
6 |
7 | A simple app consisting of a collaborative dialogue talking to a service.
8 |
9 |
10 | en_US
11 |
12 |
13 | en_US
14 |
15 |
16 |
17 | interactive
18 |
19 |
20 | Launch this to test your collaborative dialog in isolation (easier for debugging)
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/scripts/stk/services.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.services.py
3 |
4 | Syntactic sugar for accessing NAOqi services.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 |
14 | class ServiceCache(object):
15 | "A helper for accessing NAOqi services."
16 |
17 | def __init__(self, session=None):
18 | self.session = None
19 | self.services = {}
20 | if session:
21 | self.init(session)
22 |
23 | def init(self, session):
24 | "Sets the session object, if it wasn't passed to constructor."
25 | self.session = session
26 |
27 | def __getattr__(self, servicename):
28 | "We overload this so (instance).ALMotion returns the service, or None."
29 | if (not servicename in self.services) or (
30 | servicename == "ALTabletService"):
31 | # ugly hack: never cache ALtabletService, always ask for a new one
32 | if servicename.startswith("__"):
33 | # Behave like a normal python object for those
34 | raise AttributeError
35 | try:
36 | self.services[servicename] = self.session.service(servicename)
37 | except RuntimeError: # Cannot find service
38 | self.services[servicename] = None
39 | return self.services[servicename]
40 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/scripts/stk/services.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.services.py
3 |
4 | Syntactic sugar for accessing NAOqi services.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 |
14 | class ServiceCache(object):
15 | "A helper for accessing NAOqi services."
16 |
17 | def __init__(self, session=None):
18 | self.session = None
19 | self.services = {}
20 | if session:
21 | self.init(session)
22 |
23 | def init(self, session):
24 | "Sets the session object, if it wasn't passed to constructor."
25 | self.session = session
26 |
27 | def __getattr__(self, servicename):
28 | "We overload this so (instance).ALMotion returns the service, or None."
29 | if (not servicename in self.services) or (
30 | servicename == "ALTabletService"):
31 | # ugly hack: never cache ALtabletService, always ask for a new one
32 | if servicename.startswith("__"):
33 | # Behave like a normal python object for those
34 | raise AttributeError
35 | try:
36 | self.services[servicename] = self.session.service(servicename)
37 | except RuntimeError: # Cannot find service
38 | self.services[servicename] = None
39 | return self.services[servicename]
40 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/scripts/stk/services.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.services.py
3 |
4 | Syntactic sugar for accessing NAOqi services.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 |
14 | class ServiceCache(object):
15 | "A helper for accessing NAOqi services."
16 |
17 | def __init__(self, session=None):
18 | self.session = None
19 | self.services = {}
20 | if session:
21 | self.init(session)
22 |
23 | def init(self, session):
24 | "Sets the session object, if it wasn't passed to constructor."
25 | self.session = session
26 |
27 | def __getattr__(self, servicename):
28 | "We overload this so (instance).ALMotion returns the service, or None."
29 | if (not servicename in self.services) or (
30 | servicename == "ALTabletService"):
31 | # ugly hack: never cache ALtabletService, always ask for a new one
32 | if servicename.startswith("__"):
33 | # Behave like a normal python object for those
34 | raise AttributeError
35 | try:
36 | self.services[servicename] = self.session.service(servicename)
37 | except RuntimeError: # Cannot find service
38 | self.services[servicename] = None
39 | return self.services[servicename]
40 |
--------------------------------------------------------------------------------
/templates/python-service/app/scripts/stk/services.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.services.py
3 |
4 | Syntactic sugar for accessing NAOqi services.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 |
14 | class ServiceCache(object):
15 | "A helper for accessing NAOqi services."
16 |
17 | def __init__(self, session=None):
18 | self.session = None
19 | self.services = {}
20 | if session:
21 | self.init(session)
22 |
23 | def init(self, session):
24 | "Sets the session object, if it wasn't passed to constructor."
25 | self.session = session
26 |
27 | def __getattr__(self, servicename):
28 | "We overload this so (instance).ALMotion returns the service, or None."
29 | if (not servicename in self.services) or (
30 | servicename == "ALTabletService"):
31 | # ugly hack: never cache ALtabletService, always ask for a new one
32 | if servicename.startswith("__"):
33 | # Behave like a normal python object for those
34 | raise AttributeError
35 | try:
36 | self.services[servicename] = self.session.service(servicename)
37 | except RuntimeError: # Cannot find service
38 | self.services[servicename] = None
39 | return self.services[servicename]
40 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/scripts/stk/services.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.services.py
3 |
4 | Syntactic sugar for accessing NAOqi services.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 |
14 | class ServiceCache(object):
15 | "A helper for accessing NAOqi services."
16 |
17 | def __init__(self, session=None):
18 | self.session = None
19 | self.services = {}
20 | if session:
21 | self.init(session)
22 |
23 | def init(self, session):
24 | "Sets the session object, if it wasn't passed to constructor."
25 | self.session = session
26 |
27 | def __getattr__(self, servicename):
28 | "We overload this so (instance).ALMotion returns the service, or None."
29 | if (not servicename in self.services) or (
30 | servicename == "ALTabletService"):
31 | # ugly hack: never cache ALtabletService, always ask for a new one
32 | if servicename.startswith("__"):
33 | # Behave like a normal python object for those
34 | raise AttributeError
35 | try:
36 | self.services[servicename] = self.session.service(servicename)
37 | except RuntimeError: # Cannot find service
38 | self.services[servicename] = None
39 | return self.services[servicename]
40 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/scripts/stk/services.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.services.py
3 |
4 | Syntactic sugar for accessing NAOqi services.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 |
14 | class ServiceCache(object):
15 | "A helper for accessing NAOqi services."
16 |
17 | def __init__(self, session=None):
18 | self.session = None
19 | self.services = {}
20 | if session:
21 | self.init(session)
22 |
23 | def init(self, session):
24 | "Sets the session object, if it wasn't passed to constructor."
25 | self.session = session
26 |
27 | def __getattr__(self, servicename):
28 | "We overload this so (instance).ALMotion returns the service, or None."
29 | if (not servicename in self.services) or (
30 | servicename == "ALTabletService"):
31 | # ugly hack: never cache ALtabletService, always ask for a new one
32 | if servicename.startswith("__"):
33 | # Behave like a normal python object for those
34 | raise AttributeError
35 | try:
36 | self.services[servicename] = self.session.service(servicename)
37 | except RuntimeError: # Cannot find service
38 | self.services[servicename] = None
39 | return self.services[servicename]
40 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/service-webpage-nao.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/dialog-service.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/app-with-tablet.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/service-tabletpage.pml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015-2017, SoftBank Robotics Europe SAS
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without
5 | modification, are permitted provided that the following conditions are met:
6 | * Redistributions of source code must retain the above copyright
7 | notice, this list of conditions and the following disclaimer.
8 | * Redistributions in binary form must reproduce the above copyright
9 | notice, this list of conditions and the following disclaimer in the
10 | documentation and/or other materials provided with the distribution.
11 | * Neither the name of the SoftBank Robotics Europe SAS nor the
12 | names of its contributors may be used to endorse or promote products
13 | derived from this software without specific prior written permission.
14 |
15 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 | DISCLAIMED. IN NO EVENT SHALL SoftBank Robotics Europe SAS BE LIABLE FOR ANY
19 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/debug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App debug interface!
7 | Pick the robot to use
8 | Robot IP:
9 |
13 | The app's page will be displayed as if it was on a tablet connected to that robot
14 |
15 |
16 |
17 |
18 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/debug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App debug interface!
7 | Pick the robot to use
8 | Robot IP:
9 |
13 | The app's page will be displayed as if it was on a tablet connected to that robot
14 |
15 |
16 |
17 |
18 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/debug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App debug interface!
7 | Pick the robot to use
8 | Robot IP:
9 |
13 | The app's page will be displayed as if it was on a tablet connected to that robot
14 |
15 |
16 |
17 |
18 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/debug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App debug interface!
7 | Pick the robot to use
8 | Robot IP:
9 |
13 | The app's page will be displayed as if it was on a tablet connected to that robot
14 |
15 |
16 |
17 |
18 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/debug/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | App debug interface!
7 | Pick the robot to use
8 | Robot IP:
9 |
13 | The app's page will be displayed as if it was on a tablet connected to that robot
14 |
15 |
16 |
17 |
18 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/scripts/myservice.py:
--------------------------------------------------------------------------------
1 |
2 | """
3 | A sample showing how to make a Python script as an app.
4 | """
5 |
6 | __version__ = "0.0.8"
7 |
8 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
9 | __author__ = 'YOURNAME'
10 | __email__ = 'YOUREMAIL@aldebaran.com'
11 |
12 | import json
13 | import time
14 |
15 | import stk.runner
16 | import stk.events
17 | import stk.services
18 | import stk.logging
19 |
20 | KEY_TABLETSETATE = "app-with-tablet/TabletState"
21 |
22 | class ALMyService(object):
23 | "A sample standalone app, that demonstrates simple Python usage"
24 | APP_ID = "com.aldebaran.dx-team-presentation"
25 | def __init__(self, qiapp):
26 | self.qiapp = qiapp
27 | self.events = stk.events.EventHelper(qiapp.session)
28 | self.s = stk.services.ServiceCache(qiapp.session)
29 | self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
30 |
31 | def show(self, command):
32 | self.events.set(KEY_TABLETSETATE, json.dumps(command))
33 |
34 | def on_start(self):
35 | "Ask to be touched, waits, and exits."
36 | self.show({"title": "intro"})
37 | self.s.ALTextToSpeech.say("This is the first page")
38 | time.sleep(1.0)
39 | self.show({"title": "other"})
40 | self.s.ALTextToSpeech.say("This is another page")
41 | time.sleep(1.0)
42 | self.show({"title": "last"})
43 | self.s.ALTextToSpeech.say("This is the last page, I'm done")
44 | self.stop()
45 |
46 | def stop(self):
47 | "Standard way of stopping the application."
48 | self.qiapp.stop()
49 |
50 | def on_stop(self):
51 | "Cleanup"
52 | self.show({})
53 | self.logger.info("Application finished.")
54 | self.events.clear()
55 |
56 | if __name__ == "__main__":
57 | stk.runner.run_service(ALMyService)
58 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/serve.py:
--------------------------------------------------------------------------------
1 | """
2 | A helper script for testing your app's local html files, with no robot install.
3 |
4 | Usage:
5 | Run serve.py, a browser will open on a debug page, enter your robot's IP address
6 | and your local pages will be served as if they were on the robot.
7 |
8 | Using a server like this (as opposed to just file:// etc.) is only necessary
9 | if you do ajax calls in your page.
10 | """
11 |
12 | __version__ = "0.0.3"
13 |
14 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
15 | __author__ = 'ekroeger'
16 | __email__ = 'ekroeger@aldebaran.com'
17 |
18 | import os
19 | import threading
20 | import webbrowser
21 | import BaseHTTPServer
22 | import SimpleHTTPServer
23 | import urlparse
24 | import urllib
25 |
26 | USE_SERVER = False
27 |
28 | PORT = 8081
29 |
30 | def open_browser():
31 | """Start a browser after waiting for half a second."""
32 | if USE_SERVER:
33 | def _open_browser():
34 | url = 'http://localhost:%s/debug/index.html' % PORT
35 | webbrowser.open(url)
36 | thread = threading.Timer(0.5, _open_browser)
37 | thread.start()
38 | else:
39 | indexpath = os.path.join(os.getcwd(), "debug/index.html")
40 | url = urlparse.urljoin('file:', urllib.pathname2url(indexpath))
41 | webbrowser.open(url)
42 |
43 | def start_server():
44 | """Start the server."""
45 | if USE_SERVER:
46 | server_address = ("", PORT)
47 | handler_class = SimpleHTTPServer.SimpleHTTPRequestHandler
48 | handler_class.extensions_map['.png'] = 'image/png'
49 | server = BaseHTTPServer.HTTPServer(server_address, handler_class)
50 | server.serve_forever()
51 |
52 | def run():
53 | open_browser() # Comment out this line if you don't want to open a browser
54 | start_server()
55 |
56 | if __name__ == "__main__":
57 | run()
58 |
59 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/serve.py:
--------------------------------------------------------------------------------
1 | """
2 | A helper script for testing your app's local html files, with no robot install.
3 |
4 | Usage:
5 | Run serve.py, a browser will open on a debug page, enter your robot's IP address
6 | and your local pages will be served as if they were on the robot.
7 |
8 | Using a server like this (as opposed to just file:// etc.) is only necessary
9 | if you do ajax calls in your page.
10 | """
11 |
12 | __version__ = "0.0.3"
13 |
14 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
15 | __author__ = 'ekroeger'
16 | __email__ = 'ekroeger@aldebaran.com'
17 |
18 | import os
19 | import threading
20 | import webbrowser
21 | import BaseHTTPServer
22 | import SimpleHTTPServer
23 | import urlparse
24 | import urllib
25 |
26 | USE_SERVER = False
27 |
28 | PORT = 8081
29 |
30 | def open_browser():
31 | """Start a browser after waiting for half a second."""
32 | if USE_SERVER:
33 | def _open_browser():
34 | url = 'http://localhost:%s/debug/index.html' % PORT
35 | webbrowser.open(url)
36 | thread = threading.Timer(0.5, _open_browser)
37 | thread.start()
38 | else:
39 | indexpath = os.path.join(os.getcwd(), "debug/index.html")
40 | url = urlparse.urljoin('file:', urllib.pathname2url(indexpath))
41 | webbrowser.open(url)
42 |
43 | def start_server():
44 | """Start the server."""
45 | if USE_SERVER:
46 | server_address = ("", PORT)
47 | handler_class = SimpleHTTPServer.SimpleHTTPRequestHandler
48 | handler_class.extensions_map['.png'] = 'image/png'
49 | server = BaseHTTPServer.HTTPServer(server_address, handler_class)
50 | server.serve_forever()
51 |
52 | def run():
53 | open_browser() # Comment out this line if you don't want to open a browser
54 | start_server()
55 |
56 | if __name__ == "__main__":
57 | run()
58 |
59 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/serve.py:
--------------------------------------------------------------------------------
1 | """
2 | A helper script for testing your app's local html files, with no robot install.
3 |
4 | Usage:
5 | Run serve.py, a browser will open on a debug page, enter your robot's IP address
6 | and your local pages will be served as if they were on the robot.
7 |
8 | Using a server like this (as opposed to just file:// etc.) is only necessary
9 | if you do ajax calls in your page.
10 | """
11 |
12 | __version__ = "0.0.3"
13 |
14 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
15 | __author__ = 'ekroeger'
16 | __email__ = 'ekroeger@aldebaran.com'
17 |
18 | import os
19 | import threading
20 | import webbrowser
21 | import BaseHTTPServer
22 | import SimpleHTTPServer
23 | import urlparse
24 | import urllib
25 |
26 | USE_SERVER = False
27 |
28 | PORT = 8081
29 |
30 | def open_browser():
31 | """Start a browser after waiting for half a second."""
32 | if USE_SERVER:
33 | def _open_browser():
34 | url = 'http://localhost:%s/debug/index.html' % PORT
35 | webbrowser.open(url)
36 | thread = threading.Timer(0.5, _open_browser)
37 | thread.start()
38 | else:
39 | indexpath = os.path.join(os.getcwd(), "debug/index.html")
40 | url = urlparse.urljoin('file:', urllib.pathname2url(indexpath))
41 | webbrowser.open(url)
42 |
43 | def start_server():
44 | """Start the server."""
45 | if USE_SERVER:
46 | server_address = ("", PORT)
47 | handler_class = SimpleHTTPServer.SimpleHTTPRequestHandler
48 | handler_class.extensions_map['.png'] = 'image/png'
49 | server = BaseHTTPServer.HTTPServer(server_address, handler_class)
50 | server.serve_forever()
51 |
52 | def run():
53 | open_browser() # Comment out this line if you don't want to open a browser
54 | start_server()
55 |
56 | if __name__ == "__main__":
57 | run()
58 |
59 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/serve.py:
--------------------------------------------------------------------------------
1 | """
2 | A helper script for testing your app's local html files, with no robot install.
3 |
4 | Usage:
5 | Run serve.py, a browser will open on a debug page, enter your robot's IP address
6 | and your local pages will be served as if they were on the robot.
7 |
8 | Using a server like this (as opposed to just file:// etc.) is only necessary
9 | if you do ajax calls in your page.
10 | """
11 |
12 | __version__ = "0.0.3"
13 |
14 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
15 | __author__ = 'ekroeger'
16 | __email__ = 'ekroeger@aldebaran.com'
17 |
18 | import os
19 | import threading
20 | import webbrowser
21 | import BaseHTTPServer
22 | import SimpleHTTPServer
23 | import urlparse
24 | import urllib
25 |
26 | USE_SERVER = False
27 |
28 | PORT = 8081
29 |
30 | def open_browser():
31 | """Start a browser after waiting for half a second."""
32 | if USE_SERVER:
33 | def _open_browser():
34 | url = 'http://localhost:%s/debug/index.html' % PORT
35 | webbrowser.open(url)
36 | thread = threading.Timer(0.5, _open_browser)
37 | thread.start()
38 | else:
39 | indexpath = os.path.join(os.getcwd(), "debug/index.html")
40 | url = urlparse.urljoin('file:', urllib.pathname2url(indexpath))
41 | webbrowser.open(url)
42 |
43 | def start_server():
44 | """Start the server."""
45 | if USE_SERVER:
46 | server_address = ("", PORT)
47 | handler_class = SimpleHTTPServer.SimpleHTTPRequestHandler
48 | handler_class.extensions_map['.png'] = 'image/png'
49 | server = BaseHTTPServer.HTTPServer(server_address, handler_class)
50 | server.serve_forever()
51 |
52 | def run():
53 | open_browser() # Comment out this line if you don't want to open a browser
54 | start_server()
55 |
56 | if __name__ == "__main__":
57 | run()
58 |
59 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/serve.py:
--------------------------------------------------------------------------------
1 | """
2 | A helper script for testing your app's local html files, with no robot install.
3 |
4 | Usage:
5 | Run serve.py, a browser will open on a debug page, enter your robot's IP address
6 | and your local pages will be served as if they were on the robot.
7 |
8 | Using a server like this (as opposed to just file:// etc.) is only necessary
9 | if you do ajax calls in your page.
10 | """
11 |
12 | __version__ = "0.0.3"
13 |
14 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
15 | __author__ = 'ekroeger'
16 | __email__ = 'ekroeger@aldebaran.com'
17 |
18 | import os
19 | import threading
20 | import webbrowser
21 | import BaseHTTPServer
22 | import SimpleHTTPServer
23 | import urlparse
24 | import urllib
25 |
26 | USE_SERVER = False
27 |
28 | PORT = 8081
29 |
30 | def open_browser():
31 | """Start a browser after waiting for half a second."""
32 | if USE_SERVER:
33 | def _open_browser():
34 | url = 'http://localhost:%s/debug/index.html' % PORT
35 | webbrowser.open(url)
36 | thread = threading.Timer(0.5, _open_browser)
37 | thread.start()
38 | else:
39 | indexpath = os.path.join(os.getcwd(), "debug/index.html")
40 | url = urlparse.urljoin('file:', urllib.pathname2url(indexpath))
41 | webbrowser.open(url)
42 |
43 | def start_server():
44 | """Start the server."""
45 | if USE_SERVER:
46 | server_address = ("", PORT)
47 | handler_class = SimpleHTTPServer.SimpleHTTPRequestHandler
48 | handler_class.extensions_map['.png'] = 'image/png'
49 | server = BaseHTTPServer.HTTPServer(server_address, handler_class)
50 | server.serve_forever()
51 |
52 | def run():
53 | open_browser() # Comment out this line if you don't want to open a browser
54 | start_server()
55 |
56 | if __name__ == "__main__":
57 | run()
58 |
59 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/scripts/myservice.py:
--------------------------------------------------------------------------------
1 | """
2 | A sample showing how to have a NAOqi service as a Python app.
3 | """
4 |
5 | __version__ = "0.0.3"
6 |
7 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
8 | __author__ = 'YOURNAME'
9 | __email__ = 'YOUREMAIL@aldebaran.com'
10 |
11 |
12 | import qi
13 |
14 | import stk.runner
15 | import stk.events
16 | import stk.services
17 | import stk.logging
18 |
19 | class ALMyService(object):
20 | "NAOqi service example (set/get on a simple value)."
21 | APP_ID = "com.aldebaran.ALMyService"
22 | def __init__(self, qiapp):
23 | # generic activity boilerplate
24 | self.qiapp = qiapp
25 | self.events = stk.events.EventHelper(qiapp.session)
26 | self.s = stk.services.ServiceCache(qiapp.session)
27 | self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
28 | # Internal variables
29 | self.level = 0
30 |
31 | @qi.bind(returnType=qi.Void, paramsType=[qi.Int8])
32 | def set(self, level):
33 | "Set level"
34 | self.level = level
35 |
36 | @qi.bind(returnType=qi.Int8, paramsType=[])
37 | def get(self):
38 | "Get level"
39 | return self.level
40 |
41 | @qi.bind(returnType=qi.Void, paramsType=[])
42 | def reset(self):
43 | "Reset level to default value"
44 | return self.set(0)
45 |
46 | @qi.bind(returnType=qi.Void, paramsType=[])
47 | def stop(self):
48 | "Stop the service."
49 | self.logger.info("ALMyService stopped by user request.")
50 | self.qiapp.stop()
51 |
52 | @qi.nobind
53 | def on_stop(self):
54 | "Cleanup (add yours if needed)"
55 | self.logger.info("ALMyService finished.")
56 |
57 | ####################
58 | # Setup and Run
59 | ####################
60 |
61 | if __name__ == "__main__":
62 | stk.runner.run_service(ALMyService)
63 |
64 |
--------------------------------------------------------------------------------
/templates/python-service/app/scripts/myservice.py:
--------------------------------------------------------------------------------
1 | """
2 | A sample showing how to have a NAOqi service as a Python app.
3 | """
4 |
5 | __version__ = "0.0.3"
6 |
7 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
8 | __author__ = 'YOURNAME'
9 | __email__ = 'YOUREMAIL@aldebaran.com'
10 |
11 |
12 | import qi
13 |
14 | import stk.runner
15 | import stk.events
16 | import stk.services
17 | import stk.logging
18 |
19 | class ALMyService(object):
20 | "NAOqi service example (set/get on a simple value)."
21 | APP_ID = "com.aldebaran.ALMyService"
22 | def __init__(self, qiapp):
23 | # generic activity boilerplate
24 | self.qiapp = qiapp
25 | self.events = stk.events.EventHelper(qiapp.session)
26 | self.s = stk.services.ServiceCache(qiapp.session)
27 | self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
28 | # Internal variables
29 | self.level = 0
30 |
31 | @qi.bind(returnType=qi.Void, paramsType=[qi.Int8])
32 | def set(self, level):
33 | "Set level"
34 | self.level = level
35 |
36 | @qi.bind(returnType=qi.Int8, paramsType=[])
37 | def get(self):
38 | "Get level"
39 | return self.level
40 |
41 | @qi.bind(returnType=qi.Void, paramsType=[])
42 | def reset(self):
43 | "Reset level to default value"
44 | return self.set(0)
45 |
46 | @qi.bind(returnType=qi.Void, paramsType=[])
47 | def stop(self):
48 | "Stop the service."
49 | self.logger.info("ALMyService stopped by user request.")
50 | self.qiapp.stop()
51 |
52 | @qi.nobind
53 | def on_stop(self):
54 | "Cleanup (add yours if needed)"
55 | self.logger.info("ALMyService finished.")
56 |
57 | ####################
58 | # Setup and Run
59 | ####################
60 |
61 | if __name__ == "__main__":
62 | stk.runner.run_service(ALMyService)
63 |
64 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/scripts/myservice.py:
--------------------------------------------------------------------------------
1 | """
2 | A sample showing how to have a NAOqi service as a Python app.
3 | """
4 |
5 | __version__ = "0.0.3"
6 |
7 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
8 | __author__ = 'ekroeger'
9 | __email__ = 'ekroeger@aldebaran.com'
10 |
11 |
12 | import qi
13 |
14 | import stk.runner
15 | import stk.events
16 | import stk.services
17 | import stk.logging
18 |
19 | class ALMyService(object):
20 | "NAOqi service example (set/get on a simple value)."
21 | APP_ID = "com.aldebaran.ALMyService"
22 | def __init__(self, qiapp):
23 | # generic activity boilerplate
24 | self.qiapp = qiapp
25 | self.events = stk.events.EventHelper(qiapp.session)
26 | self.s = stk.services.ServiceCache(qiapp.session)
27 | self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
28 | # Internal variables
29 | self.level = 0
30 |
31 | @qi.bind(returnType=qi.Void, paramsType=[qi.Int8])
32 | def set(self, level):
33 | "Set level"
34 | self.level = level
35 |
36 | @qi.bind(returnType=qi.Int8, paramsType=[])
37 | def get(self):
38 | "Get level"
39 | return self.level
40 |
41 | @qi.bind(returnType=qi.Void, paramsType=[])
42 | def reset(self):
43 | "Reset level to default value"
44 | return self.set(0)
45 |
46 | @qi.bind(returnType=qi.Void, paramsType=[])
47 | def stop(self):
48 | "Stop the service."
49 | self.logger.info("ALMyService stopped by user request.")
50 | self.qiapp.stop()
51 |
52 | @qi.nobind
53 | def on_stop(self):
54 | "Cleanup (add yours if needed)"
55 | self.logger.info("ALMyService finished.")
56 |
57 | ####################
58 | # Setup and Run
59 | ####################
60 |
61 | if __name__ == "__main__":
62 | stk.runner.run_service(ALMyService)
63 |
64 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/scripts/myservice.py:
--------------------------------------------------------------------------------
1 | """
2 | A sample showing how to have a NAOqi service as a Python app.
3 | """
4 |
5 | __version__ = "0.0.3"
6 |
7 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
8 | __author__ = 'ekroeger'
9 | __email__ = 'ekroeger@aldebaran.com'
10 |
11 |
12 | import qi
13 |
14 | import stk.runner
15 | import stk.events
16 | import stk.services
17 | import stk.logging
18 |
19 | class ALMyService(object):
20 | "NAOqi service example (set/get on a simple value)."
21 | APP_ID = "com.aldebaran.ALMyService"
22 | def __init__(self, qiapp):
23 | # generic activity boilerplate
24 | self.qiapp = qiapp
25 | self.events = stk.events.EventHelper(qiapp.session)
26 | self.s = stk.services.ServiceCache(qiapp.session)
27 | self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
28 | # Internal variables
29 | self.level = 0
30 |
31 | @qi.bind(returnType=qi.Void, paramsType=[qi.Int8])
32 | def set(self, level):
33 | "Set level"
34 | self.level = level
35 |
36 | @qi.bind(returnType=qi.Int8, paramsType=[])
37 | def get(self):
38 | "Get level"
39 | return self.level
40 |
41 | @qi.bind(returnType=qi.Void, paramsType=[])
42 | def reset(self):
43 | "Reset level to default value"
44 | return self.set(0)
45 |
46 | @qi.bind(returnType=qi.Void, paramsType=[])
47 | def stop(self):
48 | "Stop the service."
49 | self.logger.info("ALMyService stopped by user request.")
50 | self.qiapp.stop()
51 |
52 | @qi.nobind
53 | def on_stop(self):
54 | "Cleanup (add yours if needed)"
55 | self.logger.info("ALMyService finished.")
56 |
57 | ####################
58 | # Setup and Run
59 | ####################
60 |
61 | if __name__ == "__main__":
62 | stk.runner.run_service(ALMyService)
63 |
64 |
--------------------------------------------------------------------------------
/doc/services.md:
--------------------------------------------------------------------------------
1 |
2 | Clarifying the "service" terminology
3 | =======
4 |
5 | There are two different entities that are called "services":
6 |
7 | * **NAOqi services** (also called "modules"), that expose an API and are registered to the ServiceDirectory. You can call them with qicli, subscribe to their signals, etc.
8 |
9 | * **systemd services**, that are standalone executables packaged in an Application Package, declared in it's manifest with a `` tag. These are managed by ALServiceManager, who can start and stop them (they will have their own process). For clarity's sake, these are called "**Executables**" in this doc.
10 |
11 | The confusion between the two is increased by the fact that a common pattern is to write an executable whose sole purpose is to run a NAOqi service, and sometimes to identify both with the same name (e.g. both are called “ALFuchsiaBallTracker”).
12 |
13 | Ways of using them in an app:
14 |
15 | * Run a standalone executable during your app, possibly as the only content. This is demonstrated in the `pythonapp` template.
16 |
17 | * Run a NAOqi service during your app (packaged in an executable), but only while the app is running -> this is how `service-tabletpage` is built.
18 |
19 | * Package a NAOqi service running all the time -> this wastes resources, and risks causing hard-to-find bugs, so should only be used for system apps that *really* need to do so.
20 |
21 |
22 | qi.Application
23 | =======
24 |
25 |
26 | robot_runner**`.init()`** returns a QiApplication object, the same you would get by calling `qi.Application()̀`.
27 |
28 | When your python script is packaged in an application, it should be declared in the manifest with a --qi-url parameter:
29 |
30 | ``
31 | ` `
32 | ` `
33 |
34 | However, you can also execute that script directly, locally on your computer (python main.py), or from your favourite editor.
35 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/scripts/stk/logging.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.logging.py
3 |
4 | Utility library for logging with qi.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 | import functools
14 | import traceback
15 |
16 | import qi
17 |
18 |
19 | def get_logger(session, app_id):
20 | """Returns a qi logger object."""
21 | logger = qi.logging.Logger(app_id)
22 | try:
23 | qicore = qi.module("qicore")
24 | log_manager = session.service("LogManager")
25 | provider = qicore.createObject("LogProvider", log_manager)
26 | log_manager.addProvider(provider)
27 | except RuntimeError:
28 | # no qicore, we're not running on a robot, it doesn't matter
29 | pass
30 | except AttributeError:
31 | # old version of NAOqi - logging will probably not work.
32 | pass
33 | return logger
34 |
35 |
36 | def log_exceptions(func):
37 | """Catches all exceptions in decorated method, and prints them.
38 |
39 | Attached function must be on an object with a "logger" member.
40 | """
41 | @functools.wraps(func)
42 | def wrapped(self, *args):
43 | try:
44 | return func(self, *args)
45 | except Exception as exc:
46 | self.logger.error(traceback.format_exc())
47 | raise exc
48 | return wrapped
49 |
50 |
51 | def log_exceptions_and_return(default_value):
52 | """If an exception occurs, print it and return default_value.
53 |
54 | Attached function must be on an object with a "logger" member.
55 | """
56 | def decorator(func):
57 | @functools.wraps(func)
58 | def wrapped(self, *args):
59 | try:
60 | return func(self, *args)
61 | except Exception:
62 | self.logger.error(traceback.format_exc())
63 | return default_value
64 | return wrapped
65 | return decorator
66 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/scripts/stk/logging.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.logging.py
3 |
4 | Utility library for logging with qi.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 | import functools
14 | import traceback
15 |
16 | import qi
17 |
18 |
19 | def get_logger(session, app_id):
20 | """Returns a qi logger object."""
21 | logger = qi.logging.Logger(app_id)
22 | try:
23 | qicore = qi.module("qicore")
24 | log_manager = session.service("LogManager")
25 | provider = qicore.createObject("LogProvider", log_manager)
26 | log_manager.addProvider(provider)
27 | except RuntimeError:
28 | # no qicore, we're not running on a robot, it doesn't matter
29 | pass
30 | except AttributeError:
31 | # old version of NAOqi - logging will probably not work.
32 | pass
33 | return logger
34 |
35 |
36 | def log_exceptions(func):
37 | """Catches all exceptions in decorated method, and prints them.
38 |
39 | Attached function must be on an object with a "logger" member.
40 | """
41 | @functools.wraps(func)
42 | def wrapped(self, *args):
43 | try:
44 | return func(self, *args)
45 | except Exception as exc:
46 | self.logger.error(traceback.format_exc())
47 | raise exc
48 | return wrapped
49 |
50 |
51 | def log_exceptions_and_return(default_value):
52 | """If an exception occurs, print it and return default_value.
53 |
54 | Attached function must be on an object with a "logger" member.
55 | """
56 | def decorator(func):
57 | @functools.wraps(func)
58 | def wrapped(self, *args):
59 | try:
60 | return func(self, *args)
61 | except Exception:
62 | self.logger.error(traceback.format_exc())
63 | return default_value
64 | return wrapped
65 | return decorator
66 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/scripts/stk/logging.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.logging.py
3 |
4 | Utility library for logging with qi.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 | import functools
14 | import traceback
15 |
16 | import qi
17 |
18 |
19 | def get_logger(session, app_id):
20 | """Returns a qi logger object."""
21 | logger = qi.logging.Logger(app_id)
22 | try:
23 | qicore = qi.module("qicore")
24 | log_manager = session.service("LogManager")
25 | provider = qicore.createObject("LogProvider", log_manager)
26 | log_manager.addProvider(provider)
27 | except RuntimeError:
28 | # no qicore, we're not running on a robot, it doesn't matter
29 | pass
30 | except AttributeError:
31 | # old version of NAOqi - logging will probably not work.
32 | pass
33 | return logger
34 |
35 |
36 | def log_exceptions(func):
37 | """Catches all exceptions in decorated method, and prints them.
38 |
39 | Attached function must be on an object with a "logger" member.
40 | """
41 | @functools.wraps(func)
42 | def wrapped(self, *args):
43 | try:
44 | return func(self, *args)
45 | except Exception as exc:
46 | self.logger.error(traceback.format_exc())
47 | raise exc
48 | return wrapped
49 |
50 |
51 | def log_exceptions_and_return(default_value):
52 | """If an exception occurs, print it and return default_value.
53 |
54 | Attached function must be on an object with a "logger" member.
55 | """
56 | def decorator(func):
57 | @functools.wraps(func)
58 | def wrapped(self, *args):
59 | try:
60 | return func(self, *args)
61 | except Exception:
62 | self.logger.error(traceback.format_exc())
63 | return default_value
64 | return wrapped
65 | return decorator
66 |
--------------------------------------------------------------------------------
/templates/python-service/app/scripts/stk/logging.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.logging.py
3 |
4 | Utility library for logging with qi.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 | import functools
14 | import traceback
15 |
16 | import qi
17 |
18 |
19 | def get_logger(session, app_id):
20 | """Returns a qi logger object."""
21 | logger = qi.logging.Logger(app_id)
22 | try:
23 | qicore = qi.module("qicore")
24 | log_manager = session.service("LogManager")
25 | provider = qicore.createObject("LogProvider", log_manager)
26 | log_manager.addProvider(provider)
27 | except RuntimeError:
28 | # no qicore, we're not running on a robot, it doesn't matter
29 | pass
30 | except AttributeError:
31 | # old version of NAOqi - logging will probably not work.
32 | pass
33 | return logger
34 |
35 |
36 | def log_exceptions(func):
37 | """Catches all exceptions in decorated method, and prints them.
38 |
39 | Attached function must be on an object with a "logger" member.
40 | """
41 | @functools.wraps(func)
42 | def wrapped(self, *args):
43 | try:
44 | return func(self, *args)
45 | except Exception as exc:
46 | self.logger.error(traceback.format_exc())
47 | raise exc
48 | return wrapped
49 |
50 |
51 | def log_exceptions_and_return(default_value):
52 | """If an exception occurs, print it and return default_value.
53 |
54 | Attached function must be on an object with a "logger" member.
55 | """
56 | def decorator(func):
57 | @functools.wraps(func)
58 | def wrapped(self, *args):
59 | try:
60 | return func(self, *args)
61 | except Exception:
62 | self.logger.error(traceback.format_exc())
63 | return default_value
64 | return wrapped
65 | return decorator
66 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/scripts/stk/logging.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.logging.py
3 |
4 | Utility library for logging with qi.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 | import functools
14 | import traceback
15 |
16 | import qi
17 |
18 |
19 | def get_logger(session, app_id):
20 | """Returns a qi logger object."""
21 | logger = qi.logging.Logger(app_id)
22 | try:
23 | qicore = qi.module("qicore")
24 | log_manager = session.service("LogManager")
25 | provider = qicore.createObject("LogProvider", log_manager)
26 | log_manager.addProvider(provider)
27 | except RuntimeError:
28 | # no qicore, we're not running on a robot, it doesn't matter
29 | pass
30 | except AttributeError:
31 | # old version of NAOqi - logging will probably not work.
32 | pass
33 | return logger
34 |
35 |
36 | def log_exceptions(func):
37 | """Catches all exceptions in decorated method, and prints them.
38 |
39 | Attached function must be on an object with a "logger" member.
40 | """
41 | @functools.wraps(func)
42 | def wrapped(self, *args):
43 | try:
44 | return func(self, *args)
45 | except Exception as exc:
46 | self.logger.error(traceback.format_exc())
47 | raise exc
48 | return wrapped
49 |
50 |
51 | def log_exceptions_and_return(default_value):
52 | """If an exception occurs, print it and return default_value.
53 |
54 | Attached function must be on an object with a "logger" member.
55 | """
56 | def decorator(func):
57 | @functools.wraps(func)
58 | def wrapped(self, *args):
59 | try:
60 | return func(self, *args)
61 | except Exception:
62 | self.logger.error(traceback.format_exc())
63 | return default_value
64 | return wrapped
65 | return decorator
66 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/scripts/stk/logging.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.logging.py
3 |
4 | Utility library for logging with qi.
5 | """
6 |
7 | __version__ = "0.1.2"
8 |
9 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
10 | __author__ = 'ekroeger'
11 | __email__ = 'ekroeger@aldebaran.com'
12 |
13 | import functools
14 | import traceback
15 |
16 | import qi
17 |
18 |
19 | def get_logger(session, app_id):
20 | """Returns a qi logger object."""
21 | logger = qi.logging.Logger(app_id)
22 | try:
23 | qicore = qi.module("qicore")
24 | log_manager = session.service("LogManager")
25 | provider = qicore.createObject("LogProvider", log_manager)
26 | log_manager.addProvider(provider)
27 | except RuntimeError:
28 | # no qicore, we're not running on a robot, it doesn't matter
29 | pass
30 | except AttributeError:
31 | # old version of NAOqi - logging will probably not work.
32 | pass
33 | return logger
34 |
35 |
36 | def log_exceptions(func):
37 | """Catches all exceptions in decorated method, and prints them.
38 |
39 | Attached function must be on an object with a "logger" member.
40 | """
41 | @functools.wraps(func)
42 | def wrapped(self, *args):
43 | try:
44 | return func(self, *args)
45 | except Exception as exc:
46 | self.logger.error(traceback.format_exc())
47 | raise exc
48 | return wrapped
49 |
50 |
51 | def log_exceptions_and_return(default_value):
52 | """If an exception occurs, print it and return default_value.
53 |
54 | Attached function must be on an object with a "logger" member.
55 | """
56 | def decorator(func):
57 | @functools.wraps(func)
58 | def wrapped(self, *args):
59 | try:
60 | return func(self, *args)
61 | except Exception:
62 | self.logger.error(traceback.format_exc())
63 | return default_value
64 | return wrapped
65 | return decorator
66 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/scripts/main.py:
--------------------------------------------------------------------------------
1 | """
2 | A sample showing how to make a Python script as an app.
3 | """
4 |
5 | __version__ = "0.0.8"
6 |
7 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
8 | __author__ = 'YOURNAME'
9 | __email__ = 'YOUREMAIL@aldebaran.com'
10 |
11 | import stk.runner
12 | import stk.events
13 | import stk.services
14 | import stk.logging
15 |
16 | class Activity(object):
17 | "A sample standalone app, that demonstrates simple Python usage"
18 | APP_ID = "com.aldebaran.pythonapp"
19 | def __init__(self, qiapp):
20 | self.qiapp = qiapp
21 | self.events = stk.events.EventHelper(qiapp.session)
22 | self.s = stk.services.ServiceCache(qiapp.session)
23 | self.logger = stk.logging.get_logger(qiapp.session, self.APP_ID)
24 |
25 | def on_touched(self, *args):
26 | "Callback for tablet touched."
27 | if args:
28 | self.events.disconnect("ALTabletService.onTouchDown")
29 | self.logger.info("Tablet touched: " + str(args))
30 | self.s.ALTextToSpeech.say("Yay!")
31 | self.stop()
32 |
33 | def on_start(self):
34 | "Ask to be touched, waits, and exits."
35 | # Two ways of waiting for events
36 | # 1) block until it's called
37 | self.s.ALTextToSpeech.say("Touch my forehead.")
38 | self.logger.warning("Listening for touch...")
39 | while not self.events.wait_for("FrontTactilTouched"):
40 | pass
41 |
42 | # 2) explicitly connect a callback
43 | if self.s.ALTabletService:
44 | self.events.connect("ALTabletService.onTouchDown", self.on_touched)
45 | self.s.ALTextToSpeech.say("okay, now touch my tablet.")
46 | # (this allows to simltaneously speak and watch an event)
47 | else:
48 | self.s.ALTextToSpeech.say("touch my tablet ... oh. " + \
49 | "I don't haave one.")
50 | self.stop()
51 |
52 | def stop(self):
53 | "Standard way of stopping the application."
54 | self.qiapp.stop()
55 |
56 | def on_stop(self):
57 | "Cleanup"
58 | self.logger.info("Application finished.")
59 | self.events.clear()
60 |
61 | if __name__ == "__main__":
62 | stk.runner.run_activity(Activity)
63 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/testrun/behavior.xar:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | media/images/box/root.png
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | ../dialog-service/dialog-service.dlg
20 | media/images/box/box-dialog.png
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/debug/js/jquery.cookie.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Cookie Plugin v1.4.1
3 | * https://github.com/carhartl/jquery-cookie
4 | *
5 | * Copyright 2006, 2014 Klaus Hartl
6 | * Released under the MIT license
7 | */
8 | (function (factory) {
9 | if (typeof define === 'function' && define.amd) {
10 | // AMD (Register as an anonymous module)
11 | define(['jquery'], factory);
12 | } else if (typeof exports === 'object') {
13 | // Node/CommonJS
14 | module.exports = factory(require('jquery'));
15 | } else {
16 | // Browser globals
17 | factory(jQuery);
18 | }
19 | }(function ($) {
20 |
21 | var pluses = /\+/g;
22 |
23 | function encode(s) {
24 | return config.raw ? s : encodeURIComponent(s);
25 | }
26 |
27 | function decode(s) {
28 | return config.raw ? s : decodeURIComponent(s);
29 | }
30 |
31 | function stringifyCookieValue(value) {
32 | return encode(config.json ? JSON.stringify(value) : String(value));
33 | }
34 |
35 | function parseCookieValue(s) {
36 | if (s.indexOf('"') === 0) {
37 | // This is a quoted cookie as according to RFC2068, unescape...
38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
39 | }
40 |
41 | try {
42 | // Replace server-side written pluses with spaces.
43 | // If we can't decode the cookie, ignore it, it's unusable.
44 | // If we can't parse the cookie, ignore it, it's unusable.
45 | s = decodeURIComponent(s.replace(pluses, ' '));
46 | return config.json ? JSON.parse(s) : s;
47 | } catch(e) {}
48 | }
49 |
50 | function read(s, converter) {
51 | var value = config.raw ? s : parseCookieValue(s);
52 | return $.isFunction(converter) ? converter(value) : value;
53 | }
54 |
55 | var config = $.cookie = function (key, value, options) {
56 |
57 | // Write
58 |
59 | if (arguments.length > 1 && !$.isFunction(value)) {
60 | options = $.extend({}, config.defaults, options);
61 |
62 | if (typeof options.expires === 'number') {
63 | var days = options.expires, t = options.expires = new Date();
64 | t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
65 | }
66 |
67 | return (document.cookie = [
68 | encode(key), '=', stringifyCookieValue(value),
69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
70 | options.path ? '; path=' + options.path : '',
71 | options.domain ? '; domain=' + options.domain : '',
72 | options.secure ? '; secure' : ''
73 | ].join(''));
74 | }
75 |
76 | // Read
77 |
78 | var result = key ? undefined : {},
79 | // To prevent the for loop in the first place assign an empty array
80 | // in case there are no cookies at all. Also prevents odd result when
81 | // calling $.cookie().
82 | cookies = document.cookie ? document.cookie.split('; ') : [],
83 | i = 0,
84 | l = cookies.length;
85 |
86 | for (; i < l; i++) {
87 | var parts = cookies[i].split('='),
88 | name = decode(parts.shift()),
89 | cookie = parts.join('=');
90 |
91 | if (key === name) {
92 | // If second argument (value) is a function it's a converter...
93 | result = read(cookie, value);
94 | break;
95 | }
96 |
97 | // Prevent storing a cookie that we couldn't decode.
98 | if (!key && (cookie = read(cookie)) !== undefined) {
99 | result[name] = cookie;
100 | }
101 | }
102 |
103 | return result;
104 | };
105 |
106 | config.defaults = {};
107 |
108 | $.removeCookie = function (key, options) {
109 | // Must not alter options, thus extending a fresh object...
110 | $.cookie(key, '', $.extend({}, options, { expires: -1 }));
111 | return !$.cookie(key);
112 | };
113 |
114 | }));
115 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/debug/js/jquery.cookie.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Cookie Plugin v1.4.1
3 | * https://github.com/carhartl/jquery-cookie
4 | *
5 | * Copyright 2006, 2014 Klaus Hartl
6 | * Released under the MIT license
7 | */
8 | (function (factory) {
9 | if (typeof define === 'function' && define.amd) {
10 | // AMD (Register as an anonymous module)
11 | define(['jquery'], factory);
12 | } else if (typeof exports === 'object') {
13 | // Node/CommonJS
14 | module.exports = factory(require('jquery'));
15 | } else {
16 | // Browser globals
17 | factory(jQuery);
18 | }
19 | }(function ($) {
20 |
21 | var pluses = /\+/g;
22 |
23 | function encode(s) {
24 | return config.raw ? s : encodeURIComponent(s);
25 | }
26 |
27 | function decode(s) {
28 | return config.raw ? s : decodeURIComponent(s);
29 | }
30 |
31 | function stringifyCookieValue(value) {
32 | return encode(config.json ? JSON.stringify(value) : String(value));
33 | }
34 |
35 | function parseCookieValue(s) {
36 | if (s.indexOf('"') === 0) {
37 | // This is a quoted cookie as according to RFC2068, unescape...
38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
39 | }
40 |
41 | try {
42 | // Replace server-side written pluses with spaces.
43 | // If we can't decode the cookie, ignore it, it's unusable.
44 | // If we can't parse the cookie, ignore it, it's unusable.
45 | s = decodeURIComponent(s.replace(pluses, ' '));
46 | return config.json ? JSON.parse(s) : s;
47 | } catch(e) {}
48 | }
49 |
50 | function read(s, converter) {
51 | var value = config.raw ? s : parseCookieValue(s);
52 | return $.isFunction(converter) ? converter(value) : value;
53 | }
54 |
55 | var config = $.cookie = function (key, value, options) {
56 |
57 | // Write
58 |
59 | if (arguments.length > 1 && !$.isFunction(value)) {
60 | options = $.extend({}, config.defaults, options);
61 |
62 | if (typeof options.expires === 'number') {
63 | var days = options.expires, t = options.expires = new Date();
64 | t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
65 | }
66 |
67 | return (document.cookie = [
68 | encode(key), '=', stringifyCookieValue(value),
69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
70 | options.path ? '; path=' + options.path : '',
71 | options.domain ? '; domain=' + options.domain : '',
72 | options.secure ? '; secure' : ''
73 | ].join(''));
74 | }
75 |
76 | // Read
77 |
78 | var result = key ? undefined : {},
79 | // To prevent the for loop in the first place assign an empty array
80 | // in case there are no cookies at all. Also prevents odd result when
81 | // calling $.cookie().
82 | cookies = document.cookie ? document.cookie.split('; ') : [],
83 | i = 0,
84 | l = cookies.length;
85 |
86 | for (; i < l; i++) {
87 | var parts = cookies[i].split('='),
88 | name = decode(parts.shift()),
89 | cookie = parts.join('=');
90 |
91 | if (key === name) {
92 | // If second argument (value) is a function it's a converter...
93 | result = read(cookie, value);
94 | break;
95 | }
96 |
97 | // Prevent storing a cookie that we couldn't decode.
98 | if (!key && (cookie = read(cookie)) !== undefined) {
99 | result[name] = cookie;
100 | }
101 | }
102 |
103 | return result;
104 | };
105 |
106 | config.defaults = {};
107 |
108 | $.removeCookie = function (key, options) {
109 | // Must not alter options, thus extending a fresh object...
110 | $.cookie(key, '', $.extend({}, options, { expires: -1 }));
111 | return !$.cookie(key);
112 | };
113 |
114 | }));
115 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/debug/js/jquery.cookie.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Cookie Plugin v1.4.1
3 | * https://github.com/carhartl/jquery-cookie
4 | *
5 | * Copyright 2006, 2014 Klaus Hartl
6 | * Released under the MIT license
7 | */
8 | (function (factory) {
9 | if (typeof define === 'function' && define.amd) {
10 | // AMD (Register as an anonymous module)
11 | define(['jquery'], factory);
12 | } else if (typeof exports === 'object') {
13 | // Node/CommonJS
14 | module.exports = factory(require('jquery'));
15 | } else {
16 | // Browser globals
17 | factory(jQuery);
18 | }
19 | }(function ($) {
20 |
21 | var pluses = /\+/g;
22 |
23 | function encode(s) {
24 | return config.raw ? s : encodeURIComponent(s);
25 | }
26 |
27 | function decode(s) {
28 | return config.raw ? s : decodeURIComponent(s);
29 | }
30 |
31 | function stringifyCookieValue(value) {
32 | return encode(config.json ? JSON.stringify(value) : String(value));
33 | }
34 |
35 | function parseCookieValue(s) {
36 | if (s.indexOf('"') === 0) {
37 | // This is a quoted cookie as according to RFC2068, unescape...
38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
39 | }
40 |
41 | try {
42 | // Replace server-side written pluses with spaces.
43 | // If we can't decode the cookie, ignore it, it's unusable.
44 | // If we can't parse the cookie, ignore it, it's unusable.
45 | s = decodeURIComponent(s.replace(pluses, ' '));
46 | return config.json ? JSON.parse(s) : s;
47 | } catch(e) {}
48 | }
49 |
50 | function read(s, converter) {
51 | var value = config.raw ? s : parseCookieValue(s);
52 | return $.isFunction(converter) ? converter(value) : value;
53 | }
54 |
55 | var config = $.cookie = function (key, value, options) {
56 |
57 | // Write
58 |
59 | if (arguments.length > 1 && !$.isFunction(value)) {
60 | options = $.extend({}, config.defaults, options);
61 |
62 | if (typeof options.expires === 'number') {
63 | var days = options.expires, t = options.expires = new Date();
64 | t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
65 | }
66 |
67 | return (document.cookie = [
68 | encode(key), '=', stringifyCookieValue(value),
69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
70 | options.path ? '; path=' + options.path : '',
71 | options.domain ? '; domain=' + options.domain : '',
72 | options.secure ? '; secure' : ''
73 | ].join(''));
74 | }
75 |
76 | // Read
77 |
78 | var result = key ? undefined : {},
79 | // To prevent the for loop in the first place assign an empty array
80 | // in case there are no cookies at all. Also prevents odd result when
81 | // calling $.cookie().
82 | cookies = document.cookie ? document.cookie.split('; ') : [],
83 | i = 0,
84 | l = cookies.length;
85 |
86 | for (; i < l; i++) {
87 | var parts = cookies[i].split('='),
88 | name = decode(parts.shift()),
89 | cookie = parts.join('=');
90 |
91 | if (key === name) {
92 | // If second argument (value) is a function it's a converter...
93 | result = read(cookie, value);
94 | break;
95 | }
96 |
97 | // Prevent storing a cookie that we couldn't decode.
98 | if (!key && (cookie = read(cookie)) !== undefined) {
99 | result[name] = cookie;
100 | }
101 | }
102 |
103 | return result;
104 | };
105 |
106 | config.defaults = {};
107 |
108 | $.removeCookie = function (key, options) {
109 | // Must not alter options, thus extending a fresh object...
110 | $.cookie(key, '', $.extend({}, options, { expires: -1 }));
111 | return !$.cookie(key);
112 | };
113 |
114 | }));
115 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/debug/js/jquery.cookie.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Cookie Plugin v1.4.1
3 | * https://github.com/carhartl/jquery-cookie
4 | *
5 | * Copyright 2006, 2014 Klaus Hartl
6 | * Released under the MIT license
7 | */
8 | (function (factory) {
9 | if (typeof define === 'function' && define.amd) {
10 | // AMD (Register as an anonymous module)
11 | define(['jquery'], factory);
12 | } else if (typeof exports === 'object') {
13 | // Node/CommonJS
14 | module.exports = factory(require('jquery'));
15 | } else {
16 | // Browser globals
17 | factory(jQuery);
18 | }
19 | }(function ($) {
20 |
21 | var pluses = /\+/g;
22 |
23 | function encode(s) {
24 | return config.raw ? s : encodeURIComponent(s);
25 | }
26 |
27 | function decode(s) {
28 | return config.raw ? s : decodeURIComponent(s);
29 | }
30 |
31 | function stringifyCookieValue(value) {
32 | return encode(config.json ? JSON.stringify(value) : String(value));
33 | }
34 |
35 | function parseCookieValue(s) {
36 | if (s.indexOf('"') === 0) {
37 | // This is a quoted cookie as according to RFC2068, unescape...
38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
39 | }
40 |
41 | try {
42 | // Replace server-side written pluses with spaces.
43 | // If we can't decode the cookie, ignore it, it's unusable.
44 | // If we can't parse the cookie, ignore it, it's unusable.
45 | s = decodeURIComponent(s.replace(pluses, ' '));
46 | return config.json ? JSON.parse(s) : s;
47 | } catch(e) {}
48 | }
49 |
50 | function read(s, converter) {
51 | var value = config.raw ? s : parseCookieValue(s);
52 | return $.isFunction(converter) ? converter(value) : value;
53 | }
54 |
55 | var config = $.cookie = function (key, value, options) {
56 |
57 | // Write
58 |
59 | if (arguments.length > 1 && !$.isFunction(value)) {
60 | options = $.extend({}, config.defaults, options);
61 |
62 | if (typeof options.expires === 'number') {
63 | var days = options.expires, t = options.expires = new Date();
64 | t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
65 | }
66 |
67 | return (document.cookie = [
68 | encode(key), '=', stringifyCookieValue(value),
69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
70 | options.path ? '; path=' + options.path : '',
71 | options.domain ? '; domain=' + options.domain : '',
72 | options.secure ? '; secure' : ''
73 | ].join(''));
74 | }
75 |
76 | // Read
77 |
78 | var result = key ? undefined : {},
79 | // To prevent the for loop in the first place assign an empty array
80 | // in case there are no cookies at all. Also prevents odd result when
81 | // calling $.cookie().
82 | cookies = document.cookie ? document.cookie.split('; ') : [],
83 | i = 0,
84 | l = cookies.length;
85 |
86 | for (; i < l; i++) {
87 | var parts = cookies[i].split('='),
88 | name = decode(parts.shift()),
89 | cookie = parts.join('=');
90 |
91 | if (key === name) {
92 | // If second argument (value) is a function it's a converter...
93 | result = read(cookie, value);
94 | break;
95 | }
96 |
97 | // Prevent storing a cookie that we couldn't decode.
98 | if (!key && (cookie = read(cookie)) !== undefined) {
99 | result[name] = cookie;
100 | }
101 | }
102 |
103 | return result;
104 | };
105 |
106 | config.defaults = {};
107 |
108 | $.removeCookie = function (key, options) {
109 | // Must not alter options, thus extending a fresh object...
110 | $.cookie(key, '', $.extend({}, options, { expires: -1 }));
111 | return !$.cookie(key);
112 | };
113 |
114 | }));
115 |
--------------------------------------------------------------------------------
/templates/simple-webpage-nao/debug/js/jquery.cookie.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * jQuery Cookie Plugin v1.4.1
3 | * https://github.com/carhartl/jquery-cookie
4 | *
5 | * Copyright 2006, 2014 Klaus Hartl
6 | * Released under the MIT license
7 | */
8 | (function (factory) {
9 | if (typeof define === 'function' && define.amd) {
10 | // AMD (Register as an anonymous module)
11 | define(['jquery'], factory);
12 | } else if (typeof exports === 'object') {
13 | // Node/CommonJS
14 | module.exports = factory(require('jquery'));
15 | } else {
16 | // Browser globals
17 | factory(jQuery);
18 | }
19 | }(function ($) {
20 |
21 | var pluses = /\+/g;
22 |
23 | function encode(s) {
24 | return config.raw ? s : encodeURIComponent(s);
25 | }
26 |
27 | function decode(s) {
28 | return config.raw ? s : decodeURIComponent(s);
29 | }
30 |
31 | function stringifyCookieValue(value) {
32 | return encode(config.json ? JSON.stringify(value) : String(value));
33 | }
34 |
35 | function parseCookieValue(s) {
36 | if (s.indexOf('"') === 0) {
37 | // This is a quoted cookie as according to RFC2068, unescape...
38 | s = s.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
39 | }
40 |
41 | try {
42 | // Replace server-side written pluses with spaces.
43 | // If we can't decode the cookie, ignore it, it's unusable.
44 | // If we can't parse the cookie, ignore it, it's unusable.
45 | s = decodeURIComponent(s.replace(pluses, ' '));
46 | return config.json ? JSON.parse(s) : s;
47 | } catch(e) {}
48 | }
49 |
50 | function read(s, converter) {
51 | var value = config.raw ? s : parseCookieValue(s);
52 | return $.isFunction(converter) ? converter(value) : value;
53 | }
54 |
55 | var config = $.cookie = function (key, value, options) {
56 |
57 | // Write
58 |
59 | if (arguments.length > 1 && !$.isFunction(value)) {
60 | options = $.extend({}, config.defaults, options);
61 |
62 | if (typeof options.expires === 'number') {
63 | var days = options.expires, t = options.expires = new Date();
64 | t.setMilliseconds(t.getMilliseconds() + days * 864e+5);
65 | }
66 |
67 | return (document.cookie = [
68 | encode(key), '=', stringifyCookieValue(value),
69 | options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
70 | options.path ? '; path=' + options.path : '',
71 | options.domain ? '; domain=' + options.domain : '',
72 | options.secure ? '; secure' : ''
73 | ].join(''));
74 | }
75 |
76 | // Read
77 |
78 | var result = key ? undefined : {},
79 | // To prevent the for loop in the first place assign an empty array
80 | // in case there are no cookies at all. Also prevents odd result when
81 | // calling $.cookie().
82 | cookies = document.cookie ? document.cookie.split('; ') : [],
83 | i = 0,
84 | l = cookies.length;
85 |
86 | for (; i < l; i++) {
87 | var parts = cookies[i].split('='),
88 | name = decode(parts.shift()),
89 | cookie = parts.join('=');
90 |
91 | if (key === name) {
92 | // If second argument (value) is a function it's a converter...
93 | result = read(cookie, value);
94 | break;
95 | }
96 |
97 | // Prevent storing a cookie that we couldn't decode.
98 | if (!key && (cookie = read(cookie)) !== undefined) {
99 | result[name] = cookie;
100 | }
101 | }
102 |
103 | return result;
104 | };
105 |
106 | config.defaults = {};
107 |
108 | $.removeCookie = function (key, options) {
109 | // Must not alter options, thus extending a fresh object...
110 | $.cookie(key, '', $.extend({}, options, { expires: -1 }));
111 | return !$.cookie(key);
112 | };
113 |
114 | }));
115 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/behavior.xar:
--------------------------------------------------------------------------------
1 | media/images/box/root.pngmedia/images/box/root.png
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/behavior.xar:
--------------------------------------------------------------------------------
1 | media/images/box/root.pngmedia/images/box/root.png
--------------------------------------------------------------------------------
/templates/app-with-tablet/testrun.py:
--------------------------------------------------------------------------------
1 | """
2 | A test runner for a NAOqi service (to test the service packaged in the app)
3 |
4 | Edit it to set your robot's IP to run it (or use arv etc.)
5 |
6 | So far it's pretty hard-coded
7 | """
8 |
9 | __version__ = "0.0.1"
10 |
11 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
12 | __author__ = 'ekroeger'
13 | __email__ = 'ekroeger@aldebaran.com'
14 |
15 |
16 | import subprocess
17 | import time
18 | import sys
19 | import traceback
20 |
21 | import qi
22 |
23 | #########################################
24 | # Helper base class
25 | #########################################
26 |
27 | class ServiceTester:
28 | _app = None
29 | _testresults = []
30 |
31 | @classmethod
32 | def configure(cls, robot):
33 | sys.argv.extend(["--qi-url", robot])
34 | cls.robot = robot
35 | cls._app = qi.Application()
36 | cls._app.start()
37 |
38 | @classmethod
39 | def recap(cls):
40 | succeeded = 0
41 | failed = []
42 | for name, result in cls._testresults:
43 | if result:
44 | succeeded += 1
45 | else:
46 | failed.append(name)
47 | print "================================================"
48 | print "Successes: {0}/{1}".format(succeeded, len(cls._testresults))
49 | if failed:
50 | print "Failed tests:", ", ".join(failed)
51 | else:
52 | print "All OK :)"
53 |
54 | def service(self, service_name):
55 | return self._app.session.service(service_name)
56 |
57 | def __init__(self):
58 | self.name = self.__class__.__name__
59 | self.start()
60 |
61 | def start(self):
62 | command = ["/usr/bin/python", self.script, "--qi-url", self.robot]
63 | self.popen = subprocess.Popen(command, stdout=subprocess.PIPE,
64 | stderr=subprocess.STDOUT)
65 | self.running = True
66 | #print "Spawned", self.script, "with ID", self.popen.pid
67 | #print
68 |
69 | def finish_and_dump(self, verbose=True):
70 | if self.running:
71 | self.running = False
72 | self.popen.terminate()
73 | if verbose:
74 | print
75 | print "Killed. Output:"
76 | lines_iterator = iter(self.popen.stdout.readline, b"")
77 | for line in lines_iterator:
78 | print ">", line.strip("\n") # yield line
79 | print
80 |
81 | def run_wrapped(self):
82 | succeeded = False
83 | try:
84 | print
85 | print "--------------------"
86 | print "starting", self.name
87 | succeeded = self.run()
88 | print "finished", self.name
89 | except Exception as e:
90 | print "error in", self.name
91 | print traceback.format_exc()
92 | finally:
93 | self.finish_and_dump(verbose=(not succeeded))
94 | self._testresults.append((self.name, succeeded))
95 |
96 | #########################################
97 | # Specific test classes
98 | #########################################
99 |
100 | class SetGetTest(ServiceTester):
101 | script = "app/scripts/myservice.py"
102 | def run(self):
103 | time.sleep(1)
104 |
105 | ALMyService = self.service("ALMyService")
106 | ALMyService.set(0)
107 | assert ALMyService.get() == 0
108 | ALMyService.set(2)
109 | assert ALMyService.get() == 2
110 | return True
111 |
112 |
113 | class ResetTest(ServiceTester):
114 | script = "app/scripts/myservice.py"
115 | def run(self):
116 | time.sleep(1)
117 |
118 | ALMyService = self.service("ALMyService")
119 | ALMyService.reset()
120 | assert ALMyService.get() == 0
121 | return True
122 |
123 |
124 | class ExitTest(ServiceTester):
125 | script = "app/scripts/myservice.py"
126 | def run(self):
127 | time.sleep(1)
128 |
129 | ALMyService = self.service("ALMyService")
130 | goterror = False
131 | try:
132 | ALMyService.exit()
133 | ALMyService.set(1)
134 | except RuntimeError:
135 | print "Got error after exit, as expected"
136 | goterror = True
137 | assert goterror, "Expected an exception after exit!"
138 | return True
139 |
140 | def run_tests(robotname, *testclasses):
141 | ServiceTester.configure(robotname)
142 | for cls in testclasses:
143 | cls().run_wrapped()
144 | ServiceTester.recap()
145 |
146 |
147 | def test_all(robotname):
148 | run_tests(robotname,
149 | SetGetTest,
150 | ResetTest,
151 | ExitTest,
152 | )
153 |
154 | if __name__ == "__main__":
155 | ROBOTNAME = "yourrobot.local" # Adapt this depending of your robot
156 | ROBOTNAME = "citadelle.local"
157 | test_all(ROBOTNAME)
158 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/testrun.py:
--------------------------------------------------------------------------------
1 | """
2 | A test runner for a NAOqi service (to test the service packaged in the app)
3 |
4 | Edit it to set your robot's IP to run it (or use arv etc.)
5 |
6 | So far it's pretty hard-coded
7 | """
8 |
9 | __version__ = "0.0.1"
10 |
11 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
12 | __author__ = 'ekroeger'
13 | __email__ = 'ekroeger@aldebaran.com'
14 |
15 |
16 | import subprocess
17 | import time
18 | import sys
19 | import traceback
20 |
21 | import qi
22 |
23 | #########################################
24 | # Helper base class
25 | #########################################
26 |
27 | class ServiceTester:
28 | _app = None
29 | _testresults = []
30 |
31 | @classmethod
32 | def configure(cls, robot):
33 | sys.argv.extend(["--qi-url", robot])
34 | cls.robot = robot
35 | cls._app = qi.Application()
36 | cls._app.start()
37 |
38 | @classmethod
39 | def recap(cls):
40 | succeeded = 0
41 | failed = []
42 | for name, result in cls._testresults:
43 | if result:
44 | succeeded += 1
45 | else:
46 | failed.append(name)
47 | print "================================================"
48 | print "Successes: {0}/{1}".format(succeeded, len(cls._testresults))
49 | if failed:
50 | print "Failed tests:", ", ".join(failed)
51 | else:
52 | print "All OK :)"
53 |
54 | def service(self, service_name):
55 | return self._app.session.service(service_name)
56 |
57 | def __init__(self):
58 | self.name = self.__class__.__name__
59 | self.start()
60 |
61 | def start(self):
62 | command = ["/usr/bin/python", self.script, "--qi-url", self.robot]
63 | self.popen = subprocess.Popen(command, stdout=subprocess.PIPE,
64 | stderr=subprocess.STDOUT)
65 | self.running = True
66 | #print "Spawned", self.script, "with ID", self.popen.pid
67 | #print
68 |
69 | def finish_and_dump(self, verbose=True):
70 | if self.running:
71 | self.running = False
72 | self.popen.terminate()
73 | if verbose:
74 | print
75 | print "Killed. Output:"
76 | lines_iterator = iter(self.popen.stdout.readline, b"")
77 | for line in lines_iterator:
78 | print ">", line.strip("\n") # yield line
79 | print
80 |
81 | def run_wrapped(self):
82 | succeeded = False
83 | try:
84 | print
85 | print "--------------------"
86 | print "starting", self.name
87 | succeeded = self.run()
88 | print "finished", self.name
89 | except Exception as e:
90 | print "error in", self.name
91 | print traceback.format_exc()
92 | finally:
93 | self.finish_and_dump(verbose=(not succeeded))
94 | self._testresults.append((self.name, succeeded))
95 |
96 | #########################################
97 | # Specific test classes
98 | #########################################
99 |
100 | class SetGetTest(ServiceTester):
101 | script = "app/scripts/myservice.py"
102 | def run(self):
103 | time.sleep(1)
104 |
105 | ALMyService = self.service("ALMyService")
106 | ALMyService.set(0)
107 | assert ALMyService.get() == 0
108 | ALMyService.set(2)
109 | assert ALMyService.get() == 2
110 | return True
111 |
112 |
113 | class ResetTest(ServiceTester):
114 | script = "app/scripts/myservice.py"
115 | def run(self):
116 | time.sleep(1)
117 |
118 | ALMyService = self.service("ALMyService")
119 | ALMyService.reset()
120 | assert ALMyService.get() == 0
121 | return True
122 |
123 |
124 | class ExitTest(ServiceTester):
125 | script = "app/scripts/myservice.py"
126 | def run(self):
127 | time.sleep(1)
128 |
129 | ALMyService = self.service("ALMyService")
130 | goterror = False
131 | try:
132 | ALMyService.exit()
133 | ALMyService.set(1)
134 | except RuntimeError:
135 | print "Got error after exit, as expected"
136 | goterror = True
137 | assert goterror, "Expected an exception after exit!"
138 | return True
139 |
140 | def run_tests(robotname, *testclasses):
141 | ServiceTester.configure(robotname)
142 | for cls in testclasses:
143 | cls().run_wrapped()
144 | ServiceTester.recap()
145 |
146 |
147 | def test_all(robotname):
148 | run_tests(robotname,
149 | SetGetTest,
150 | ResetTest,
151 | ExitTest,
152 | )
153 |
154 | if __name__ == "__main__":
155 | ROBOTNAME = "yourrobot.local" # Adapt this depending of your robot
156 | ROBOTNAME = "citadelle.local"
157 | test_all(ROBOTNAME)
158 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/testrun.py:
--------------------------------------------------------------------------------
1 | """
2 | A test runner for a NAOqi service (to test the service packaged in the app)
3 |
4 | Edit it to set your robot's IP to run it (or use arv etc.)
5 |
6 | So far it's pretty hard-coded
7 | """
8 |
9 | __version__ = "0.0.1"
10 |
11 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
12 | __author__ = 'ekroeger'
13 | __email__ = 'ekroeger@aldebaran.com'
14 |
15 |
16 | import subprocess
17 | import time
18 | import sys
19 | import traceback
20 |
21 | import qi
22 |
23 | #########################################
24 | # Helper base class
25 | #########################################
26 |
27 | class ServiceTester:
28 | _app = None
29 | _testresults = []
30 |
31 | @classmethod
32 | def configure(cls, robot):
33 | sys.argv.extend(["--qi-url", robot])
34 | cls.robot = robot
35 | cls._app = qi.Application()
36 | cls._app.start()
37 |
38 | @classmethod
39 | def recap(cls):
40 | succeeded = 0
41 | failed = []
42 | for name, result in cls._testresults:
43 | if result:
44 | succeeded += 1
45 | else:
46 | failed.append(name)
47 | print "================================================"
48 | print "Successes: {0}/{1}".format(succeeded, len(cls._testresults))
49 | if failed:
50 | print "Failed tests:", ", ".join(failed)
51 | else:
52 | print "All OK :)"
53 |
54 | def service(self, service_name):
55 | return self._app.session.service(service_name)
56 |
57 | def __init__(self):
58 | self.name = self.__class__.__name__
59 | self.start()
60 |
61 | def start(self):
62 | command = ["/usr/bin/python", self.script, "--qi-url", self.robot]
63 | self.popen = subprocess.Popen(command, stdout=subprocess.PIPE,
64 | stderr=subprocess.STDOUT)
65 | self.running = True
66 | #print "Spawned", self.script, "with ID", self.popen.pid
67 | #print
68 |
69 | def finish_and_dump(self, verbose=True):
70 | if self.running:
71 | self.running = False
72 | self.popen.terminate()
73 | if verbose:
74 | print
75 | print "Killed. Output:"
76 | lines_iterator = iter(self.popen.stdout.readline, b"")
77 | for line in lines_iterator:
78 | print ">", line.strip("\n") # yield line
79 | print
80 |
81 | def run_wrapped(self):
82 | succeeded = False
83 | try:
84 | print
85 | print "--------------------"
86 | print "starting", self.name
87 | succeeded = self.run()
88 | print "finished", self.name
89 | except Exception as e:
90 | print "error in", self.name
91 | print traceback.format_exc()
92 | finally:
93 | self.finish_and_dump(verbose=(not succeeded))
94 | self._testresults.append((self.name, succeeded))
95 |
96 | #########################################
97 | # Specific test classes
98 | #########################################
99 |
100 | class SetGetTest(ServiceTester):
101 | script = "app/scripts/myservice.py"
102 | def run(self):
103 | time.sleep(1)
104 |
105 | ALMyService = self.service("ALMyService")
106 | ALMyService.set(0)
107 | assert ALMyService.get() == 0
108 | ALMyService.set(2)
109 | assert ALMyService.get() == 2
110 | return True
111 |
112 |
113 | class ResetTest(ServiceTester):
114 | script = "app/scripts/myservice.py"
115 | def run(self):
116 | time.sleep(1)
117 |
118 | ALMyService = self.service("ALMyService")
119 | ALMyService.reset()
120 | assert ALMyService.get() == 0
121 | return True
122 |
123 |
124 | class ExitTest(ServiceTester):
125 | script = "app/scripts/myservice.py"
126 | def run(self):
127 | time.sleep(1)
128 |
129 | ALMyService = self.service("ALMyService")
130 | goterror = False
131 | try:
132 | ALMyService.exit()
133 | ALMyService.set(1)
134 | except RuntimeError:
135 | print "Got error after exit, as expected"
136 | goterror = True
137 | assert goterror, "Expected an exception after exit!"
138 | return True
139 |
140 | def run_tests(robotname, *testclasses):
141 | ServiceTester.configure(robotname)
142 | for cls in testclasses:
143 | cls().run_wrapped()
144 | ServiceTester.recap()
145 |
146 |
147 | def test_all(robotname):
148 | run_tests(robotname,
149 | SetGetTest,
150 | ResetTest,
151 | ExitTest,
152 | )
153 |
154 | if __name__ == "__main__":
155 | ROBOTNAME = "yourrobot.local" # Adapt this depending of your robot
156 | ROBOTNAME = "citadelle.local"
157 | test_all(ROBOTNAME)
158 |
--------------------------------------------------------------------------------
/templates/dialog-service/testrun.py:
--------------------------------------------------------------------------------
1 | """
2 | A test runner for a NAOqi service (to test the service packaged in the app)
3 |
4 | Edit it to set your robot's IP to run it (or use arv etc.)
5 |
6 | So far it's pretty hard-coded
7 | """
8 |
9 | __version__ = "0.0.1"
10 |
11 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
12 | __author__ = 'ekroeger'
13 | __email__ = 'ekroeger@aldebaran.com'
14 |
15 |
16 | import subprocess
17 | import time
18 | import sys
19 | import traceback
20 |
21 | import qi
22 |
23 | #########################################
24 | # Helper base class
25 | #########################################
26 |
27 | class ServiceTester:
28 | _app = None
29 | _testresults = []
30 |
31 | @classmethod
32 | def configure(cls, robot):
33 | sys.argv.extend(["--qi-url", robot])
34 | cls.robot = robot
35 | cls._app = qi.Application()
36 | cls._app.start()
37 |
38 | @classmethod
39 | def recap(cls):
40 | succeeded = 0
41 | failed = []
42 | for name, result in cls._testresults:
43 | if result:
44 | succeeded += 1
45 | else:
46 | failed.append(name)
47 | print "================================================"
48 | print "Successes: {0}/{1}".format(succeeded, len(cls._testresults))
49 | if failed:
50 | print "Failed tests:", ", ".join(failed)
51 | else:
52 | print "All OK :)"
53 |
54 | def service(self, service_name):
55 | return self._app.session.service(service_name)
56 |
57 | def __init__(self):
58 | self.name = self.__class__.__name__
59 | self.start()
60 |
61 | def start(self):
62 | command = ["/usr/bin/python", self.script, "--qi-url", self.robot]
63 | self.popen = subprocess.Popen(command, stdout=subprocess.PIPE,
64 | stderr=subprocess.STDOUT)
65 | self.running = True
66 | #print "Spawned", self.script, "with ID", self.popen.pid
67 | #print
68 |
69 | def finish_and_dump(self, verbose=True):
70 | if self.running:
71 | self.running = False
72 | self.popen.terminate()
73 | if verbose:
74 | print
75 | print "Killed. Output:"
76 | lines_iterator = iter(self.popen.stdout.readline, b"")
77 | for line in lines_iterator:
78 | print ">", line.strip("\n") # yield line
79 | print
80 |
81 | def run_wrapped(self):
82 | succeeded = False
83 | try:
84 | print
85 | print "--------------------"
86 | print "starting", self.name
87 | succeeded = self.run()
88 | print "finished", self.name
89 | except Exception as e:
90 | print "error in", self.name
91 | print traceback.format_exc()
92 | finally:
93 | self.finish_and_dump(verbose=(not succeeded))
94 | self._testresults.append((self.name, succeeded))
95 |
96 | #########################################
97 | # Specific test classes
98 | #########################################
99 |
100 | class SetGetTest(ServiceTester):
101 | script = "app/scripts/myservice.py"
102 | def run(self):
103 | time.sleep(1)
104 |
105 | ALMyService = self.service("ALMyService")
106 | ALMyService.set(0)
107 | assert ALMyService.get() == 0
108 | ALMyService.set(2)
109 | assert ALMyService.get() == 2
110 | return True
111 |
112 |
113 | class ResetTest(ServiceTester):
114 | script = "app/scripts/myservice.py"
115 | def run(self):
116 | time.sleep(1)
117 |
118 | ALMyService = self.service("ALMyService")
119 | ALMyService.reset()
120 | assert ALMyService.get() == 0
121 | return True
122 |
123 |
124 | class StopTest(ServiceTester):
125 | script = "app/scripts/myservice.py"
126 | def run(self):
127 | time.sleep(1)
128 |
129 | ALMyService = self.service("ALMyService")
130 | goterror = False
131 | try:
132 | ALMyService.stop()
133 | time.sleep(1)
134 | ALMyService.set(1)
135 | except RuntimeError:
136 | print "Got error after exit, as expected"
137 | goterror = True
138 | assert goterror, "Expected an exception after exit!"
139 | return True
140 |
141 | def run_tests(robotname, *testclasses):
142 | ServiceTester.configure(robotname)
143 | for cls in testclasses:
144 | cls().run_wrapped()
145 | ServiceTester.recap()
146 |
147 |
148 | def test_all(robotname):
149 | run_tests(robotname,
150 | SetGetTest,
151 | ResetTest,
152 | StopTest,
153 | )
154 |
155 | if __name__ == "__main__":
156 | ROBOTNAME = "yourrobot.local" # Adapt this depending of your robot
157 | ROBOTNAME = "citadelle.local"
158 | test_all(ROBOTNAME)
159 |
--------------------------------------------------------------------------------
/templates/python-service/testrun.py:
--------------------------------------------------------------------------------
1 | """
2 | A test runner for a NAOqi service (to test the service packaged in the app)
3 |
4 | Edit it to set your robot's IP to run it (or use arv etc.)
5 |
6 | So far it's pretty hard-coded
7 | """
8 |
9 | __version__ = "0.0.1"
10 |
11 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
12 | __author__ = 'ekroeger'
13 | __email__ = 'ekroeger@aldebaran.com'
14 |
15 |
16 | import subprocess
17 | import time
18 | import sys
19 | import traceback
20 |
21 | import qi
22 |
23 | #########################################
24 | # Helper base class
25 | #########################################
26 |
27 | class ServiceTester:
28 | _app = None
29 | _testresults = []
30 |
31 | @classmethod
32 | def configure(cls, robot):
33 | sys.argv.extend(["--qi-url", robot])
34 | cls.robot = robot
35 | cls._app = qi.Application()
36 | cls._app.start()
37 |
38 | @classmethod
39 | def recap(cls):
40 | succeeded = 0
41 | failed = []
42 | for name, result in cls._testresults:
43 | if result:
44 | succeeded += 1
45 | else:
46 | failed.append(name)
47 | print "================================================"
48 | print "Successes: {0}/{1}".format(succeeded, len(cls._testresults))
49 | if failed:
50 | print "Failed tests:", ", ".join(failed)
51 | else:
52 | print "All OK :)"
53 |
54 | def service(self, service_name):
55 | return self._app.session.service(service_name)
56 |
57 | def __init__(self):
58 | self.name = self.__class__.__name__
59 | self.start()
60 |
61 | def start(self):
62 | command = ["/usr/bin/python", self.script, "--qi-url", self.robot]
63 | self.popen = subprocess.Popen(command, stdout=subprocess.PIPE,
64 | stderr=subprocess.STDOUT)
65 | self.running = True
66 | #print "Spawned", self.script, "with ID", self.popen.pid
67 | #print
68 |
69 | def finish_and_dump(self, verbose=True):
70 | if self.running:
71 | self.running = False
72 | self.popen.terminate()
73 | if verbose:
74 | print
75 | print "Killed. Output:"
76 | lines_iterator = iter(self.popen.stdout.readline, b"")
77 | for line in lines_iterator:
78 | print ">", line.strip("\n") # yield line
79 | print
80 |
81 | def run_wrapped(self):
82 | succeeded = False
83 | try:
84 | print
85 | print "--------------------"
86 | print "starting", self.name
87 | succeeded = self.run()
88 | print "finished", self.name
89 | except Exception as e:
90 | print "error in", self.name
91 | print traceback.format_exc()
92 | finally:
93 | self.finish_and_dump(verbose=(not succeeded))
94 | self._testresults.append((self.name, succeeded))
95 |
96 | #########################################
97 | # Specific test classes
98 | #########################################
99 |
100 | class SetGetTest(ServiceTester):
101 | script = "app/scripts/myservice.py"
102 | def run(self):
103 | time.sleep(1)
104 |
105 | ALMyService = self.service("ALMyService")
106 | ALMyService.set(0)
107 | assert ALMyService.get() == 0
108 | ALMyService.set(2)
109 | assert ALMyService.get() == 2
110 | return True
111 |
112 |
113 | class ResetTest(ServiceTester):
114 | script = "app/scripts/myservice.py"
115 | def run(self):
116 | time.sleep(1)
117 |
118 | ALMyService = self.service("ALMyService")
119 | ALMyService.reset()
120 | assert ALMyService.get() == 0
121 | return True
122 |
123 |
124 | class StopTest(ServiceTester):
125 | script = "app/scripts/myservice.py"
126 | def run(self):
127 | time.sleep(1)
128 |
129 | ALMyService = self.service("ALMyService")
130 | goterror = False
131 | try:
132 | ALMyService.stop()
133 | time.sleep(1)
134 | ALMyService.set(1)
135 | except RuntimeError:
136 | print "Got error after exit, as expected"
137 | goterror = True
138 | assert goterror, "Expected an exception after exit!"
139 | return True
140 |
141 | def run_tests(robotname, *testclasses):
142 | ServiceTester.configure(robotname)
143 | for cls in testclasses:
144 | cls().run_wrapped()
145 | ServiceTester.recap()
146 |
147 |
148 | def test_all(robotname):
149 | run_tests(robotname,
150 | SetGetTest,
151 | ResetTest,
152 | StopTest,
153 | )
154 |
155 | if __name__ == "__main__":
156 | ROBOTNAME = "yourrobot.local" # Adapt this depending of your robot
157 | ROBOTNAME = "citadelle.local"
158 | test_all(ROBOTNAME)
159 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/behavior.xar:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | media/images/box/root.png
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | media/images/box/box-python-script.png
20 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
--------------------------------------------------------------------------------
/jumpstart.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | # PYTHON_ARGCOMPLETE_OK
3 | """
4 | jumpstart.py
5 |
6 | A script for generating a NAOqi project from a tamplate folder.
7 | """
8 |
9 | __version__ = "0.1.1"
10 |
11 | __copyright__ = "Copyright 2015-2016, SBRE"
12 | __author__ = 'ekroeger'
13 | __email__ = 'ekroeger@aldebaran.com'
14 |
15 | import os
16 | import shutil
17 | import re
18 |
19 | import distutils.dir_util
20 |
21 | argcomplete = None
22 | try:
23 | import argcomplete
24 | except Exception as e:
25 | pass
26 |
27 | TEMPLATES = "templates"
28 | OUTPUT = "output"
29 |
30 | FILETYPES_TO_REPROCESS = [".xar", ".pml", ".manifest", ".py", ".js", ".json",
31 | ".xml", ".html", ".top", ".dlg"]
32 |
33 |
34 | def rename_in_file(filepath, sourceword, destword):
35 | sourcere = re.compile(r"\b" + sourceword + r"\b")
36 | # Does this pattern even occur in this file? (most of the time, it won't)
37 | with open(filepath) as f:
38 | if not any(sourcere.search(line) for line in f):
39 | return False# We're done here.
40 | # pattern is in the file, so perform replace operation.
41 |
42 | with open(filepath) as f:
43 | temp_filepath = filepath + ".tmp"
44 | out = open(temp_filepath, "w")
45 | for line in f:
46 | out.write(sourcere.sub(destword, line))
47 | f.close()
48 | out.close()
49 | os.unlink(filepath)
50 | os.rename(temp_filepath, filepath)
51 | return True
52 |
53 | def rename_in_folder(folder, sourceword, destword):
54 | files = list(os.listdir(folder))
55 | for filename in files:
56 | if filename.startswith("."):
57 | continue
58 | filepath = os.path.join(folder, filename)
59 | # 1) replace everything inside
60 | if os.path.isdir(filepath):
61 | rename_in_folder(filepath, sourceword, destword)
62 | else:
63 | extension = os.path.splitext(filename)[-1].lower()
64 | if extension in FILETYPES_TO_REPROCESS:
65 | if rename_in_file(filepath, sourceword, destword):
66 | print "Renamed inside", filename
67 | # 2) rename if needed
68 | if sourceword in filename:
69 | newfilename = filename.replace(sourceword, destword)
70 | os.rename(filepath, os.path.join(folder, newfilename))
71 | print "Renamed", filename
72 |
73 | def generate(sourcename, destname, servicename=None):
74 | "Generate a folder based on a template, or add to an existing one."
75 | if not os.path.exists(OUTPUT):
76 | os.mkdir(OUTPUT)
77 | sourcepath = os.path.join(TEMPLATES, sourcename)
78 | destpath = os.path.join(OUTPUT, destname)
79 | if not os.path.exists(sourcepath):
80 | raise Exception, "Template not found: " + repr(sourcename)
81 | project_exists = os.path.exists(destpath)
82 | if project_exists:
83 | shutil.move(destpath, destpath + "_TEMP")
84 | print "Project already exists, only adding new files to it"
85 | shutil.copytree(sourcepath, destpath)
86 | rename_in_folder(destpath, sourcename, destname)
87 |
88 | if servicename:
89 | # script name (used by ALServiceManager) should be underscore
90 | scriptname = servicename.lower()
91 | # service name (used in ServiceDirectory) should be capitalized
92 | if not servicename[0].isupper():
93 | servicename = servicename.capitalize()
94 | rename_in_folder(destpath, "ALMyService", servicename)
95 | rename_in_folder(destpath, "myservice", scriptname)
96 |
97 | if project_exists:
98 | distutils.dir_util.copy_tree(destpath + "_TEMP", destpath)
99 | shutil.rmtree(destpath + "_TEMP")
100 | print "Done adding to", destname, "from", sourcename,
101 | else:
102 | print "Done generating", destname, "from", sourcename,
103 |
104 |
105 | def test_run():
106 | #generate("pythonapp", "mytestapp")
107 | generate("service-tabletpage", "servicetestapp", "ALSuperDuperService")
108 |
109 | # Used for argcomplete
110 | class TemplateCompleter(object):
111 | def __init__(self):
112 | self.choices = os.listdir("templates")
113 |
114 | def __call__(self, prefix, **kwargs):
115 | return (c for c in self.choices if c.startswith(prefix))
116 |
117 |
118 | def run_with_sysargs():
119 | import argparse
120 | parser = argparse.ArgumentParser(description='Generates a project.')
121 | parser.add_argument('sourcename', type=str,
122 | help='name of source recipe/template').completer = TemplateCompleter()
123 | parser.add_argument('destname', type=str,
124 | help='name of new project to create')
125 | parser.add_argument('servicename', type=str,
126 | help='optional, name of service to create',
127 | nargs='?')
128 | if argcomplete:
129 | argcomplete.autocomplete(parser)
130 | args = parser.parse_args()
131 | if (args.servicename):
132 | generate(args.sourcename, args.destname, args.servicename)
133 | else:
134 | generate(args.sourcename, args.destname)
135 |
136 | if __name__ == "__main__":
137 | #test_run()
138 | #rename_in_folder("./output/basicparams/", "basicparams", "volumeslider")
139 | run_with_sysargs()
140 |
141 |
--------------------------------------------------------------------------------
/templates/simple-tabletpage/app/behavior.xar:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | media/images/box/root.png
5 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | media/images/box/root.png
20 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/scripts/stk/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.runner.py
3 |
4 | A helper library for making simple standalone python scripts as apps.
5 |
6 | Wraps some NAOqi and system stuff, you could do all this by directly using the
7 | Python SDK, these helper functions just isolate some frequently used/hairy
8 | bits so you don't have them mixed in your logic.
9 | """
10 |
11 | __version__ = "0.1.3"
12 |
13 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
14 | __author__ = 'ekroeger'
15 | __email__ = 'ekroeger@aldebaran.com'
16 |
17 | import sys
18 | import qi
19 | from distutils.version import LooseVersion
20 |
21 | #
22 | # Helpers for making sure we have a robot to connect to
23 | #
24 |
25 |
26 | def check_commandline_args(description):
27 | "Checks whether command-line parameters are enough"
28 | import argparse
29 | parser = argparse.ArgumentParser(description=description)
30 | parser.add_argument('--qi-url', help='connect to specific NAOqi instance')
31 |
32 | args = parser.parse_args()
33 | return args
34 |
35 |
36 | def is_on_robot():
37 | "Returns whether this is being executed on an Aldebaran robot."
38 | import platform
39 | return "aldebaran" in platform.platform()
40 |
41 |
42 | def get_debug_robot():
43 | "Returns IP address of debug robot, complaining if not found"
44 | try:
45 | import qiq.config
46 | qiqrobot = qiq.config.defaultHost()
47 | if qiqrobot:
48 | robot = raw_input(
49 | "connect to which robot? (default is {0}) ".format(qiqrobot))
50 | if robot:
51 | return robot
52 | else:
53 | return qiqrobot
54 | else:
55 | print "qiq found, but it has no default robot configured."
56 | except ImportError:
57 | # qiq not installed
58 | print "qiq not installed (you can use it to set a default robot)."
59 | return raw_input("connect to which robot? ")
60 |
61 |
62 | def init(qi_url=None):
63 | "Returns a QiApplication object, possibly with interactive input."
64 | if qi_url:
65 | sys.argv.extend(["--qi-url", qi_url])
66 | else:
67 | args = check_commandline_args('Run the app.')
68 | if bool(args.qi_url):
69 | qi_url = args.qi_url
70 | elif not is_on_robot():
71 | print "no --qi-url parameter given; interactively getting debug robot."
72 | debug_robot = get_debug_robot()
73 | if debug_robot:
74 | sys.argv.extend(["--qi-url", debug_robot])
75 | qi_url = debug_robot
76 | else:
77 | raise RuntimeError("No robot, not running.")
78 |
79 | qiapp = None
80 | sys.argv[0] = str(sys.argv[0])
81 |
82 | # In versions bellow 2.3, look for --qi-url in the arguemnts and call accordingly the Application
83 | if qi_url and LooseVersion(qi.__version__) < LooseVersion("2.3"):
84 | position = 0
85 | qiapp = qi.Application(url="tcp://"+qi_url+":9559")
86 | # In versions greater than 2.3 the ip can simply be passed through argv[0]
87 | else:
88 | # In some environments sys.argv[0] has unicode, which qi rejects
89 | qiapp = qi.Application()
90 |
91 | qiapp.start()
92 | return qiapp
93 |
94 |
95 | # Main runner
96 |
97 | def run_activity(activity_class, service_name=None):
98 | """Instantiate the given class, and runs it.
99 |
100 | The given class must take a qiapplication object as parameter, and may also
101 | have on_start and on_stop methods, that will be called before and after
102 | running it."""
103 | qiapp = init()
104 | activity = activity_class(qiapp)
105 | service_id = None
106 |
107 | try:
108 | # if it's a service, register it
109 | if service_name:
110 | # Note: this will fail if there is already a service. Unregistering
111 | # it would not be a good practice, because it's process would still
112 | # be running.
113 | service_id = qiapp.session.registerService(service_name, activity)
114 |
115 | if hasattr(activity, "on_start"):
116 | def handle_on_start_done(on_start_future):
117 | "Custom callback, for checking errors"
118 | if on_start_future.hasError():
119 | try:
120 | msg = "Error in on_start(), stopping application: %s" \
121 | % on_start_future.error()
122 | if hasattr(activity, "logger"):
123 | activity.logger.error(msg)
124 | else:
125 | print msg
126 | finally:
127 | qiapp.stop()
128 | qi.async(activity.on_start).addCallback(handle_on_start_done)
129 |
130 | # Run the QiApplication, which runs until someone calls qiapp.stop()
131 | qiapp.run()
132 |
133 | finally:
134 | # Cleanup
135 | if hasattr(activity, "on_stop"):
136 | # We need a qi.async call so that if the class is single threaded,
137 | # it will wait for callbacks to be finished.
138 | qi.async(activity.on_stop).wait()
139 | if service_id:
140 | qiapp.session.unregisterService(service_id)
141 |
142 |
143 | def run_service(service_class, service_name=None):
144 | """Instantiate the given class, and registers it as a NAOqi service.
145 |
146 | The given class must take a qiapplication object as parameter, and may also
147 | have on_start and on_stop methods, that will be called before and after
148 | running it.
149 |
150 | If the service_name parameter is not given, the classes' name will be used.
151 | """
152 | if not service_name:
153 | service_name = service_class.__name__
154 | run_activity(service_class, service_name)
155 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/scripts/stk/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.runner.py
3 |
4 | A helper library for making simple standalone python scripts as apps.
5 |
6 | Wraps some NAOqi and system stuff, you could do all this by directly using the
7 | Python SDK, these helper functions just isolate some frequently used/hairy
8 | bits so you don't have them mixed in your logic.
9 | """
10 |
11 | __version__ = "0.1.3"
12 |
13 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
14 | __author__ = 'ekroeger'
15 | __email__ = 'ekroeger@aldebaran.com'
16 |
17 | import sys
18 | import qi
19 | from distutils.version import LooseVersion
20 |
21 | #
22 | # Helpers for making sure we have a robot to connect to
23 | #
24 |
25 |
26 | def check_commandline_args(description):
27 | "Checks whether command-line parameters are enough"
28 | import argparse
29 | parser = argparse.ArgumentParser(description=description)
30 | parser.add_argument('--qi-url', help='connect to specific NAOqi instance')
31 |
32 | args = parser.parse_args()
33 | return args
34 |
35 |
36 | def is_on_robot():
37 | "Returns whether this is being executed on an Aldebaran robot."
38 | import platform
39 | return "aldebaran" in platform.platform()
40 |
41 |
42 | def get_debug_robot():
43 | "Returns IP address of debug robot, complaining if not found"
44 | try:
45 | import qiq.config
46 | qiqrobot = qiq.config.defaultHost()
47 | if qiqrobot:
48 | robot = raw_input(
49 | "connect to which robot? (default is {0}) ".format(qiqrobot))
50 | if robot:
51 | return robot
52 | else:
53 | return qiqrobot
54 | else:
55 | print "qiq found, but it has no default robot configured."
56 | except ImportError:
57 | # qiq not installed
58 | print "qiq not installed (you can use it to set a default robot)."
59 | return raw_input("connect to which robot? ")
60 |
61 |
62 | def init(qi_url=None):
63 | "Returns a QiApplication object, possibly with interactive input."
64 | if qi_url:
65 | sys.argv.extend(["--qi-url", qi_url])
66 | else:
67 | args = check_commandline_args('Run the app.')
68 | if bool(args.qi_url):
69 | qi_url = args.qi_url
70 | elif not is_on_robot():
71 | print "no --qi-url parameter given; interactively getting debug robot."
72 | debug_robot = get_debug_robot()
73 | if debug_robot:
74 | sys.argv.extend(["--qi-url", debug_robot])
75 | qi_url = debug_robot
76 | else:
77 | raise RuntimeError("No robot, not running.")
78 |
79 | qiapp = None
80 | sys.argv[0] = str(sys.argv[0])
81 |
82 | # In versions bellow 2.3, look for --qi-url in the arguemnts and call accordingly the Application
83 | if qi_url and hasattr(qi, "__version__") and LooseVersion(qi.__version__) < LooseVersion("2.3"):
84 | qiapp = qi.Application(url="tcp://"+qi_url+":9559")
85 | # In versions greater than 2.3 the ip can simply be passed through argv[0]
86 | else:
87 | # In some environments sys.argv[0] has unicode, which qi rejects
88 | qiapp = qi.Application()
89 |
90 | qiapp.start()
91 | return qiapp
92 |
93 |
94 | # Main runner
95 |
96 | def run_activity(activity_class, service_name=None):
97 | """Instantiate the given class, and runs it.
98 |
99 | The given class must take a qiapplication object as parameter, and may also
100 | have on_start and on_stop methods, that will be called before and after
101 | running it."""
102 | qiapp = init()
103 | activity = activity_class(qiapp)
104 | service_id = None
105 |
106 | try:
107 | # if it's a service, register it
108 | if service_name:
109 | # Note: this will fail if there is already a service. Unregistering
110 | # it would not be a good practice, because it's process would still
111 | # be running.
112 | service_id = qiapp.session.registerService(service_name, activity)
113 |
114 | if hasattr(activity, "on_start"):
115 | def handle_on_start_done(on_start_future):
116 | "Custom callback, for checking errors"
117 | if on_start_future.hasError():
118 | try:
119 | msg = "Error in on_start(), stopping application: %s" \
120 | % on_start_future.error()
121 | if hasattr(activity, "logger"):
122 | activity.logger.error(msg)
123 | else:
124 | print msg
125 | finally:
126 | qiapp.stop()
127 | qi.async(activity.on_start).addCallback(handle_on_start_done)
128 |
129 | # Run the QiApplication, which runs until someone calls qiapp.stop()
130 | qiapp.run()
131 |
132 | finally:
133 | # Cleanup
134 | if hasattr(activity, "on_stop"):
135 | # We need a qi.async call so that if the class is single threaded,
136 | # it will wait for callbacks to be finished.
137 | qi.async(activity.on_stop).wait()
138 | if service_id:
139 | qiapp.session.unregisterService(service_id)
140 |
141 |
142 | def run_service(service_class, service_name=None):
143 | """Instantiate the given class, and registers it as a NAOqi service.
144 |
145 | The given class must take a qiapplication object as parameter, and may also
146 | have on_start and on_stop methods, that will be called before and after
147 | running it.
148 |
149 | If the service_name parameter is not given, the classes' name will be used.
150 | """
151 | if not service_name:
152 | service_name = service_class.__name__
153 | run_activity(service_class, service_name)
154 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/scripts/stk/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.runner.py
3 |
4 | A helper library for making simple standalone python scripts as apps.
5 |
6 | Wraps some NAOqi and system stuff, you could do all this by directly using the
7 | Python SDK, these helper functions just isolate some frequently used/hairy
8 | bits so you don't have them mixed in your logic.
9 | """
10 |
11 | __version__ = "0.1.3"
12 |
13 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
14 | __author__ = 'ekroeger'
15 | __email__ = 'ekroeger@aldebaran.com'
16 |
17 | import sys
18 | import qi
19 | from distutils.version import LooseVersion
20 |
21 | #
22 | # Helpers for making sure we have a robot to connect to
23 | #
24 |
25 |
26 | def check_commandline_args(description):
27 | "Checks whether command-line parameters are enough"
28 | import argparse
29 | parser = argparse.ArgumentParser(description=description)
30 | parser.add_argument('--qi-url', help='connect to specific NAOqi instance')
31 |
32 | args = parser.parse_args()
33 | return args
34 |
35 |
36 | def is_on_robot():
37 | "Returns whether this is being executed on an Aldebaran robot."
38 | import platform
39 | return "aldebaran" in platform.platform()
40 |
41 |
42 | def get_debug_robot():
43 | "Returns IP address of debug robot, complaining if not found"
44 | try:
45 | import qiq.config
46 | qiqrobot = qiq.config.defaultHost()
47 | if qiqrobot:
48 | robot = raw_input(
49 | "connect to which robot? (default is {0}) ".format(qiqrobot))
50 | if robot:
51 | return robot
52 | else:
53 | return qiqrobot
54 | else:
55 | print "qiq found, but it has no default robot configured."
56 | except ImportError:
57 | # qiq not installed
58 | print "qiq not installed (you can use it to set a default robot)."
59 | return raw_input("connect to which robot? ")
60 |
61 |
62 | def init(qi_url=None):
63 | "Returns a QiApplication object, possibly with interactive input."
64 | if qi_url:
65 | sys.argv.extend(["--qi-url", qi_url])
66 | else:
67 | args = check_commandline_args('Run the app.')
68 | if bool(args.qi_url):
69 | qi_url = args.qi_url
70 | elif not is_on_robot():
71 | print "no --qi-url parameter given; interactively getting debug robot."
72 | debug_robot = get_debug_robot()
73 | if debug_robot:
74 | sys.argv.extend(["--qi-url", debug_robot])
75 | qi_url = debug_robot
76 | else:
77 | raise RuntimeError("No robot, not running.")
78 |
79 | qiapp = None
80 | sys.argv[0] = str(sys.argv[0])
81 |
82 | # In versions bellow 2.3, look for --qi-url in the arguemnts and call accordingly the Application
83 | if qi_url and hasattr(qi, "__version__") and LooseVersion(qi.__version__) < LooseVersion("2.3"):
84 | qiapp = qi.Application(url="tcp://"+qi_url+":9559")
85 | # In versions greater than 2.3 the ip can simply be passed through argv[0]
86 | else:
87 | # In some environments sys.argv[0] has unicode, which qi rejects
88 | qiapp = qi.Application()
89 |
90 | qiapp.start()
91 | return qiapp
92 |
93 |
94 | # Main runner
95 |
96 | def run_activity(activity_class, service_name=None):
97 | """Instantiate the given class, and runs it.
98 |
99 | The given class must take a qiapplication object as parameter, and may also
100 | have on_start and on_stop methods, that will be called before and after
101 | running it."""
102 | qiapp = init()
103 | activity = activity_class(qiapp)
104 | service_id = None
105 |
106 | try:
107 | # if it's a service, register it
108 | if service_name:
109 | # Note: this will fail if there is already a service. Unregistering
110 | # it would not be a good practice, because it's process would still
111 | # be running.
112 | service_id = qiapp.session.registerService(service_name, activity)
113 |
114 | if hasattr(activity, "on_start"):
115 | def handle_on_start_done(on_start_future):
116 | "Custom callback, for checking errors"
117 | if on_start_future.hasError():
118 | try:
119 | msg = "Error in on_start(), stopping application: %s" \
120 | % on_start_future.error()
121 | if hasattr(activity, "logger"):
122 | activity.logger.error(msg)
123 | else:
124 | print msg
125 | finally:
126 | qiapp.stop()
127 | qi.async(activity.on_start).addCallback(handle_on_start_done)
128 |
129 | # Run the QiApplication, which runs until someone calls qiapp.stop()
130 | qiapp.run()
131 |
132 | finally:
133 | # Cleanup
134 | if hasattr(activity, "on_stop"):
135 | # We need a qi.async call so that if the class is single threaded,
136 | # it will wait for callbacks to be finished.
137 | qi.async(activity.on_stop).wait()
138 | if service_id:
139 | qiapp.session.unregisterService(service_id)
140 |
141 |
142 | def run_service(service_class, service_name=None):
143 | """Instantiate the given class, and registers it as a NAOqi service.
144 |
145 | The given class must take a qiapplication object as parameter, and may also
146 | have on_start and on_stop methods, that will be called before and after
147 | running it.
148 |
149 | If the service_name parameter is not given, the classes' name will be used.
150 | """
151 | if not service_name:
152 | service_name = service_class.__name__
153 | run_activity(service_class, service_name)
154 |
--------------------------------------------------------------------------------
/templates/python-service/app/scripts/stk/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.runner.py
3 |
4 | A helper library for making simple standalone python scripts as apps.
5 |
6 | Wraps some NAOqi and system stuff, you could do all this by directly using the
7 | Python SDK, these helper functions just isolate some frequently used/hairy
8 | bits so you don't have them mixed in your logic.
9 | """
10 |
11 | __version__ = "0.1.3"
12 |
13 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
14 | __author__ = 'ekroeger'
15 | __email__ = 'ekroeger@aldebaran.com'
16 |
17 | import sys
18 | import qi
19 | from distutils.version import LooseVersion
20 |
21 | #
22 | # Helpers for making sure we have a robot to connect to
23 | #
24 |
25 |
26 | def check_commandline_args(description):
27 | "Checks whether command-line parameters are enough"
28 | import argparse
29 | parser = argparse.ArgumentParser(description=description)
30 | parser.add_argument('--qi-url', help='connect to specific NAOqi instance')
31 |
32 | args = parser.parse_args()
33 | return args
34 |
35 |
36 | def is_on_robot():
37 | "Returns whether this is being executed on an Aldebaran robot."
38 | import platform
39 | return "aldebaran" in platform.platform()
40 |
41 |
42 | def get_debug_robot():
43 | "Returns IP address of debug robot, complaining if not found"
44 | try:
45 | import qiq.config
46 | qiqrobot = qiq.config.defaultHost()
47 | if qiqrobot:
48 | robot = raw_input(
49 | "connect to which robot? (default is {0}) ".format(qiqrobot))
50 | if robot:
51 | return robot
52 | else:
53 | return qiqrobot
54 | else:
55 | print "qiq found, but it has no default robot configured."
56 | except ImportError:
57 | # qiq not installed
58 | print "qiq not installed (you can use it to set a default robot)."
59 | return raw_input("connect to which robot? ")
60 |
61 |
62 | def init(qi_url=None):
63 | "Returns a QiApplication object, possibly with interactive input."
64 | if qi_url:
65 | sys.argv.extend(["--qi-url", qi_url])
66 | else:
67 | args = check_commandline_args('Run the app.')
68 | if bool(args.qi_url):
69 | qi_url = args.qi_url
70 | elif not is_on_robot():
71 | print "no --qi-url parameter given; interactively getting debug robot."
72 | debug_robot = get_debug_robot()
73 | if debug_robot:
74 | sys.argv.extend(["--qi-url", debug_robot])
75 | qi_url = debug_robot
76 | else:
77 | raise RuntimeError("No robot, not running.")
78 |
79 | qiapp = None
80 | sys.argv[0] = str(sys.argv[0])
81 |
82 | # In versions bellow 2.3, look for --qi-url in the arguemnts and call accordingly the Application
83 | if qi_url and hasattr(qi, "__version__") and LooseVersion(qi.__version__) < LooseVersion("2.3"):
84 | qiapp = qi.Application(url="tcp://"+qi_url+":9559")
85 | # In versions greater than 2.3 the ip can simply be passed through argv[0]
86 | else:
87 | # In some environments sys.argv[0] has unicode, which qi rejects
88 | qiapp = qi.Application()
89 |
90 | qiapp.start()
91 | return qiapp
92 |
93 |
94 | # Main runner
95 |
96 | def run_activity(activity_class, service_name=None):
97 | """Instantiate the given class, and runs it.
98 |
99 | The given class must take a qiapplication object as parameter, and may also
100 | have on_start and on_stop methods, that will be called before and after
101 | running it."""
102 | qiapp = init()
103 | activity = activity_class(qiapp)
104 | service_id = None
105 |
106 | try:
107 | # if it's a service, register it
108 | if service_name:
109 | # Note: this will fail if there is already a service. Unregistering
110 | # it would not be a good practice, because it's process would still
111 | # be running.
112 | service_id = qiapp.session.registerService(service_name, activity)
113 |
114 | if hasattr(activity, "on_start"):
115 | def handle_on_start_done(on_start_future):
116 | "Custom callback, for checking errors"
117 | if on_start_future.hasError():
118 | try:
119 | msg = "Error in on_start(), stopping application: %s" \
120 | % on_start_future.error()
121 | if hasattr(activity, "logger"):
122 | activity.logger.error(msg)
123 | else:
124 | print msg
125 | finally:
126 | qiapp.stop()
127 | qi.async(activity.on_start).addCallback(handle_on_start_done)
128 |
129 | # Run the QiApplication, which runs until someone calls qiapp.stop()
130 | qiapp.run()
131 |
132 | finally:
133 | # Cleanup
134 | if hasattr(activity, "on_stop"):
135 | # We need a qi.async call so that if the class is single threaded,
136 | # it will wait for callbacks to be finished.
137 | qi.async(activity.on_stop).wait()
138 | if service_id:
139 | qiapp.session.unregisterService(service_id)
140 |
141 |
142 | def run_service(service_class, service_name=None):
143 | """Instantiate the given class, and registers it as a NAOqi service.
144 |
145 | The given class must take a qiapplication object as parameter, and may also
146 | have on_start and on_stop methods, that will be called before and after
147 | running it.
148 |
149 | If the service_name parameter is not given, the classes' name will be used.
150 | """
151 | if not service_name:
152 | service_name = service_class.__name__
153 | run_activity(service_class, service_name)
154 |
--------------------------------------------------------------------------------
/templates/service-tabletpage/app/scripts/stk/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.runner.py
3 |
4 | A helper library for making simple standalone python scripts as apps.
5 |
6 | Wraps some NAOqi and system stuff, you could do all this by directly using the
7 | Python SDK, these helper functions just isolate some frequently used/hairy
8 | bits so you don't have them mixed in your logic.
9 | """
10 |
11 | __version__ = "0.1.3"
12 |
13 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
14 | __author__ = 'ekroeger'
15 | __email__ = 'ekroeger@aldebaran.com'
16 |
17 | import sys
18 | import qi
19 | from distutils.version import LooseVersion
20 |
21 | #
22 | # Helpers for making sure we have a robot to connect to
23 | #
24 |
25 |
26 | def check_commandline_args(description):
27 | "Checks whether command-line parameters are enough"
28 | import argparse
29 | parser = argparse.ArgumentParser(description=description)
30 | parser.add_argument('--qi-url', help='connect to specific NAOqi instance')
31 |
32 | args = parser.parse_args()
33 | return args
34 |
35 |
36 | def is_on_robot():
37 | "Returns whether this is being executed on an Aldebaran robot."
38 | import platform
39 | return "aldebaran" in platform.platform()
40 |
41 |
42 | def get_debug_robot():
43 | "Returns IP address of debug robot, complaining if not found"
44 | try:
45 | import qiq.config
46 | qiqrobot = qiq.config.defaultHost()
47 | if qiqrobot:
48 | robot = raw_input(
49 | "connect to which robot? (default is {0}) ".format(qiqrobot))
50 | if robot:
51 | return robot
52 | else:
53 | return qiqrobot
54 | else:
55 | print "qiq found, but it has no default robot configured."
56 | except ImportError:
57 | # qiq not installed
58 | print "qiq not installed (you can use it to set a default robot)."
59 | return raw_input("connect to which robot? ")
60 |
61 |
62 | def init(qi_url=None):
63 | "Returns a QiApplication object, possibly with interactive input."
64 | if qi_url:
65 | sys.argv.extend(["--qi-url", qi_url])
66 | else:
67 | args = check_commandline_args('Run the app.')
68 | if bool(args.qi_url):
69 | qi_url = args.qi_url
70 | elif not is_on_robot():
71 | print "no --qi-url parameter given; interactively getting debug robot."
72 | debug_robot = get_debug_robot()
73 | if debug_robot:
74 | sys.argv.extend(["--qi-url", debug_robot])
75 | qi_url = debug_robot
76 | else:
77 | raise RuntimeError("No robot, not running.")
78 |
79 | qiapp = None
80 | sys.argv[0] = str(sys.argv[0])
81 |
82 | # In versions bellow 2.3, look for --qi-url in the arguemnts and call accordingly the Application
83 | if qi_url and hasattr(qi, "__version__") and LooseVersion(qi.__version__) < LooseVersion("2.3"):
84 | qiapp = qi.Application(url="tcp://"+qi_url+":9559")
85 | # In versions greater than 2.3 the ip can simply be passed through argv[0]
86 | else:
87 | # In some environments sys.argv[0] has unicode, which qi rejects
88 | qiapp = qi.Application()
89 |
90 | qiapp.start()
91 | return qiapp
92 |
93 |
94 | # Main runner
95 |
96 | def run_activity(activity_class, service_name=None):
97 | """Instantiate the given class, and runs it.
98 |
99 | The given class must take a qiapplication object as parameter, and may also
100 | have on_start and on_stop methods, that will be called before and after
101 | running it."""
102 | qiapp = init()
103 | activity = activity_class(qiapp)
104 | service_id = None
105 |
106 | try:
107 | # if it's a service, register it
108 | if service_name:
109 | # Note: this will fail if there is already a service. Unregistering
110 | # it would not be a good practice, because it's process would still
111 | # be running.
112 | service_id = qiapp.session.registerService(service_name, activity)
113 |
114 | if hasattr(activity, "on_start"):
115 | def handle_on_start_done(on_start_future):
116 | "Custom callback, for checking errors"
117 | if on_start_future.hasError():
118 | try:
119 | msg = "Error in on_start(), stopping application: %s" \
120 | % on_start_future.error()
121 | if hasattr(activity, "logger"):
122 | activity.logger.error(msg)
123 | else:
124 | print msg
125 | finally:
126 | qiapp.stop()
127 | qi.async(activity.on_start).addCallback(handle_on_start_done)
128 |
129 | # Run the QiApplication, which runs until someone calls qiapp.stop()
130 | qiapp.run()
131 |
132 | finally:
133 | # Cleanup
134 | if hasattr(activity, "on_stop"):
135 | # We need a qi.async call so that if the class is single threaded,
136 | # it will wait for callbacks to be finished.
137 | qi.async(activity.on_stop).wait()
138 | if service_id:
139 | qiapp.session.unregisterService(service_id)
140 |
141 |
142 | def run_service(service_class, service_name=None):
143 | """Instantiate the given class, and registers it as a NAOqi service.
144 |
145 | The given class must take a qiapplication object as parameter, and may also
146 | have on_start and on_stop methods, that will be called before and after
147 | running it.
148 |
149 | If the service_name parameter is not given, the classes' name will be used.
150 | """
151 | if not service_name:
152 | service_name = service_class.__name__
153 | run_activity(service_class, service_name)
154 |
--------------------------------------------------------------------------------
/templates/service-webpage-nao/app/scripts/stk/runner.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.runner.py
3 |
4 | A helper library for making simple standalone python scripts as apps.
5 |
6 | Wraps some NAOqi and system stuff, you could do all this by directly using the
7 | Python SDK, these helper functions just isolate some frequently used/hairy
8 | bits so you don't have them mixed in your logic.
9 | """
10 |
11 | __version__ = "0.1.3"
12 |
13 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
14 | __author__ = 'ekroeger'
15 | __email__ = 'ekroeger@aldebaran.com'
16 |
17 | import sys
18 | import qi
19 | from distutils.version import LooseVersion
20 |
21 | #
22 | # Helpers for making sure we have a robot to connect to
23 | #
24 |
25 |
26 | def check_commandline_args(description):
27 | "Checks whether command-line parameters are enough"
28 | import argparse
29 | parser = argparse.ArgumentParser(description=description)
30 | parser.add_argument('--qi-url', help='connect to specific NAOqi instance')
31 |
32 | args = parser.parse_args()
33 | return args
34 |
35 |
36 | def is_on_robot():
37 | "Returns whether this is being executed on an Aldebaran robot."
38 | import platform
39 | return "aldebaran" in platform.platform()
40 |
41 |
42 | def get_debug_robot():
43 | "Returns IP address of debug robot, complaining if not found"
44 | try:
45 | import qiq.config
46 | qiqrobot = qiq.config.defaultHost()
47 | if qiqrobot:
48 | robot = raw_input(
49 | "connect to which robot? (default is {0}) ".format(qiqrobot))
50 | if robot:
51 | return robot
52 | else:
53 | return qiqrobot
54 | else:
55 | print "qiq found, but it has no default robot configured."
56 | except ImportError:
57 | # qiq not installed
58 | print "qiq not installed (you can use it to set a default robot)."
59 | return raw_input("connect to which robot? ")
60 |
61 |
62 | def init(qi_url=None):
63 | "Returns a QiApplication object, possibly with interactive input."
64 | if qi_url:
65 | sys.argv.extend(["--qi-url", qi_url])
66 | else:
67 | args = check_commandline_args('Run the app.')
68 | if bool(args.qi_url):
69 | qi_url = args.qi_url
70 | elif not is_on_robot():
71 | print "no --qi-url parameter given; interactively getting debug robot."
72 | debug_robot = get_debug_robot()
73 | if debug_robot:
74 | sys.argv.extend(["--qi-url", debug_robot])
75 | qi_url = debug_robot
76 | else:
77 | raise RuntimeError("No robot, not running.")
78 |
79 | qiapp = None
80 | sys.argv[0] = str(sys.argv[0])
81 |
82 | # In versions bellow 2.3, look for --qi-url in the arguemnts and call accordingly the Application
83 | if qi_url and hasattr(qi, "__version__") and LooseVersion(qi.__version__) < LooseVersion("2.3"):
84 | qiapp = qi.Application(url="tcp://"+qi_url+":9559")
85 | # In versions greater than 2.3 the ip can simply be passed through argv[0]
86 | else:
87 | # In some environments sys.argv[0] has unicode, which qi rejects
88 | qiapp = qi.Application()
89 |
90 | qiapp.start()
91 | return qiapp
92 |
93 |
94 | # Main runner
95 |
96 | def run_activity(activity_class, service_name=None):
97 | """Instantiate the given class, and runs it.
98 |
99 | The given class must take a qiapplication object as parameter, and may also
100 | have on_start and on_stop methods, that will be called before and after
101 | running it."""
102 | qiapp = init()
103 | activity = activity_class(qiapp)
104 | service_id = None
105 |
106 | try:
107 | # if it's a service, register it
108 | if service_name:
109 | # Note: this will fail if there is already a service. Unregistering
110 | # it would not be a good practice, because it's process would still
111 | # be running.
112 | service_id = qiapp.session.registerService(service_name, activity)
113 |
114 | if hasattr(activity, "on_start"):
115 | def handle_on_start_done(on_start_future):
116 | "Custom callback, for checking errors"
117 | if on_start_future.hasError():
118 | try:
119 | msg = "Error in on_start(), stopping application: %s" \
120 | % on_start_future.error()
121 | if hasattr(activity, "logger"):
122 | activity.logger.error(msg)
123 | else:
124 | print msg
125 | finally:
126 | qiapp.stop()
127 | qi.async(activity.on_start).addCallback(handle_on_start_done)
128 |
129 | # Run the QiApplication, which runs until someone calls qiapp.stop()
130 | qiapp.run()
131 |
132 | finally:
133 | # Cleanup
134 | if hasattr(activity, "on_stop"):
135 | # We need a qi.async call so that if the class is single threaded,
136 | # it will wait for callbacks to be finished.
137 | qi.async(activity.on_stop).wait()
138 | if service_id:
139 | qiapp.session.unregisterService(service_id)
140 |
141 |
142 | def run_service(service_class, service_name=None):
143 | """Instantiate the given class, and registers it as a NAOqi service.
144 |
145 | The given class must take a qiapplication object as parameter, and may also
146 | have on_start and on_stop methods, that will be called before and after
147 | running it.
148 |
149 | If the service_name parameter is not given, the classes' name will be used.
150 | """
151 | if not service_name:
152 | service_name = service_class.__name__
153 | run_activity(service_class, service_name)
154 |
--------------------------------------------------------------------------------
/templates/pythonapp/app/scripts/stk/events.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.events.py
3 |
4 | Provides misc. wrappers for ALMemory and Signals (using the same syntax for
5 | handling both).
6 | """
7 |
8 | __version__ = "0.1.1"
9 |
10 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
11 | __author__ = 'ekroeger'
12 | __email__ = 'ekroeger@aldebaran.com'
13 |
14 | import qi
15 |
16 |
17 | def on(*keys):
18 | """Decorator for connecting a callback to one or several events.
19 |
20 | Usage:
21 |
22 | class O:
23 | @on("MyMemoryKey")
24 | def my_callback(self,value):
25 | print "I was called!", value
26 |
27 | o = O()
28 | events = EventsHelper()
29 | events.connect_decorators(o)
30 |
31 | After that, whenever MyMemoryKey is raised, o.my_callback will be called
32 | with the value.
33 | """
34 | def decorator(func):
35 | func.__event_keys__ = keys
36 | return func
37 | return decorator
38 |
39 |
40 | class EventHelper(object):
41 | "Helper for ALMemory; takes care of event connections so you don't have to"
42 |
43 | def __init__(self, session=None):
44 | self.session = None
45 | self.almemory = None
46 | if session:
47 | self.init(session)
48 | self.handlers = {} # a handler is (subscriber, connections)
49 | self.subscriber_names = {}
50 | self.wait_value = None
51 | self.wait_promise = None
52 |
53 | def init(self, session):
54 | "Sets the NAOqi session, if it wasn't passed to the constructor"
55 | self.session = session
56 | self.almemory = session.service("ALMemory")
57 |
58 | def connect_decorators(self, obj):
59 | "Connects all decorated methods of target object."
60 | for membername in dir(obj):
61 | member = getattr(obj, membername)
62 | if hasattr(member, "__event_keys__"):
63 | for event in member.__event_keys__:
64 | self.connect(event, member)
65 |
66 | def connect(self, event, callback):
67 | """Connects an ALMemory event or signal to a callback.
68 |
69 | Note that some events trigger side effects in services when someone
70 | subscribes to them (such as WordRecognized). Those will *not* be
71 | triggered by this function, for those, use .subscribe().
72 | """
73 | if event not in self.handlers:
74 | if "." in event:
75 | # if we have more than one ".":
76 | service_name, signal_name = event.split(".")
77 | service = self.session.service(service_name)
78 | self.handlers[event] = (getattr(service, signal_name), [])
79 | else:
80 | # It's a "normal" ALMemory event.
81 | self.handlers[event] = (
82 | self.almemory.subscriber(event).signal, [])
83 | signal, connections = self.handlers[event]
84 | connection_id = signal.connect(callback)
85 | connections.append(connection_id)
86 | return connection_id
87 |
88 | def subscribe(self, event, attachedname, callback):
89 | """Subscribes to an ALMemory event so as to notify providers.
90 |
91 | This is necessary for things like WordRecognized."""
92 | connection_id = self.connect(event, callback)
93 | dummyname = "on_" + event.replace("/", "")
94 | self.almemory.subscribeToEvent(event, attachedname, dummyname)
95 | self.subscriber_names[event] = attachedname
96 | return connection_id
97 |
98 | def disconnect(self, event, connection_id=None):
99 | "Disconnects a connection, or all if no connection is specified."
100 | if event in self.handlers:
101 | signal, connections = self.handlers[event]
102 | if connection_id:
103 | if connection_id in connections:
104 | signal.disconnect(connection_id)
105 | connections.remove(connection_id)
106 | else:
107 | # Didn't specify a connection ID: remove all
108 | for connection_id in connections:
109 | signal.disconnect(connection_id)
110 | del connections[:]
111 | if event in self.subscriber_names:
112 | name = self.subscriber_names[event]
113 | self.almemory.unsubscribeToEvent(event, name)
114 | del self.subscriber_names[event]
115 |
116 | def clear(self):
117 | "Disconnect all connections"
118 | for event in list(self.handlers):
119 | self.disconnect(event)
120 |
121 | def get(self, key):
122 | "Gets ALMemory value."
123 | return self.almemory.getData(key)
124 |
125 | def get_int(self, key):
126 | "Gets ALMemory value, cast as int."
127 | try:
128 | return int(self.get(key))
129 | except RuntimeError:
130 | # Key doesn't exist
131 | return 0
132 | except ValueError:
133 | # Key exists, but can't be parsed to int
134 | return 0
135 |
136 | def set(self, key, value):
137 | "Sets value of ALMemory key."
138 | return self.almemory.raiseEvent(key, value)
139 |
140 | def remove(self, key):
141 | "Remove key from ALMemory."
142 | try:
143 | self.almemory.removeData(key)
144 | except RuntimeError:
145 | pass
146 |
147 | def _on_wait_event(self, value):
148 | "Internal - callback for an event."
149 | if self.wait_promise:
150 | self.wait_promise.setValue(value)
151 | self.wait_promise = None
152 |
153 | def _on_wait_signal(self, *args):
154 | "Internal - callback for a signal."
155 | if self.wait_promise:
156 | self.wait_promise.setValue(args)
157 | self.wait_promise = None
158 |
159 | def cancel_wait(self):
160 | "Cancel the current wait (raises an exception in the waiting thread)"
161 | if self.wait_promise:
162 | self.wait_promise.setCanceled()
163 | self.wait_promise = None
164 |
165 | def wait_for(self, event, subscribe=False):
166 | """Block until a certain event is raised, and returns it's value.
167 |
168 | If you pass subscribe=True, ALMemory.subscribeToEvent will be called
169 | (sometimes necessary for side effects, i.e. WordRecognized).
170 |
171 | This will block a thread so you should avoid doing this too often!
172 | """
173 | if self.wait_promise:
174 | # there was already a wait in progress, cancel it!
175 | self.wait_promise.setCanceled()
176 | self.wait_promise = qi.Promise()
177 | if subscribe:
178 | connection_id = self.subscribe(event, "EVENTHELPER",
179 | self._on_wait_event)
180 | elif "." in event: # it's a signal
181 | connection_id = self.connect(event, self._on_wait_signal)
182 | else:
183 | connection_id = self.connect(event, self._on_wait_event)
184 | try:
185 | result = self.wait_promise.future().value()
186 | finally:
187 | self.disconnect(event, connection_id)
188 | return result
189 |
--------------------------------------------------------------------------------
/templates/app-with-tablet/app/scripts/stk/events.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.events.py
3 |
4 | Provides misc. wrappers for ALMemory and Signals (using the same syntax for
5 | handling both).
6 | """
7 |
8 | __version__ = "0.1.1"
9 |
10 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
11 | __author__ = 'ekroeger'
12 | __email__ = 'ekroeger@aldebaran.com'
13 |
14 | import qi
15 |
16 |
17 | def on(*keys):
18 | """Decorator for connecting a callback to one or several events.
19 |
20 | Usage:
21 |
22 | class O:
23 | @on("MyMemoryKey")
24 | def my_callback(self,value):
25 | print "I was called!", value
26 |
27 | o = O()
28 | events = EventsHelper()
29 | events.connect_decorators(o)
30 |
31 | After that, whenever MyMemoryKey is raised, o.my_callback will be called
32 | with the value.
33 | """
34 | def decorator(func):
35 | func.__event_keys__ = keys
36 | return func
37 | return decorator
38 |
39 |
40 | class EventHelper(object):
41 | "Helper for ALMemory; takes care of event connections so you don't have to"
42 |
43 | def __init__(self, session=None):
44 | self.session = None
45 | self.almemory = None
46 | if session:
47 | self.init(session)
48 | self.handlers = {} # a handler is (subscriber, connections)
49 | self.subscriber_names = {}
50 | self.wait_value = None
51 | self.wait_promise = None
52 |
53 | def init(self, session):
54 | "Sets the NAOqi session, if it wasn't passed to the constructor"
55 | self.session = session
56 | self.almemory = session.service("ALMemory")
57 |
58 | def connect_decorators(self, obj):
59 | "Connects all decorated methods of target object."
60 | for membername in dir(obj):
61 | member = getattr(obj, membername)
62 | if hasattr(member, "__event_keys__"):
63 | for event in member.__event_keys__:
64 | self.connect(event, member)
65 |
66 | def connect(self, event, callback):
67 | """Connects an ALMemory event or signal to a callback.
68 |
69 | Note that some events trigger side effects in services when someone
70 | subscribes to them (such as WordRecognized). Those will *not* be
71 | triggered by this function, for those, use .subscribe().
72 | """
73 | if event not in self.handlers:
74 | if "." in event:
75 | # if we have more than one ".":
76 | service_name, signal_name = event.split(".")
77 | service = self.session.service(service_name)
78 | self.handlers[event] = (getattr(service, signal_name), [])
79 | else:
80 | # It's a "normal" ALMemory event.
81 | self.handlers[event] = (
82 | self.almemory.subscriber(event).signal, [])
83 | signal, connections = self.handlers[event]
84 | connection_id = signal.connect(callback)
85 | connections.append(connection_id)
86 | return connection_id
87 |
88 | def subscribe(self, event, attachedname, callback):
89 | """Subscribes to an ALMemory event so as to notify providers.
90 |
91 | This is necessary for things like WordRecognized."""
92 | connection_id = self.connect(event, callback)
93 | dummyname = "on_" + event.replace("/", "")
94 | self.almemory.subscribeToEvent(event, attachedname, dummyname)
95 | self.subscriber_names[event] = attachedname
96 | return connection_id
97 |
98 | def disconnect(self, event, connection_id=None):
99 | "Disconnects a connection, or all if no connection is specified."
100 | if event in self.handlers:
101 | signal, connections = self.handlers[event]
102 | if connection_id:
103 | if connection_id in connections:
104 | signal.disconnect(connection_id)
105 | connections.remove(connection_id)
106 | else:
107 | # Didn't specify a connection ID: remove all
108 | for connection_id in connections:
109 | signal.disconnect(connection_id)
110 | del connections[:]
111 | if event in self.subscriber_names:
112 | name = self.subscriber_names[event]
113 | self.almemory.unsubscribeToEvent(event, name)
114 | del self.subscriber_names[event]
115 |
116 | def clear(self):
117 | "Disconnect all connections"
118 | for event in list(self.handlers):
119 | self.disconnect(event)
120 |
121 | def get(self, key):
122 | "Gets ALMemory value."
123 | return self.almemory.getData(key)
124 |
125 | def get_int(self, key):
126 | "Gets ALMemory value, cast as int."
127 | try:
128 | return int(self.get(key))
129 | except RuntimeError:
130 | # Key doesn't exist
131 | return 0
132 | except ValueError:
133 | # Key exists, but can't be parsed to int
134 | return 0
135 |
136 | def set(self, key, value):
137 | "Sets value of ALMemory key."
138 | return self.almemory.raiseEvent(key, value)
139 |
140 | def remove(self, key):
141 | "Remove key from ALMemory."
142 | try:
143 | self.almemory.removeData(key)
144 | except RuntimeError:
145 | pass
146 |
147 | def _on_wait_event(self, value):
148 | "Internal - callback for an event."
149 | if self.wait_promise:
150 | self.wait_promise.setValue(value)
151 | self.wait_promise = None
152 |
153 | def _on_wait_signal(self, *args):
154 | "Internal - callback for a signal."
155 | if self.wait_promise:
156 | self.wait_promise.setValue(args)
157 | self.wait_promise = None
158 |
159 | def cancel_wait(self):
160 | "Cancel the current wait (raises an exception in the waiting thread)"
161 | if self.wait_promise:
162 | self.wait_promise.setCanceled()
163 | self.wait_promise = None
164 |
165 | def wait_for(self, event, subscribe=False):
166 | """Block until a certain event is raised, and returns it's value.
167 |
168 | If you pass subscribe=True, ALMemory.subscribeToEvent will be called
169 | (sometimes necessary for side effects, i.e. WordRecognized).
170 |
171 | This will block a thread so you should avoid doing this too often!
172 | """
173 | if self.wait_promise:
174 | # there was already a wait in progress, cancel it!
175 | self.wait_promise.setCanceled()
176 | self.wait_promise = qi.Promise()
177 | if subscribe:
178 | connection_id = self.subscribe(event, "EVENTHELPER",
179 | self._on_wait_event)
180 | elif "." in event: # it's a signal
181 | connection_id = self.connect(event, self._on_wait_signal)
182 | else:
183 | connection_id = self.connect(event, self._on_wait_event)
184 | try:
185 | result = self.wait_promise.future().value()
186 | finally:
187 | self.disconnect(event, connection_id)
188 | return result
189 |
--------------------------------------------------------------------------------
/templates/dialog-service/app/scripts/stk/events.py:
--------------------------------------------------------------------------------
1 | """
2 | stk.events.py
3 |
4 | Provides misc. wrappers for ALMemory and Signals (using the same syntax for
5 | handling both).
6 | """
7 |
8 | __version__ = "0.1.1"
9 |
10 | __copyright__ = "Copyright 2015, Aldebaran Robotics"
11 | __author__ = 'ekroeger'
12 | __email__ = 'ekroeger@aldebaran.com'
13 |
14 | import qi
15 |
16 |
17 | def on(*keys):
18 | """Decorator for connecting a callback to one or several events.
19 |
20 | Usage:
21 |
22 | class O:
23 | @on("MyMemoryKey")
24 | def my_callback(self,value):
25 | print "I was called!", value
26 |
27 | o = O()
28 | events = EventsHelper()
29 | events.connect_decorators(o)
30 |
31 | After that, whenever MyMemoryKey is raised, o.my_callback will be called
32 | with the value.
33 | """
34 | def decorator(func):
35 | func.__event_keys__ = keys
36 | return func
37 | return decorator
38 |
39 |
40 | class EventHelper(object):
41 | "Helper for ALMemory; takes care of event connections so you don't have to"
42 |
43 | def __init__(self, session=None):
44 | self.session = None
45 | self.almemory = None
46 | if session:
47 | self.init(session)
48 | self.handlers = {} # a handler is (subscriber, connections)
49 | self.subscriber_names = {}
50 | self.wait_value = None
51 | self.wait_promise = None
52 |
53 | def init(self, session):
54 | "Sets the NAOqi session, if it wasn't passed to the constructor"
55 | self.session = session
56 | self.almemory = session.service("ALMemory")
57 |
58 | def connect_decorators(self, obj):
59 | "Connects all decorated methods of target object."
60 | for membername in dir(obj):
61 | member = getattr(obj, membername)
62 | if hasattr(member, "__event_keys__"):
63 | for event in member.__event_keys__:
64 | self.connect(event, member)
65 |
66 | def connect(self, event, callback):
67 | """Connects an ALMemory event or signal to a callback.
68 |
69 | Note that some events trigger side effects in services when someone
70 | subscribes to them (such as WordRecognized). Those will *not* be
71 | triggered by this function, for those, use .subscribe().
72 | """
73 | if event not in self.handlers:
74 | if "." in event:
75 | # if we have more than one ".":
76 | service_name, signal_name = event.split(".")
77 | service = self.session.service(service_name)
78 | self.handlers[event] = (getattr(service, signal_name), [])
79 | else:
80 | # It's a "normal" ALMemory event.
81 | self.handlers[event] = (
82 | self.almemory.subscriber(event).signal, [])
83 | signal, connections = self.handlers[event]
84 | connection_id = signal.connect(callback)
85 | connections.append(connection_id)
86 | return connection_id
87 |
88 | def subscribe(self, event, attachedname, callback):
89 | """Subscribes to an ALMemory event so as to notify providers.
90 |
91 | This is necessary for things like WordRecognized."""
92 | connection_id = self.connect(event, callback)
93 | dummyname = "on_" + event.replace("/", "")
94 | self.almemory.subscribeToEvent(event, attachedname, dummyname)
95 | self.subscriber_names[event] = attachedname
96 | return connection_id
97 |
98 | def disconnect(self, event, connection_id=None):
99 | "Disconnects a connection, or all if no connection is specified."
100 | if event in self.handlers:
101 | signal, connections = self.handlers[event]
102 | if connection_id:
103 | if connection_id in connections:
104 | signal.disconnect(connection_id)
105 | connections.remove(connection_id)
106 | else:
107 | # Didn't specify a connection ID: remove all
108 | for connection_id in connections:
109 | signal.disconnect(connection_id)
110 | del connections[:]
111 | if event in self.subscriber_names:
112 | name = self.subscriber_names[event]
113 | self.almemory.unsubscribeToEvent(event, name)
114 | del self.subscriber_names[event]
115 |
116 | def clear(self):
117 | "Disconnect all connections"
118 | for event in list(self.handlers):
119 | self.disconnect(event)
120 |
121 | def get(self, key):
122 | "Gets ALMemory value."
123 | return self.almemory.getData(key)
124 |
125 | def get_int(self, key):
126 | "Gets ALMemory value, cast as int."
127 | try:
128 | return int(self.get(key))
129 | except RuntimeError:
130 | # Key doesn't exist
131 | return 0
132 | except ValueError:
133 | # Key exists, but can't be parsed to int
134 | return 0
135 |
136 | def set(self, key, value):
137 | "Sets value of ALMemory key."
138 | return self.almemory.raiseEvent(key, value)
139 |
140 | def remove(self, key):
141 | "Remove key from ALMemory."
142 | try:
143 | self.almemory.removeData(key)
144 | except RuntimeError:
145 | pass
146 |
147 | def _on_wait_event(self, value):
148 | "Internal - callback for an event."
149 | if self.wait_promise:
150 | self.wait_promise.setValue(value)
151 | self.wait_promise = None
152 |
153 | def _on_wait_signal(self, *args):
154 | "Internal - callback for a signal."
155 | if self.wait_promise:
156 | self.wait_promise.setValue(args)
157 | self.wait_promise = None
158 |
159 | def cancel_wait(self):
160 | "Cancel the current wait (raises an exception in the waiting thread)"
161 | if self.wait_promise:
162 | self.wait_promise.setCanceled()
163 | self.wait_promise = None
164 |
165 | def wait_for(self, event, subscribe=False):
166 | """Block until a certain event is raised, and returns it's value.
167 |
168 | If you pass subscribe=True, ALMemory.subscribeToEvent will be called
169 | (sometimes necessary for side effects, i.e. WordRecognized).
170 |
171 | This will block a thread so you should avoid doing this too often!
172 | """
173 | if self.wait_promise:
174 | # there was already a wait in progress, cancel it!
175 | self.wait_promise.setCanceled()
176 | self.wait_promise = qi.Promise()
177 | if subscribe:
178 | connection_id = self.subscribe(event, "EVENTHELPER",
179 | self._on_wait_event)
180 | elif "." in event: # it's a signal
181 | connection_id = self.connect(event, self._on_wait_signal)
182 | else:
183 | connection_id = self.connect(event, self._on_wait_event)
184 | try:
185 | result = self.wait_promise.future().value()
186 | finally:
187 | self.disconnect(event, connection_id)
188 | return result
189 |
--------------------------------------------------------------------------------