Skip to content

Commit 6b60e04

Browse files
adamcarhedenMarkusBordihn
authored andcommitted
Aiy tutorial (#206)
* Added AIY Examples - Added examples from https://github.com/google/aiyprojects-raspbian as cards on the AIY select screen. - Removed unused 'mkdir' function from tutorial build script. * Added AIY Voice Kit tutorial
1 parent e5b1e35 commit 6b60e04

File tree

19 files changed

+458
-17
lines changed

19 files changed

+458
-17
lines changed

.gitmodules

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,8 @@
105105
path = third_party/coding-with-chrome-libraries
106106
url = https://github.com/google/coding-with-chrome-libraries.git
107107
ignore = dirty
108+
109+
[submodule "third_party/aiyprojects-raspbian"]
110+
path = third_party/aiyprojects-raspbian
111+
url = https://github.com/google/aiyprojects-raspbian.git
112+
ignore = dirty

build/cwc/aiy.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/**
2+
* @fileoverview BUILD configuration for Coding with Chrome AIY examples.
3+
*
4+
* @license Copyright 2018 The Coding with Chrome Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*
18+
* @author [email protected] (Adam Carheden)
19+
* @deprecated This script is a temporary method for creating tutorial files
20+
* until we develop support for editing them.
21+
*/
22+
let fs = require('fs');
23+
let path = require('path');
24+
let makeDir = require('make-dir');
25+
let inDir = path.join(__dirname,
26+
'../../third_party/aiyprojects-raspbian/src/examples');
27+
let outDir = path.join(__dirname,
28+
'./../../genfiles/core/resources/examples/aiy');
29+
30+
let examples = [
31+
'voice/voice_recorder.py',
32+
'voice/assistant_grpc_demo.py',
33+
'vision/joy/joy_detection_demo.py',
34+
'vision/image_classification_camera.py',
35+
'button_led.py',
36+
'leds_example.py',
37+
38+
// TODO(carheden): These don't work with my voice kit, possibly
39+
// due to hardware options
40+
// 'gpiozero/bonnet_button.py',
41+
// 'gpiozero/button_example.py',
42+
// 'gpiozero/led_chaser.py',
43+
// 'gpiozero/led_example.py',
44+
// 'gpiozero/servo_example.py',
45+
// 'gpiozero/simple_button_example.py',
46+
47+
// TODO(carheden): These require API keys, which we can't set up from CwC yet.
48+
// 'buzzer/buzzer_demo.py',
49+
// 'voice/assistant_library_demo.py',
50+
// 'voice/assistant_library_with_button_demo.py',
51+
// 'voice/assistant_library_with_local_commands_demo.py',
52+
// 'voice/cloudspeech_demo.py',
53+
54+
55+
// TODO(carheden): These examples require files in addition to the code.
56+
// Figure out how to push additional files to the AIY or modify them to use
57+
// a single file.
58+
// 'buzzer/buzzer_tracker_demo.py',
59+
// 'vision/object_meter/object_meter.py',
60+
// 'vision/object_meter/wordnet_grouping/mapping_data.py',
61+
// 'vision/object_meter/wordnet_grouping/category_mapper.py',
62+
63+
// TODO(carheden): These expect command line agruments. Modify them to work
64+
// from CwC
65+
// 'vision/any_model_camera.py',
66+
// 'vision/dish_classification.py',
67+
// 'vision/dish_detection.py',
68+
// 'vision/face_detection_camera.py',
69+
// 'vision/face_detection.py',
70+
// 'vision/face_detection_raspivid.py',
71+
// 'vision/image_classification.py',
72+
// 'vision/inaturalist_classification.py',
73+
// 'vision/mobilenet_based_classifier.py',
74+
// 'vision/object_detection.py',
75+
// 'vision/video_capture/video_capture.py',
76+
// 'vision/face_camera_trigger.py',
77+
];
78+
79+
let normalizeTitle = function(title) {
80+
return title.replace(/_/g, ' ')
81+
.replace(/ \w/g, (part) => part.toUpperCase())
82+
.replace(/^\w/g, (part) => part.toUpperCase());
83+
};
84+
85+
/*
86+
* We have to encapsulate python code in for AIY in a .cwc file to
87+
* force it to use the AIY CwC mode mode.
88+
*
89+
* TODO(fstanis/carheden/mbordihn): If user open an AIY python file from the
90+
* menus, they won't be able to use AIY because cwc will load the wrong mode.
91+
* Consider an 'activate AIY' button in the Python mode or something.
92+
*/
93+
let pyToAIYCwc = function(python) {
94+
return {
95+
'content': {
96+
'__python__': {
97+
'content': fs.readFileSync(python, 'utf8'),
98+
'name': '__python__',
99+
'size': fs.statSync(python).size,
100+
'type': 'text/x-python',
101+
'version': 1,
102+
},
103+
},
104+
'files': {},
105+
'flags': {},
106+
'format': 'Coding with Chrome File Format 3',
107+
'frameworks': {},
108+
'history': '',
109+
'metadata': {
110+
'__default__': {
111+
'author': 'AIY Projects Team',
112+
'title': normalizeTitle(path.basename(python, '.py')),
113+
'version': '1.0',
114+
},
115+
},
116+
'mode': 'aiy',
117+
'ui': 'default',
118+
'view': '__python',
119+
};
120+
};
121+
122+
123+
examples.forEach((python) => {
124+
let pythonPath = fs.realpathSync(path.join(inDir, python));
125+
let cwcObject = pyToAIYCwc(pythonPath);
126+
let cwcJSON = JSON.stringify(cwcObject, null, ' ');
127+
let cwcDirFragment = path.dirname(python);
128+
let cwcFileName = path.basename(python, '.py') + '.cwc';
129+
let cwcPath = path.join(outDir, cwcDirFragment, cwcFileName);
130+
makeDir(path.dirname(cwcPath)).then(() => {
131+
fs.writeFile(cwcPath, cwcJSON, (err) => {
132+
if (err) {
133+
throw err;
134+
}
135+
console.log(`\t${pythonPath} ->\n\t\t ${cwcPath}`);
136+
});
137+
});
138+
});

build/cwc/tutorials.js

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,20 +25,6 @@ let makeDir = require('make-dir');
2525
let inDir = fs.realpathSync(__dirname + '/../../static_files/tutorials');
2626
let outDir = fs.realpathSync(__dirname + '/../../genfiles/core/resources');
2727

28-
29-
let mkdir = function(dir) {
30-
if (fs.existsSync(dir)) {
31-
return;
32-
}
33-
try {
34-
fs.mkdirSync(dir);
35-
} catch (e) {
36-
let p = path.dirname(dir);
37-
mkdir(p);
38-
fs.mkdirSync(dir);
39-
}
40-
};
41-
4228
let procTemplates = function(dir, callback) {
4329
fs.readdir(dir, function(err, list) {
4430
if (err) {

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@
3939
"build:cwc": "npm run build:cwc-deps && npm run build:cwc-main",
4040
"build:cwc-blocks": "node build/cwc/blocks.js",
4141
"build:cwc-debug": "npm run build:cwc-deps && npm run build:cwc-main-debug",
42-
"build:cwc-deps": "npm run build:cwc-blocks && npm run build:cwc-frameworks && npm run build:cwc-gss && npm run build:cwc-locales && npm run build:cwc-soy && npm run build:cwc-static-files && npm run build:cwc-tutorials",
42+
"build:cwc-deps": "npm run build:cwc-blocks && npm run build:cwc-frameworks && npm run build:cwc-gss && npm run build:cwc-locales && npm run build:cwc-soy && npm run build:cwc-static-files && npm run build:cwc-tutorials && npm run build:cwc-aiy-examples",
4343
"build:cwc-frameworks": "node build/cwc/frameworks.js",
4444
"build:cwc-gss": "node build/cwc/gss.js",
4545
"build:cwc-locales": "node build/cwc/locales.js",
@@ -50,6 +50,7 @@
5050
"build:cwc-soy": "node build/cwc/soy.js",
5151
"build:cwc-static-files": "node build/cwc/static_files.js",
5252
"build:cwc-tutorials": "node build/cwc/tutorials.js",
53+
"build:cwc-aiy-examples": "node build/cwc/aiy.js",
5354
"build:external": "npm run build:external-frameworks && npm run build:external-extra && npm run build:external-static",
5455
"build:external-extra": "node build/external/extra_files.js",
5556
"build:external-frameworks": "node build/external/frameworks.js",

src/ui/select_screen/advanced/aiy/aiy.soy

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
* Normal overview page.
3131
*/
3232
{template .overview}
33-
3433
{call cwc.soy.SelectScreenTemplate.container}
3534
{param header kind="html"}
3635
{call cwc.soy.SelectScreenTemplate.header}
@@ -41,6 +40,27 @@
4140
{/param}
4241

4342
{param content kind="html"}
43+
{call cwc.soy.SelectScreenTemplate.titleGrid data="all"}
44+
{param text: 'Tutorials...' /}
45+
{param opt_icon: 'school' /}
46+
{/call}
47+
{call cwc.soy.SelectScreenTemplate.fileCardList}
48+
{param content kind="html"}
49+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
50+
{param title: 'AIY Tutorial' /}
51+
{param text: 'Learn to set up and use the AIY voice or vision kit' /}
52+
{param opt_link_text: 'Start Learning' /}
53+
{param tutorial: 'aiy/aiy.cwct' /}
54+
{param opt_color_class: 'bg-orange' /}
55+
{param opt_icon: 'school' /}
56+
{/call}
57+
{/param}
58+
{/call}
59+
60+
{call cwc.soy.SelectScreenTemplate.titleGrid data="all"}
61+
{param text: 'Voice Kit...' /}
62+
{param opt_icon: 'record_voice_over' /}
63+
{/call}
4464
{call cwc.soy.SelectScreenTemplate.fileCardList}
4565
{param content kind="html"}
4666
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
@@ -51,7 +71,31 @@
5171
{param opt_color_class: 'bg-orange' /}
5272
{param opt_icon: 'record_voice_over' /}
5373
{/call}
74+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
75+
{param title: 'Voice Recorder' /}
76+
{param text: 'Record your voice and play it back' /}
77+
{param opt_link_text: 'Start Recording' /}
78+
{param file: 'aiy/voice/voice_recorder.cwc' /}
79+
{param opt_color_class: 'bg-orange' /}
80+
{param opt_icon: 'record_voice_overview' /}
81+
{/call}
82+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
83+
{param title: 'Google Assistant' /}
84+
{param text: 'The Google Assistant will answer all your questions' /}
85+
{param opt_link_text: 'Start Google Assistant' /}
86+
{param file: 'aiy/voice/assistant_grpc_demo.cwc' /}
87+
{param opt_color_class: 'bg-orange' /}
88+
{param opt_icon: 'record_voice_overview' /}
89+
{/call}
90+
{/param}
91+
{/call}
5492

93+
{call cwc.soy.SelectScreenTemplate.titleGrid data="all"}
94+
{param text: 'Vision Kit...' /}
95+
{param opt_icon: 'videocam' /}
96+
{/call}
97+
{call cwc.soy.SelectScreenTemplate.fileCardList}
98+
{param content kind="html"}
5599
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
56100
{param title: 'Vision Kit' /}
57101
{param text: 'Start building for the AIY Vision Kit' /}
@@ -61,10 +105,49 @@
61105
{param opt_color_class: 'bg-orange' /}
62106
{param opt_icon: 'videocam' /}
63107
{/call}
108+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
109+
{param title: 'Joy Detection' /}
110+
{param text: 'AIY will tell you when you are smiling' /}
111+
{param opt_link_text: 'Start Smiling' /}
112+
{param file: 'aiy/vision/joy/joy_detection_demo.cwc' /}
113+
{param opt_color_class: 'bg-orange' /}
114+
{param opt_icon: 'videocam' /}
115+
{/call}
116+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
117+
{param title: 'Image Classification' /}
118+
{param text: 'AIY will tell you what it sees' /}
119+
{param opt_link_text: 'Start Classifying' /}
120+
{param file: 'aiy/vision/image_classification_camera.cwc' /}
121+
{param opt_color_class: 'bg-orange' /}
122+
{param opt_icon: 'videocam' /}
123+
{/call}
64124
{/param}
65125
{/call}
66126

127+
{call cwc.soy.SelectScreenTemplate.titleGrid data="all"}
128+
{param text: 'LED Button...' /}
129+
{param opt_icon: 'brightness_5' /}
130+
{/call}
131+
{call cwc.soy.SelectScreenTemplate.fileCardList}
132+
{param content kind="html"}
133+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
134+
{param title: 'Illuminate while pressed' /}
135+
{param text: 'Turn the button on while when it\'s depressed' /}
136+
{param opt_link_text: 'Start Demo' /}
137+
{param file: 'aiy/button_led.cwc' /}
138+
{param opt_color_class: 'bg-orange' /}
139+
{param opt_icon: 'brightness_5' /}
140+
{/call}
141+
{call cwc.soy.SelectScreenTemplate.fileCard data="all"}
142+
{param title: 'LED Examples' /}
143+
{param text: 'See all the things you can do with the LED button' /}
144+
{param opt_link_text: 'Start Demo' /}
145+
{param file: 'aiy/leds_example.cwc' /}
146+
{param opt_color_class: 'bg-orange' /}
147+
{param opt_icon: 'brightness_5' /}
148+
{/call}
149+
{/param}
150+
{/call}
67151
{/param}
68152
{/call}
69-
70153
{/template}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"content": {
3+
"__python__": {
4+
"content": "",
5+
"name": "__python__",
6+
"size": 0,
7+
"type": "text/x-python",
8+
"version": 1
9+
}
10+
},
11+
"files": {},
12+
"format": "Coding with Chrome File Format 3.0",
13+
"history": "",
14+
"metadata": {
15+
"__tutorial__": {
16+
"eng": {
17+
"description": {
18+
"___TEMPLATE___:text": "eng/description.md",
19+
"mime_type": "text/markdown"
20+
},
21+
"steps": [
22+
{
23+
"title": "Setup",
24+
"description": {
25+
"___TEMPLATE___:text": "eng/step1/text.md",
26+
"mime_type": "text/markdown"
27+
}
28+
},
29+
{
30+
"title": "Plug it in",
31+
"description": {
32+
"___TEMPLATE___:text": "eng/step2/text.md",
33+
"mime_type": "text/markdown"
34+
},
35+
"images": [
36+
{
37+
"mime_type": "image/jpeg",
38+
"___TEMPLATE___:binary:data": "eng/step2/cabling.jpg"
39+
}
40+
]
41+
},
42+
{
43+
"title": "New Features",
44+
"description": {
45+
"___TEMPLATE___:text": "eng/step3/text.md",
46+
"mime_type": "text/markdown"
47+
},
48+
"___TEMPLATE___:json:tour": "eng/step3/tour.json"
49+
},
50+
{
51+
"title": "Hello, AIY",
52+
"description": {
53+
"___TEMPLATE___:text": "eng/step4/text.md",
54+
"mime_type": "text/markdown"
55+
},
56+
"___TEMPLATE___:code": "eng/step4/code.py"
57+
},
58+
{
59+
"title": "Light it up",
60+
"description": {
61+
"___TEMPLATE___:text": "eng/step5/text.md",
62+
"mime_type": "text/markdown"
63+
},
64+
"___TEMPLATE___:code": "eng/step5/code.py"
65+
}
66+
]
67+
}
68+
},
69+
"__default__": {
70+
"author": "Adam Carheden",
71+
"description": "Instructions on using the AIY Voice or Vision Kit",
72+
"title": "AIY Tutorial",
73+
"version": "1.0"
74+
}
75+
},
76+
"mode": "aiy",
77+
"ui": "default",
78+
"view": "__python__"
79+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### AIY
2+
3+
The AIY [Voice](https://aiyprojects.withgoogle.com/voice/) and
4+
[Vision](https://aiyprojects.withgoogle.com/vision/) kits can recognize speech
5+
and see objects. This tutorial will get you started using them.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
If you haven't already, follow the instructions on setting up your AIY
2+
[Voice](https://aiyprojects.withgoogle.com/voice/#assembly-guide) or
3+
[Vision](https://aiyprojects.withgoogle.com/vision/#assembly-guide) kit. Coding
4+
with Chrome can automatically connect to your AIY through USB, so when you get
5+
to the *Connect to your kit* step, continue with the next step of these
6+
instructions instead.
3.38 MB
Loading

0 commit comments

Comments
 (0)