Skip to content

Commit ff5ee6e

Browse files
committed
merge pr #148
2 parents 41883e4 + a96b5ac commit ff5ee6e

24 files changed

+980
-4
lines changed

Architectural_Spike.png

48.6 KB
Loading

api.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from config import Config
1616
from coderbotTestUnit import run_test as runCoderbotTestUnit
1717
import pigpio
18+
from musicPackages import MusicPackageManager
1819

1920
BUTTON_PIN = 16
2021

@@ -179,6 +180,25 @@ def updateFromPackage():
179180
os.system('sudo reboot')
180181
return 200
181182

183+
def updatePackages():
184+
"""
185+
Add a musical package an save the list of available packages on disk
186+
also add sounds and directory
187+
"""
188+
"""zipName = request.args.get("zipname")
189+
"""
190+
file_to_upload = connexion.request.files['file_to_upload']
191+
print("adding " +str(file_to_upload))
192+
print("adding " + file_to_upload.filename)
193+
file_to_upload.save(os.path.join('./updatePackages/', file_to_upload.filename))
194+
musicPkg = MusicPackageManager.get_instance()
195+
response = musicPkg.addPackage(file_to_upload.filename)
196+
if response == 1:
197+
return 200
198+
elif response == 2:
199+
return 2
200+
elif response == 3:
201+
return 3
182202

183203

184204
## Programs
@@ -252,4 +272,4 @@ def reset():
252272
def testCoderbot(data):
253273
# taking first JSON key value (varargin)
254274
tests_state = runCoderbotTestUnit(data[list(data.keys())[0]])
255-
return tests_state
275+
return tests_state

audioControls.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# CoderBot, a didactical programmable robot.
2+
# Copyright (C) 2014, 2015 Roberto Previtera <info@coderbot.org>
3+
#
4+
# This program is free software; you can redistribute it and/or modify
5+
# it under the terms of the GNU General Public License as published by
6+
# the Free Software Foundation; either version 2 of the License, or
7+
# (at your option) any later version.
8+
#
9+
# This program is distributed in the hope that it will be useful,
10+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
# GNU General Public License for more details.
13+
#
14+
# You should have received a copy of the GNU General Public License along
15+
# with this program; if not, write to the Free Software Foundation, Inc.,
16+
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17+
############################################################################
18+
# CoderBot, a didactical programmable robot.
19+
# Copyright (C) 2014, 2015 Roberto Previtera <info@coderbot.org>
20+
#
21+
# MUSICAL EXTENTION for CoderBot
22+
# This extention is develop by:
23+
# Michele Carbonera - miki_992@hotmail.it - m.carbonera@campus.unimib.it - michele.carbonera@unimib.it
24+
# Antonino Tramontana - a.tramontana1@campus.unimib.it
25+
# Copyright (C) 2020
26+
############################################################################
27+
28+
import os
29+
import alsaaudio
30+
31+
class AudioCtrl:
32+
mixer = None
33+
_instance = None
34+
35+
@classmethod
36+
def get_instance(cls):
37+
if cls._instance is None:
38+
cls._instance = AudioCtrl()
39+
return cls._instance
40+
41+
def __init__(self):
42+
self.mixer = alsaaudio.Mixer('PCM', cardindex=1)
43+
#self.mixer = alsaaudio.PCM(device='numid=1', cardindex=1)
44+
45+
def getVolume(self):
46+
print(self.mixer.getvolume())
47+
48+
def setVolume(self,valueVolume):
49+
self.mixer.setvolume(valueVolume)
50+
'''
51+
if __name__ == "__main__":
52+
a = AudioCtrl()
53+
a.setVolume(20)
54+
#a.setVolume(100)'''

coderbot.cfg

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,40 @@
1-
{"move_power_angle_3": "60", "cnn_default_model": "generic_fast_low", "prog_maxblocks": "-1", "camera_jpeg_quality": "5", "show_page_control": "true", "camera_framerate": "30", "prog_scrollbars": "true", "move_fw_speed": "100", "prog_level": "adv", "move_motor_trim": "1", "move_motor_mode": "dc", "cv_image_factor": "2", "move_power_angle_1": "45", "camera_path_object_size_min": "4000", "button_func": "none", "camera_color_object_size_min": "4000", "camera_jpeg_bitrate": "1000000", "move_fw_elapse": "1", "show_control_move_commands": "true", "camera_color_object_size_max": "160000", "show_page_prefs": "true", "camera_exposure_mode": "auto", "ctrl_tr_elapse": "-1", "show_page_program": "true", "move_tr_elapse": "0.5", "camera_path_object_size_max": "160000", "sound_shutter": "$shutter.mp3", "ctrl_fw_elapse": "-1", "sound_stop": "$shutdown.mp3", "ctrl_tr_speed": "80", "ctrl_fw_speed": "100", "move_tr_speed": "85", "move_power_angle_2": "60", "ctrl_hud_image": "", "load_at_start": "", "sound_start": "$startup.mp3", "encoder": "True"}
1+
{
2+
"move_power_angle_3":"60",
3+
"cnn_default_model":"generic_fast_low",
4+
"prog_maxblocks":"-1",
5+
"camera_jpeg_quality":"5",
6+
"show_page_control":"true",
7+
"camera_framerate":"30",
8+
"prog_scrollbars":"true",
9+
"move_fw_speed":"100",
10+
"prog_level":"adv",
11+
"move_motor_trim":"1",
12+
"move_motor_mode":"dc",
13+
"cv_image_factor":"2",
14+
"move_power_angle_1":"45",
15+
"camera_path_object_size_min":"4000",
16+
"button_func":"none",
17+
"camera_color_object_size_min":"4000",
18+
"camera_jpeg_bitrate":"1000000",
19+
"move_fw_elapse":"1",
20+
"show_control_move_commands":"true",
21+
"camera_color_object_size_max":"160000",
22+
"show_page_prefs":"true",
23+
"camera_exposure_mode":"auto",
24+
"ctrl_tr_elapse":"-1",
25+
"show_page_program":"true",
26+
"move_tr_elapse":"0.5",
27+
"camera_path_object_size_max":"160000",
28+
"sound_shutter":"$shutter.mp3",
29+
"ctrl_fw_elapse":"-1",
30+
"sound_stop":"$shutdown.mp3",
31+
"ctrl_tr_speed":"80",
32+
"ctrl_fw_speed":"100",
33+
"move_tr_speed":"85",
34+
"move_power_angle_2":"60",
35+
"ctrl_hud_image":"",
36+
"load_at_start":"",
37+
"sound_start":"$startup.mp3",
38+
"encoder":"True",
39+
"audio_volume_level":"100"
40+
}

data/program_cat_follower.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"name": "cat_follower", "dom_code": "<xml xmlns=\"https://developers.google.com/blockly/xml\"><variables><variable id=\",?YI{f}$o~t3-v%!oOh`\">object</variable><variable id=\"9layCHw;-1P!)]pX+m2W\">class</variable><variable id=\"80w]HhW?e7QM%yfJ*[BS\">position</variable><variable id=\"fRn/=2s}a[[jcCloxlyH\">pos_x</variable></variables><block type=\"controls_whileUntil\" id=\"[^a!+/Zsc!iXdJ*Z-Go#\" x=\"43\" y=\"19\"><field name=\"MODE\">WHILE</field><value name=\"BOOL\"><block type=\"logic_boolean\" id=\"2Qi5#s+x(vg-{l2glVGI\"><field name=\"BOOL\">TRUE</field></block></value><statement name=\"DO\"><block type=\"variables_set\" id=\"0Y_GS_fw!h^YTb,XeKz#\"><field name=\"VAR\" id=\",?YI{f}$o~t3-v%!oOh`\">object</field><value name=\"VALUE\"><block type=\"lists_getIndex\" id=\"_GYqAA5bQtVd@ICQGW(U\"><mutation statement=\"false\" at=\"false\"></mutation><field name=\"MODE\">GET</field><field name=\"WHERE\">FIRST</field><value name=\"VALUE\"><block type=\"coderbot_adv_cnn_detect_objects\" id=\"m(x+AUHK}k[f:xAb;!iH\"><field name=\"MODEL\">generic_object_detect</field></block></value></block></value><next><block type=\"variables_set\" id=\":mq1jiC7D(V_yjV]p+bj\"><field name=\"VAR\" id=\"9layCHw;-1P!)]pX+m2W\">class</field><value name=\"VALUE\"><block type=\"lists_getIndex\" id=\"gg?Rm?i]1V[@Sk0~,6}U\"><mutation statement=\"false\" at=\"false\"></mutation><field name=\"MODE\">GET</field><field name=\"WHERE\">FIRST</field><value name=\"VALUE\"><block type=\"variables_get\" id=\"jWBE:9@+HD)M5w(R6-+R\"><field name=\"VAR\" id=\",?YI{f}$o~t3-v%!oOh`\">object</field></block></value></block></value><next><block type=\"controls_if\" id=\"SoONo/Qzd^PSRs3kDLW4\"><mutation else=\"1\"></mutation><value name=\"IF0\"><block type=\"logic_compare\" id=\"girWO4BMe2k@24#mK9W|\"><field name=\"OP\">EQ</field><value name=\"A\"><block type=\"variables_get\" id=\"9oEqGs$i`cb!|tDMGcUs\"><field name=\"VAR\" id=\"9layCHw;-1P!)]pX+m2W\">class</field></block></value><value name=\"B\"><block type=\"text\" id=\"57hUIBHt5-};Ur^Ym(`p\"><field name=\"TEXT\">cat</field></block></value></block></value><statement name=\"DO0\"><block type=\"variables_set\" id=\":krqJ`zM+j//B~motZ@5\"><field name=\"VAR\" id=\"80w]HhW?e7QM%yfJ*[BS\">position</field><value name=\"VALUE\"><block type=\"lists_getIndex\" id=\"n*i|7Ey@DqvX+8X;^2fb\"><mutation statement=\"false\" at=\"true\"></mutation><field name=\"MODE\">GET</field><field name=\"WHERE\">FROM_START</field><value name=\"VALUE\"><block type=\"variables_get\" id=\"$p#z76Ff-*8z$I:6(%:F\"><field name=\"VAR\" id=\",?YI{f}$o~t3-v%!oOh`\">object</field></block></value><value name=\"AT\"><block type=\"math_number\" id=\"?s]?2J@-Pc6i1f-y{[09\"><field name=\"NUM\">3</field></block></value></block></value><next><block type=\"variables_set\" id=\"[:tR1VyS6qeSU?!D)`sN\"><field name=\"VAR\" id=\"fRn/=2s}a[[jcCloxlyH\">pos_x</field><value name=\"VALUE\"><block type=\"math_arithmetic\" id=\"*U,nQR1[HxPKn8W%pkCz\"><field name=\"OP\">DIVIDE</field><value name=\"A\"><block type=\"math_arithmetic\" id=\"uc.~ggYr?xqXV/.F7s1u\"><field name=\"OP\">ADD</field><value name=\"A\"><block type=\"lists_getIndex\" id=\"kuISxM{Klu36vQ]Jo+P@\"><mutation statement=\"false\" at=\"true\"></mutation><field name=\"MODE\">GET</field><field name=\"WHERE\">FROM_START</field><value name=\"VALUE\"><block type=\"variables_get\" id=\"?gyq($9~Uq.~3XY8_J9)\"><field name=\"VAR\" id=\"80w]HhW?e7QM%yfJ*[BS\">position</field></block></value><value name=\"AT\"><block type=\"math_number\" id=\"(1G%d4(*1Vqq?1xk.^{t\"><field name=\"NUM\">1</field></block></value></block></value><value name=\"B\"><block type=\"lists_getIndex\" id=\".Xk?/{p+tLXc=}|OA82n\"><mutation statement=\"false\" at=\"true\"></mutation><field name=\"MODE\">GET</field><field name=\"WHERE\">FROM_START</field><value name=\"VALUE\"><block type=\"variables_get\" id=\"|IdyV?|5py+=3,0!:z_A\"><field name=\"VAR\" id=\"80w]HhW?e7QM%yfJ*[BS\">position</field></block></value><value name=\"AT\"><block type=\"math_number\" id=\",Me8:/`3uBpfuBZrA)sp\"><field name=\"NUM\">3</field></block></value></block></value></block></value><value name=\"B\"><block type=\"math_number\" id=\"m~K8F`G6T$ha/a^LdD5Z\"><field name=\"NUM\">2</field></block></value></block></value><next><block type=\"text_print\" id=\"|,^zQ|VUQq/(lt,K`8y0\"><value name=\"TEXT\"><block type=\"variables_get\" id=\"#QdSbUp(4Hn;Xk(4xe0G\"><field name=\"VAR\" id=\"9layCHw;-1P!)]pX+m2W\">class</field></block></value><next><block type=\"controls_if\" id=\"}1i(Om9l5~9.WOIq!=W`\"><mutation elseif=\"1\" else=\"1\"></mutation><value name=\"IF0\"><block type=\"logic_compare\" id=\"~.k].tdW8FF4#-(AeXsM\"><field name=\"OP\">LT</field><value name=\"A\"><block type=\"variables_get\" id=\")KUmL+N6#~?rM~GnqH[G\"><field name=\"VAR\" id=\"fRn/=2s}a[[jcCloxlyH\">pos_x</field></block></value><value name=\"B\"><block type=\"math_number\" id=\"l*=6l=SR/g6%(|]$i;}C\"><field name=\"NUM\">40</field></block></value></block></value><statement name=\"DO0\"><block type=\"coderbot_adv_move\" id=\":YSGyu*XL_u{)zQBD:{X\"><field name=\"ACTION\">LEFT</field><value name=\"SPEED\"><block type=\"math_number\" id=\"de??^JX,i_mkb$RsmNXs\"><field name=\"NUM\">60</field></block></value><value name=\"ELAPSE\"><block type=\"math_number\" id=\"zs-Cre_[w%5@VNoMwi;l\"><field name=\"NUM\">0.1</field></block></value></block></statement><value name=\"IF1\"><block type=\"logic_compare\" id=\"+S5!K$WfFhj@QhRSokhV\"><field name=\"OP\">GT</field><value name=\"A\"><block type=\"variables_get\" id=\"J%|{#:u3(!lcF4.B~gQt\"><field name=\"VAR\" id=\"fRn/=2s}a[[jcCloxlyH\">pos_x</field></block></value><value name=\"B\"><block type=\"math_number\" id=\"[gg?3(+hO-?.%qW,`@t~\"><field name=\"NUM\">60</field></block></value></block></value><statement name=\"DO1\"><block type=\"coderbot_adv_move\" id=\"vA*_d?-Bwh55o,{*%v:G\"><field name=\"ACTION\">RIGHT</field><value name=\"SPEED\"><block type=\"math_number\" id=\"W}pFMYn/}2RnG+E86e~v\"><field name=\"NUM\">60</field></block></value><value name=\"ELAPSE\"><block type=\"math_number\" id=\"as/ZY,XwrTw`@Z~O9B`$\"><field name=\"NUM\">0.1</field></block></value></block></statement><statement name=\"ELSE\"><block type=\"coderbot_adv_move\" id=\"Xs:ewoKw*Fg3UK*sRCNm\"><field name=\"ACTION\">FORWARD</field><value name=\"SPEED\"><block type=\"math_number\" id=\"qSFO9:h}?s~cD:hj(r:(\"><field name=\"NUM\">100</field></block></value><value name=\"ELAPSE\"><block type=\"math_number\" id=\"Nh^fXOiu1$x8[$i1C2IV\"><field name=\"NUM\">0.2</field></block></value></block></statement></block></next></block></next></block></next></block></statement><statement name=\"ELSE\"><block type=\"text_print\" id=\"PAYJ[1S)`0Gl#=M`cX=g\"><value name=\"TEXT\"><block type=\"variables_get\" id=\"2nPmKkqF|Y:u3?r=5y|n\"><field name=\"VAR\" id=\",?YI{f}$o~t3-v%!oOh`\">object</field></block></value></block></statement></block></next></block></next></block></statement></block></xml>", "code": "object2 = None\nclass2 = None\nposition = None\npos_x = None\n\n\nwhile True:\n get_prog_eng().check_end()\n object2 = get_cam().cnn_detect_objects(\"generic_object_detect\")[0]\n class2 = object2[0]\n if class2 == 'cat':\n position = object2[2]\n pos_x = (position[0] + position[2]) / 2\n get_cam().set_text(class2)\n if pos_x < 40:\n get_bot().left(speed=60, elapse=0.1)\n elif pos_x > 60:\n get_bot().right(speed=60, elapse=0.1)\n else:\n get_bot().forward(speed=100, elapse=0.2)\n else:\n get_cam().set_text(object2)\n", "default": false}

dist/static/music_package.json

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
{
2+
"packages": {
3+
"cat": {
4+
"category": "animal",
5+
"name_IT": "gatto",
6+
"name_EN": "cat",
7+
"version": "0.1",
8+
"date": "2020-04-08",
9+
"interface": {
10+
"base": {
11+
"available": "TRUE",
12+
"icon": "cat.png"
13+
},
14+
"intermediate": {
15+
"available": "TRUE",
16+
"icon": "cat.png"
17+
},
18+
"advanced": {
19+
"available": "TRUE",
20+
"icon": "cat.png"
21+
}
22+
}
23+
},
24+
"dog": {
25+
"category": "animal",
26+
"name_IT": "cane",
27+
"name_EN": "dog",
28+
"version": "0.1",
29+
"date": "2020-04-08",
30+
"interface": {
31+
"base": {
32+
"available": "TRUE",
33+
"icon": "dog.png"
34+
},
35+
"intermediate": {
36+
"available": "TRUE",
37+
"icon": "dog.png"
38+
},
39+
"advanced": {
40+
"available": "TRUE",
41+
"icon": "dog.png"
42+
}
43+
}
44+
},
45+
"piano": {
46+
"category": "instrument",
47+
"name_IT": "pianoforte",
48+
"name_EN": "piano",
49+
"version": "0.1",
50+
"date": "2020-04-08",
51+
"interface": {
52+
"base": {
53+
"available": "TRUE",
54+
"icon": "piano.png"
55+
},
56+
"intermediate": {
57+
"available": "TRUE",
58+
"icon": "piano.png"
59+
},
60+
"advanced": {
61+
"available": "TRUE",
62+
"icon": "piano.png"
63+
}
64+
}
65+
},
66+
"guitar": {
67+
"category": "instrument",
68+
"name_IT": "chitarra",
69+
"name_EN": "guitar",
70+
"version": "0.1",
71+
"date": "2020-04-08",
72+
"interface": {
73+
"base": {
74+
"available": "TRUE",
75+
"icon": "guitar.png"
76+
},
77+
"intermediate": {
78+
"available": "TRUE",
79+
"icon": "guitar.png"
80+
},
81+
"advanced": {
82+
"available": "TRUE",
83+
"icon": "guitar.png"
84+
}
85+
}
86+
},
87+
"flute": {
88+
"category": "instrument",
89+
"name_IT": "flauto",
90+
"name_EN": "flute",
91+
"version": "0.1",
92+
"date": "2020-04-08",
93+
"interface": {
94+
"base": {
95+
"available": "TRUE",
96+
"icon": "flute.png"
97+
},
98+
"intermediate": {
99+
"available": "TRUE",
100+
"icon": "flute.png"
101+
},
102+
"advanced": {
103+
"available": "TRUE",
104+
"icon": "flute.png"
105+
}
106+
}
107+
},
108+
"pig": {
109+
"category": "animal",
110+
"name_IT": "maiale",
111+
"name_EN": "pig",
112+
"version": "0.1",
113+
"date": "2020-06-01",
114+
"interface": {
115+
"base": {
116+
"available": "TRUE",
117+
"icon": "pig.png"
118+
},
119+
"intermediate": {
120+
"available": "TRUE",
121+
"icon": "pig.png"
122+
},
123+
"advanced": {
124+
"available": "TRUE",
125+
"icon": "pig.png"
126+
}
127+
}
128+
},
129+
"elephant": {
130+
"category": "animal",
131+
"name_IT": "elefante",
132+
"name_EN": "elephant",
133+
"version": "0.1",
134+
"date": "2020-06-01",
135+
"interface": {
136+
"base": {
137+
"available": "TRUE",
138+
"icon": "elephant.png"
139+
},
140+
"intermediate": {
141+
"available": "TRUE",
142+
"icon": "elephant.png"
143+
},
144+
"advanced": {
145+
"available": "TRUE",
146+
"icon": "elephant.png"
147+
}
148+
}
149+
},
150+
"snake": {
151+
"category": "animal",
152+
"name_IT": "serpente",
153+
"name_EN": "snake",
154+
"version": "0.1",
155+
"date": "2020-06-01",
156+
"interface": {
157+
"base": {
158+
"available": "TRUE",
159+
"icon": "snake.png"
160+
},
161+
"intermediate": {
162+
"available": "TRUE",
163+
"icon": "snake.png"
164+
},
165+
"advanced": {
166+
"available": "TRUE",
167+
"icon": "snake.png"
168+
}
169+
}
170+
}
171+
}
172+
}

main.py

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@
3030
from config import Config
3131
from cnn_manager import CNNManager
3232
from event import EventManager
33-
33+
from audioControls import AudioCtrl
34+
from musicPackages import MusicPackageManager
3435
# Logging configuration
3536
logger = logging.getLogger()
3637
logger.setLevel(logging.INFO)
@@ -59,6 +60,8 @@
5960
app.prog = None
6061
app.shutdown_requested = False
6162

63+
64+
6265
## New API and web application
6366

6467
# API v2 is defined in v2.yml and its methods are in api.py
@@ -153,10 +156,23 @@ def handle_config():
153156
"""
154157
Overwrite configuration file on disk and reload it
155158
"""
159+
audioCtrl = AudioCtrl.get_instance()
160+
audioCtrl.setVolume(int(request.form['audio_volume_level']))
156161
Config.write(updateDict(app.bot_config, request.form))
157162
app.bot_config = Config.get()
158163
return "ok"
159164

165+
@app.route("/deletepkg", methods=["POST"])
166+
def handle_packages():
167+
"""
168+
Delete a musical package an save the list of available packages on disk
169+
also delete package sounds and directory
170+
"""
171+
packageName = request.form.get("nameID")
172+
musicPkg = MusicPackageManager.get_instance()
173+
musicPkg.deletePackage(packageName)
174+
return "package deleted"
175+
160176
@app.route("/config", methods=["GET"])
161177
def returnConfig():
162178
"""
@@ -468,6 +484,10 @@ def run_server():
468484
encoder=bool(app.bot_config.get('encoder')))
469485
audio = Audio.get_instance()
470486
audio.say(app.bot_config.get("sound_start"))
487+
488+
audioCtrl = AudioCtrl.get_instance()
489+
audioCtrl.setVolume(int(app.bot_config.get['audio_volume_level']))
490+
471491
try:
472492
cam = Camera.get_instance()
473493
Motion.get_instance()

0 commit comments

Comments
 (0)