def test_play_song(self): spkr = Sound() spkr.connector.play_actual_sound = False spkr.play_song(( ('G4', 'h'), # meas 1 ('D5', 'h'), ('C5', 'e3'), # meas 2 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ), tempo=150) self.assertEqual(len(self.clientSocketMock.mock_calls), 7) fn_name, args, kwargs = self.clientSocketMock.mock_calls[0] self.assertEqual(fn_name, 'send_command') self.assertDictEqual(args[0].serialize(), {'type': 'SoundCommand', 'duration': 0.8, 'message': 'Playing note with frequency: 392', 'soundType': 'note'}) fn_name, args, kwargs = self.clientSocketMock.mock_calls[1] self.assertDictEqual(args[0].serialize(), {'type': 'SoundCommand', 'duration': 0.8, 'message': 'Playing note with frequency: 587', 'soundType': 'note'}) fn_name, args, kwargs = self.clientSocketMock.mock_calls[2] self.assertDictEqual(args[0].serialize(), {'type': 'SoundCommand', 'duration': (0.8 / 4) * 2 / 3, # a triplet 'message': 'Playing note with frequency: 523', 'soundType': 'note'})
class MindstormsGadget(AlexaGadget): """ An Mindstorms gadget that will react to the Alexa wake word. """ def __init__(self): """ Performs Alexa Gadget initialization routines and ev3dev resource allocation. """ super().__init__() self.leds = Leds() self.sound = Sound() def on_connected(self, device_addr): """ Gadget connected to the paired Echo device. :param device_addr: the address of the device we connected to """ self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") logger.info("{} connected to Echo device".format(self.friendly_name)) def on_disconnected(self, device_addr): """ Gadget disconnected from the paired Echo device. :param device_addr: the address of the device we disconnected from """ self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") logger.info("{} disconnected from Echo device".format( self.friendly_name)) def on_alexa_gadget_statelistener_stateupdate(self, directive): """ Listens for the wakeword state change and react by turning on the LED. :param directive: contains a payload with the updated state information from Alexa """ color_list = ['BLACK', 'AMBER', 'YELLOW', 'GREEN'] for state in directive.payload.states: if state.name == 'wakeword': if state.value == 'active': print("Wake word active", file=sys.stderr) self.sound.play_song((('A3', 'e'), ('C5', 'e'))) for i in range(0, 4, 1): self.leds.set_color("LEFT", color_list[i], (i * 0.25)) self.leds.set_color("RIGHT", color_list[i], (i * 0.25)) time.sleep(0.25) elif state.value == 'cleared': print("Wake word cleared", file=sys.stderr) self.sound.play_song((('C5', 'e'), ('A3', 'e'))) for i in range(3, -1, -1): self.leds.set_color("LEFT", color_list[i], (i * 0.25)) self.leds.set_color("RIGHT", color_list[i], (i * 0.25)) time.sleep(0.25)
def test_play_song(self): s = Sound() s.play_song(( ('D4', 'e3'), # intro anacrouse ('D4', 'e3'), ('D4', 'e3'), ('G4', 'h'), # meas 1 ('D5', 'h'), ('C5', 'e3'), # meas 2 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), # meas 3 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), # meas 4 ['B4', 'e3'], ('C5', 'e3'), ('A4', 'h.'), ))
#!/usr/bin/micropython #testing motor import ev3dev2.motor as em import ev3dev2 as e import utime as t from ev3dev2.led import Leds from ev3dev2.sound import Sound spkr = Sound() leds = Leds() leds.set_color("LEFT", "GREEN") leds.set_color("RIGHT", "GREEN") m1= em.LargeMotor(em.OUTPUT_A) m1.on(em.SpeedPercent(25)) t.sleep(1) m1.off() leds.set_color("LEFT", "GREEN") leds.set_color("RIGHT", "RED") t.sleep(0.1) leds.set_color("LEFT", "RED") leds.set_color("RIGHT", "GREEN") t.sleep(0.1) leds.set_color("LEFT", "GREEN") leds.set_color("RIGHT", "GREEN") spkr.play_song(( ('D4', 'e3'), ('D4', 'e3'), ('D4', 'e3'), ('G4', 'h'), ('D5', 'h') ),tempo=220)
leds.set_color("RIGHT", "GREEN") sound.play_file('/home/robot/pydev/madeleine/SU.wav') sleep else: leds.set_color("LEFT", "RED") leds.set_color("RIGHT", "RED") # A long time ago in a galaxy far, # far away... Sound.play_song(( ('D4', 'e3'), # intro anacrouse ('D4', 'e3'), ('D4', 'e3'), ('G4', 'h'), # meas 1 ('D5', 'h'), ('C5', 'e3'), # meas 2 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), # meas 3 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), # meas 4 ('B4', 'e3'), ('C5', 'e3'), ('A4', 'h.'), ))
class MindstormsGadget(AlexaGadget): def __init__(self): super().__init__(gadget_config_path='./auth.ini') # order queue self.queue = Queue() self.button = Button() self.leds = Leds() self.sound = Sound() self.console = Console() self.console.set_font("Lat15-TerminusBold16.psf.gz", True) self.dispense_motor = LargeMotor(OUTPUT_A) self.pump_motor = LargeMotor(OUTPUT_B) self.touch_sensor = TouchSensor(INPUT_1) # Start threads threading.Thread(target=self._handle_queue, daemon=True).start() threading.Thread(target=self._test, daemon=True).start() def on_connected(self, device_addr): self.leds.animate_rainbow(duration=3, block=False) self.sound.play_song((('C4', 'e3'), ('C5', 'e3'))) def on_disconnected(self, device_addr): self.leds.animate_police_lights('RED', 'ORANGE', duration=3, block=False) self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") self.sound.play_song((('C5', 'e3'), ('C4', 'e3'))) def _test(self): while 1: self.button.wait_for_pressed('up') order = { 'name': 'Test', 'tea': 'Jasmine', 'sugar': 100, 'ice': 100 } self.queue.put(order) sleep(1) def _handle_queue(self): while 1: if self.queue.empty(): continue order = self.queue.get() self._make(name=order['name'], tea=order['tea'], sugar=order['sugar'], ice=order['ice']) def _send_event(self, name, payload): self.send_custom_event('Custom.Mindstorms.Gadget', name, payload) def _affirm_receive(self): self.leds.animate_flash('GREEN', sleeptime=0.25, duration=0.5, block=False) self.sound.play_song((('C3', 'e3'), ('C3', 'e3'))) def on_custom_mindstorms_gadget_control(self, directive): try: payload = json.loads(directive.payload.decode("utf-8")) print("Control payload: {}".format(payload), file=sys.stderr) control_type = payload["type"] # regular voice commands if control_type == "automatic": self._affirm_receive() order = { "name": payload["name"] or "Anonymous", "tea": payload["tea"] or "Jasmine Milk Tea", "sugar": payload["sugar"] or 100, "ice": payload["ice"] or 100, } self.queue.put(order) # series of voice commands elif control_type == "manual": # Expected params: [command] control_command = payload["command"] if control_command == "dispense": self._affirm_receive() if payload['num']: self._dispense(payload['num']) else: self._dispense() elif control_command == "pour": self._affirm_receive() if payload['num']: self._pour(payload['num']) else: self._pour() except KeyError: print("Missing expected parameters: {}".format(directive), file=sys.stderr) def _make(self, name=None, tea="Jasmine Milk Tea", sugar=100, ice=100): if not self.touch_sensor.is_pressed: # cup is not in place self._send_event('CUP', None) self.touch_sensor.wait_for_pressed() sleep(3) # cup enter delay # mid_col = console.columns // 2 # mid_row = console.rows // 2 # mid_col = 1 # mid_row = 1 # alignment = "L" process = self.sound.play_file('mega.wav', 100, Sound.PLAY_NO_WAIT_FOR_COMPLETE) # dispense boba self._dispense() # dispense liquid self._pour(tea=tea) # self.console.text_at( # s, column=mid_col, row=mid_row, alignment=alignment, reset_console=True # ) # notify alexa that drink is finished payload = { "name": name, "tea": tea, "sugar": sugar, "ice": ice, } self._send_event("DONE", payload) process.kill() # kill song self.sound.play_song((('C4', 'q'), ('C4', 'q'), ('C4', 'q')), delay=0.1) self.touch_sensor.wait_for_released() # dispense liquid def _pour(self, time_in_s=10, tea="Jasmine Milk Tea"): # send event to alexa payload = {"time_in_s": time_in_s, "tea": tea} self._send_event("POUR", payload) self.pump_motor.run_forever(speed_sp=1000) sleep(time_in_s) self.pump_motor.stop() # dispense boba def _dispense(self, cycles=10): # send event to alexa payload = {"cycles": cycles} self._send_event("DISPENSE", payload) # ensure the dispenser resets to the correct position everytime if cycles % 2: cycles += 1 # agitate the boba to make it fall for i in range(cycles): deg = 45 if i % 2 else -45 self.dispense_motor.on_for_degrees(SpeedPercent(75), deg) sleep(0.5)
class LegoBot(MoveDifferential): def __init__(self, left_motor_port, right_motor_port, rot_motor_port, wheel_class, wheel_distance_mm, desc=None, motor_class=LargeMotor): MoveDifferential.__init__(self, left_motor_port, right_motor_port, wheel_class, wheel_distance_mm) """ LegoBot Class inherits all usefull stuff for differential drive and adds sound, LEDs, IRSensor which is rotated by Medium Motor """ self.leds = Leds() self.sound = Sound() self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") # Startup sequence self.sound.play_song((('C4', 'e'), ('D4', 'e'), ('E5', 'q'))) self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") # create IR sensors self.ir_sensor = InfraredSensor() self.sensor_rotation_point = Pose( 0.05, 0.0, np.radians(0)) self.sensor_rotation_radius = 0.04 self.sensor_thread_run = False self.sensor_thread_id = None # temporary storage for ir readings and poses until half rotation is fully made self.ir_sensors = None # initialize motion self.ang_velocity = (0.0,0.0) self.rot_motor = MediumMotor(rot_motor_port) self.rotate_thread_run = False self.rotate_thread_id = None self.rotation_degrees = 180 # information about robot for controller or supervisor self.info = Struct() self.info.wheels = Struct() self.info.wheels.radius = self.wheel.radius_mm /1000 self.info.wheels.base_length = wheel_distance_mm /1000 self.info.wheels.max_velocity = 2*pi*170/60 # 170 RPM self.info.wheels.min_velocity = 2*pi*30/60 # 30 RPM self.info.pose = None self.info.ir_sensors = Struct() self.info.ir_sensors.poses = None self.info.ir_sensors.readings = None self.info.ir_sensors.rmax = 0.7 self.info.ir_sensors.rmin = 0.04 # starting odometry thread self.odometry_start(0,0,0) # start measuring distance with IR Sensor in another thread while rotating self.sensor_update_start(self.rot_motor) # start rotating of medium motor self.rotate_and_update_sensors_start() def turn_off(self): # stop odometry thread self.odometry_stop() # stop updating sensors self.rotate_and_update_sensors_stop() # return robots head to start position self.rot_motor.on_to_position(100, 0, True, True) self.sensor_update_stop() # Shutdown sequence self.sound.play_song((('E5', 'e'), ('C4', 'e'))) self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") def get_pose(self): """Get the pose of the object in world coordinates""" return Pose(self.x_pos_mm/1000, self.y_pos_mm/1000, self.theta) def move(self,dt): (vl, vr) = self.get_wheel_speeds() # actual robot move self.on_for_seconds(SpeedRPS(vl/2/pi), SpeedRPS(vr/2/pi), dt, False, False) def get_info(self): # getting updated info for supervisor self.info.pose = self.get_pose() return self.info def set_inputs(self,inputs): """ Setting new values of (vl, vr) sent by supervisor and controller """ self.set_wheel_speeds(inputs) def get_wheel_speeds(self): return self.ang_velocity def set_wheel_speeds(self,*args): if len(args) == 2: (vl, vr) = args else: (vl, vr) = args[0] left_ms = max(-self.info.wheels.max_velocity, min(self.info.wheels.max_velocity, vl)) right_ms = max(-self.info.wheels.max_velocity, min(self.info.wheels.max_velocity, vr)) self.ang_velocity = (left_ms, right_ms) def sensor_update_start(self, motor, sleep_time=0.005): # 5ms """ A thread is started that will run until the user calls sensor_update_stop() which will set sensor_thread_run to False """ self.ir_sensors = {} def _sensor_monitor(): while self.sensor_thread_run: angle = -np.radians(motor.degrees) # convert from degrees to radians sensor_x = round(self.sensor_rotation_radius*cos(angle) + self.sensor_rotation_point.x, 3) sensor_y = round(self.sensor_rotation_radius*sin(angle) + self.sensor_rotation_point.y, 3) # adding to temp dict sensor readings and poses self.ir_sensors.update({(sensor_x, sensor_y, angle):round(self.ir_sensor.proximity*0.007, 3)}) time.sleep(0.005) self.sensor_thread_id = None self.sensor_thread_run = True self.sensor_thread_id = _thread.start_new_thread(_sensor_monitor, ()) def sensor_update_stop(self): """ Signal the sensor update thread to exit and wait for it to exit """ if self.sensor_thread_id: self.sensor_thread_run = False while self.sensor_thread_id: pass def rotate_and_update_sensors_start(self): self.info.ir_sensors.readings = [] self.info.ir_sensors.poses = [] def _rotate_monitor(): while self.rotate_thread_run: # writing ir sensor reading and poses from temp dict self.info.ir_sensors.readings = [*self.ir_sensors.values()] self.info.ir_sensors.poses = [*self.ir_sensors] # cleaning up temp dict self.ir_sensors = {} # rotate rotation motor with sensor self.rot_motor.on_for_degrees(50, self.rotation_degrees, True, True) time.sleep(0.005) # change orientation of rotation self.rotation_degrees = -self.rotation_degrees self.rotate_thread_id = None self.rot_motor.position = 0 # rotate head to the left at start self.rot_motor.on_for_degrees(100, -90, True, True) self.rotate_thread_run = True self.rotate_thread_id = _thread.start_new_thread(_rotate_monitor, ()) def rotate_and_update_sensors_stop(self): """ Signal the sensor update thread to exit and wait for it to exit """ if self.rotate_thread_id: self.rotate_thread_run = False while self.rotate_thread_id: pass
pitch_motor.on_to_position(normal_speed,0,True,False) spin_motor.on_to_position(normal_speed,0,True,False) grabber_motor.on_to_position(normal_speed,0,True,True) elbow_motor.on_to_position(slow_speed,0,True,False) shoulder_control1.on_to_position(slow_speed,0,True,False) shoulder_control2.on_to_position(slow_speed,0,True,False) waist_motor.on_to_position(fast_speed,0,True,True) if event.type == 1 and event.code == 316 and event.value == 1: #PS logger.info("Engine stopping!") running = False #Reset roll_motor.on_to_position(normal_speed,0,True,False) pitch_motor.on_to_position(normal_speed,0,True,False) spin_motor.on_to_position(normal_speed,0,True,False) grabber_motor.on_to_position(normal_speed,0,True,True) elbow_motor.on_to_position(slow_speed,0,True,False) shoulder_control1.on_to_position(slow_speed,0,True,False) shoulder_control2.on_to_position(slow_speed,0,True,False) waist_motor.on_to_position(fast_speed,0,True,True) sound.play_song((('E5', 'e'), ('C4', 'e'))) leds.set_color("LEFT", "BLACK") leds.set_color("RIGHT", "BLACK") remote_leds.set_color("LEFT", "BLACK") remote_leds.set_color("RIGHT", "BLACK") time.sleep(1) # Wait for the motor thread to finish break
def test(): sounds = Sound() sounds.set_volume(100) sounds.beep() sounds.play_tone(300, 0.2) sleep(1) sounds.play_tone(500, 0.2) sleep(1) sounds.speak('start runing:') sleep(1) sounds.play_song(( ('D4', 'e3'), # intro anacrouse ('D4', 'e3'), ('D4', 'e3'), ('G4', 'h'), # meas 1 ('D5', 'h'), ('C5', 'e3'), # meas 2 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), # meas 3 ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), # meas 4 ('B4', 'e3'), ('C5', 'e3'), ('A4', 'h.'), )) sleep(1) sounds.tone([(392, 350, 100), (392, 350, 100), (392, 350, 100), (311.1, 250, 100), (466.2, 25, 100), (392, 350, 100), (311.1, 250, 100), (466.2, 25, 100), (392, 700, 100), (587.32, 350, 100), (587.32, 350, 100), (587.32, 350, 100), (622.26, 250, 100), (466.2, 25, 100), (369.99, 350, 100), (311.1, 250, 100), (466.2, 25, 100), (392, 700, 100), (784, 350, 100), (392, 250, 100), (392, 25, 100), (784, 350, 100), (739.98, 250, 100), (698.46, 25, 100), (659.26, 25, 100), (622.26, 25, 100), (659.26, 50, 400), (415.3, 25, 200), (554.36, 350, 100), (523.25, 250, 100), (493.88, 25, 100), (466.16, 25, 100), (440, 25, 100), (466.16, 50, 400), (311.13, 25, 200), (369.99, 350, 100), (311.13, 250, 100), (392, 25, 100), (466.16, 350, 100), (392, 250, 100), (466.16, 25, 100), (587.32, 700, 100), (784, 350, 100), (392, 250, 100), (392, 25, 100), (784, 350, 100), (739.98, 250, 100), (698.46, 25, 100), (659.26, 25, 100), (622.26, 25, 100), (659.26, 50, 400), (415.3, 25, 200), (554.36, 350, 100), (523.25, 250, 100), (493.88, 25, 100), (466.16, 25, 100), (440, 25, 100), (466.16, 50, 400), (311.13, 25, 200), (392, 350, 100), (311.13, 250, 100), (466.16, 25, 100), (392.00, 300, 150), (311.13, 250, 100), (466.16, 25, 100), (392, 700)]) sounds.play_file('resources/xiaohuamao.wav') sleep(2)
far away... """)) speaker = Sound() speaker.play_song(( ('D4', 'e3'), ('D4', 'e3'), ('D4', 'e3'), ('G4', 'h'), ('D5', 'h'), ('C5', 'e3'), ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), ('B4', 'e3'), ('A4', 'e3'), ('G5', 'h'), ('D5', 'q'), ('C5', 'e3'), ('B4', 'e3'), ('C5', 'e3'), ('A4', 'h.'), )) speaker.play(os.path.join(_HERE, 'snd/r2d2.wav')) #speaker.speak("Luke, I am your father")
class MindstormsGadget(AlexaGadget): """ A Mindstorms gadget that performs movement based on voice commands. Two types of commands are supported, directional movement and preset. """ def __init__(self): """ Performs Alexa Gadget initialization routines and ev3dev resource allocation. """ super().__init__() # Gadget state self.patrol_mode = False # Ev3dev initialization self.leds = Leds() self.sound = Sound() self.drive = MoveTank(OUTPUT_A,OUTPUT_A) # Band """ self.deliver = MoveTank(OUTPUT_B,OUTPUT_B) # Deliver """ # Start threads #threading.Thread(target=self._patrol_thread, daemon=True).start() def on_connected(self, device_addr): """ Gadget connected to the paired Echo device. :param device_addr: the address of the device we connected to """ self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") print("{} connected to Echo device".format(self.friendly_name)) def on_disconnected(self, device_addr): """ Gadget disconnected from the paired Echo device. :param device_addr: the address of the device we disconnected from """ self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") print("{} disconnected from Echo device".format(self.friendly_name)) def on_custom_mindstorms_gadget_control(self, directive): """ Handles the Custom.Mindstorms.Gadget control directive. :param directive: the custom directive with the matching namespace and name """ try: payload = json.loads(directive.payload.decode("utf-8")) print("Control payload: {}".format(payload)) control_type = payload["type"] if control_type == "move": # Expected params: [direction, duration, speed] self._move(payload["direction"], int(payload["duration"]), int(payload["speed"])) if control_type == "deliver": # Expected params: [direction, duration, speed] self._deliver(payload["direction"], int(payload["duration"]), int(payload["speed"]),payload["spice"]) except KeyError: print("Missing expected parameters: {}".format(directive)) def _move(self, direction, duration, speed, is_blocking=False): """ Handles move commands from the directive. Right and left movement can under or over turn depending on the surface type. :param direction: the move direction :param duration: the duration in seconds :param speed: the speed percentage as an integer :param is_blocking: if set, motor run until duration expired before accepting another command """ print("Move command: ({}, {}, {}, {})".format(direction, speed, duration, is_blocking)) if direction in Direction.FORWARD.value: self.drive.on_for_seconds(SpeedPercent(speed), SpeedPercent(speed), duration, block=is_blocking) # self.drive.run_timed(speed_sp=speed, time_sp=duration) # self.drive.run_timed(speed_sp=750, time_sp=2500) if direction in Direction.BACKWARD.value: self.drive.on_for_seconds(SpeedPercent(-speed), SpeedPercent(-speed), duration, block=is_blocking) # self.drive.run_timed(speed_sp=-speed, time_sp=duration) if direction in Direction.STOP.value: self.drive.off() self.patrol_mode = False def _deliver(self, direction, duration, speed, spice, is_blocking=False): #print("Move command: ({}, {}, {}, {})".format(direction, speed, duration, is_blocking)) # Define the speed and duration for band and deliver motor depending on the spice if (spice == 'salt'): SpeedBand = 16 Durationband = 2 SpeedDeliver = 15 DurationDeliver = 3 if (spice == 'pepper'): SpeedBand = 0 Durationband = 0 SpeedDeliver = 15 DurationDeliver = 3 if spice == 'lemon': SpeedBand = -16 Durationband = 2 SpeedDeliver = 15 DurationDeliver = 3 if spice != '': self.leds.set_color("LEFT", "ORANGE") self.leds.set_color("RIGHT", "ORANGE") #Band position to correct spice self.drive.on_for_seconds(SpeedPercent(-SpeedBand), SpeedPercent(-SpeedBand), Durationband, block=is_blocking) time.sleep(4) # deliver spice self.deliver.on_for_seconds(SpeedPercent(SpeedDeliver), SpeedPercent(SpeedDeliver), DurationDeliver, block=is_blocking) time.sleep(4) # # deliver motor to init self.deliver.on_for_seconds(SpeedPercent(-SpeedDeliver), SpeedPercent(-SpeedDeliver), DurationDeliver, block=is_blocking) time.sleep(4) #Band back to init self.drive.on_for_seconds(SpeedPercent(SpeedBand), SpeedPercent(SpeedBand), Durationband, block=is_blocking) time.sleep(4) # make some noise and blinking after the delivery self.sound.play_song((('E5', 'q'), ('E5', 'q'))) self.sound.speak('Enjoy your meal') self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN")
class MindstormsGadget(AlexaGadget): """ A Mindstorms gadget that performs movement in sync with music tempo. """ def __init__(self): """ Performs Alexa Gadget initialization routines and ev3dev resource allocation. """ super().__init__() # Ev3dev initialization self.leds = Leds() self.sound = Sound() self.left_motor = LargeMotor(OUTPUT_B) self.right_motor = LargeMotor(OUTPUT_C) self.hand_motor = MediumMotor(OUTPUT_A) # Gadget states self.bpm = 0 self.trigger_bpm = "off" self.drive = MoveTank(OUTPUT_B, OUTPUT_C) self.weapon = MediumMotor(OUTPUT_A) def on_connected(self, device_addr): """ Gadget connected to the paired Echo device. :param friendly_name: the friendly name of the gadget that has connected to the echo device """ self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") print("{} connected to Echo device".format(self.friendly_name)) def on_disconnected(self, device_addr): """ Gadget disconnected from the paired Echo device. :param friendly_name: the friendly name of the gadget that has disconnected from the echo device """ self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") print("{} disconnected from Echo device".format(self.friendly_name)) def on_custom_mindstorms_gadget_control(self, directive): """ Handles the Custom.Mindstorms.Gadget control directive. :param directive: the custom directive with the matching namespace and name """ try: payload = json.loads(directive.payload.decode("utf-8")) print("Control payload: {}".format(payload)) control_type = payload["type"] if control_type == "spin": print("Move command found") self.hand_motor.run_timed(speed_sp=1050, time_sp=2500) if control_type == "movef": print("Move Forward command found") self.right_motor.run_timed(speed_sp=1050, time_sp=1000) self.left_motor.run_timed(speed_sp=1050, time_sp=1000) if control_type == "moveb": print("Move backward command found") self.right_motor.run_timed(speed_sp=-1050, time_sp=1000) self.left_motor.run_timed(speed_sp=-1050, time_sp=1000) if control_type == "mover": print("Move right command found") self.right_motor.run_timed(speed_sp=-1050, time_sp=1000) self.left_motor.run_timed(speed_sp=1050, time_sp=1000) if control_type == "movel": print("Move left command found") self.right_motor.run_timed(speed_sp=1050, time_sp=1000) self.left_motor.run_timed(speed_sp=-1050, time_sp=1000) if control_type == "command": self.hand_motor.run_timed(speed_sp=1050, time_sp=2500) except KeyError: print("Missing expected parameters: {}".format(directive)) def on_alexa_gadget_musicdata_tempo(self, directive): """ Provides the music tempo of the song currently playing on the Echo device. :param directive: the music data directive containing the beat per minute value """ tempo_data = directive.payload.tempoData for tempo in tempo_data: print("tempo value: {}".format(tempo.value)) if tempo.value > 0: # dance pose self.right_motor.run_timed(speed_sp=750, time_sp=2500) self.left_motor.run_timed(speed_sp=-750, time_sp=2500) self.hand_motor.run_timed(speed_sp=750, time_sp=2500) self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") time.sleep(3) # starts the dance loop self.trigger_bpm = "on" threading.Thread(target=self._dance_loop, args=(tempo.value, )).start() elif tempo.value == 0: # stops the dance loop self.trigger_bpm = "off" self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") def on_alexa_gadget_statelistener_stateupdate(self, directive): """ Listens for the wakeword state change and react by turning on the LED. :param directive: contains a payload with the updated state information from Alexa """ color_list = ['BLACK', 'AMBER', 'YELLOW', 'GREEN'] for state in directive.payload.states: if state.name == 'wakeword': if state.value == 'active': print("Wake word active - turn on LED") self.sound.play_song((('A3', 'e'), ('C5', 'e'))) for i in range(0, 4, 1): self.leds.set_color("LEFT", color_list[i], (i * 0.25)) self.leds.set_color("RIGHT", color_list[i], (i * 0.25)) time.sleep(0.25) elif state.value == 'cleared': print("Wake word cleared - turn off LED") self.sound.play_song((('C5', 'e'), ('A3', 'e'))) for i in range(3, -1, -1): self.leds.set_color("LEFT", color_list[i], (i * 0.25)) self.leds.set_color("RIGHT", color_list[i], (i * 0.25)) time.sleep(0.25) def _dance_loop(self, bpm): """ Perform motor movement in sync with the beat per minute value from tempo data. :param bpm: beat per minute from AGT """ color_list = ["GREEN", "RED", "AMBER", "YELLOW"] led_color = random.choice(color_list) motor_speed = 400 milli_per_beat = min(1000, (round(60000 / bpm)) * 0.65) print("Adjusted milli_per_beat: {}".format(milli_per_beat)) while self.trigger_bpm == "on": # Alternate led color and motor direction led_color = "BLACK" if led_color != "BLACK" else random.choice( color_list) motor_speed = -motor_speed self.leds.set_color("LEFT", led_color) self.leds.set_color("RIGHT", led_color) self.right_motor.run_timed(speed_sp=motor_speed, time_sp=150) self.left_motor.run_timed(speed_sp=-motor_speed, time_sp=150) time.sleep(milli_per_beat / 1000) print("Exiting BPM process.")
class MindstormsGadget(AlexaGadget): """ A Mindstorms gadget that performs movement in sync with music tempo. """ def __init__(self): """ Performs Alexa Gadget initialization routines and ev3dev resource allocation. """ super().__init__() # Ev3dev initialization self.leds = Leds() self.sound = Sound() #self.left_motor = LargeMotor(OUTPUT_D) #self.hand_motor = MediumMotor(OUTPUT_A) # Gadget states self.bpm = 0 self.trigger_bpm = "off" self.ir = InfraredSensor() self.ir.on_channel1_top_left = self.onRedTopChannel1 self.ir.on_channel1_top_left = self.onRedTopChannel1 self.ir.on_channel1_bottom_left = self.onRedBottomChannel1 self.ir.on_channel1_top_right = self.onBlueTopChannel1 self.ir.on_channel1_bottom_right = self.onBlueBottomChannel1 threading.Thread(target=self._proximity_thread, daemon=True).start() def onRedTopChannel1(self, state): if state: print("Red Top Channel 1. State: " + str(state)) self._send_event("buttonPress", {'direction': 'up'}) def onBlueTopChannel1(self, state): if state: print("Blue Top Channel 1. State: " + str(state)) self._send_event("buttonPress", {'direction': 'down'}) def onRedBottomChannel1(self, state): if state: print("Red Bottom Channel 1. State: " + str(state)) self._send_event("buttonPress", {'direction': 'left'}) def onBlueBottomChannel1(self, state): if state: print("Blue Bottom Channel 1. State: " + str(state)) self._send_event("buttonPress", {'direction': 'right'}) def on_connected(self, device_addr): """ Gadget connected to the paired Echo device. :param friendly_name: the friendly name of the gadget that has connected to the echo device """ self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") print("{} connected to Echo device".format(self.friendly_name)) def on_disconnected(self, device_addr): """ Gadget disconnected from the paired Echo device. :param friendly_name: the friendly name of the gadget that has disconnected from the echo device """ self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") print("{} disconnected from Echo device".format(self.friendly_name)) def on_custom_mindstorms_gadget_control(self, directive): """ Handles the Custom.Mindstorms.Gadget control directive. :param directive: the custom directive with the matching namespace and name """ try: payload = json.loads(directive.payload.decode("utf-8")) except KeyError: print("Missing expected parameters: {}".format(directive)) def on_alexa_gadget_statelistener_stateupdate(self, directive): """ Listens for the wakeword state change and react by turning on the LED. :param directive: contains a payload with the updated state information from Alexa """ color_list = ['BLACK', 'AMBER', 'YELLOW', 'GREEN'] for state in directive.payload.states: if state.name == 'wakeword': if state.value == 'active': print("Wake word active - turn on LED") self.sound.play_song((('A3', 'e'), ('C5', 'e'))) for i in range(0, 4, 1): self.leds.set_color("LEFT", color_list[i], (i * 0.25)) self.leds.set_color("RIGHT", color_list[i], (i * 0.25)) time.sleep(0.25) elif state.value == 'cleared': print("Wake word cleared - turn off LED") self.sound.play_song((('C5', 'e'), ('A3', 'e'))) for i in range(3, -1, -1): self.leds.set_color("LEFT", color_list[i], (i * 0.25)) self.leds.set_color("RIGHT", color_list[i], (i * 0.25)) time.sleep(0.25) def _send_event(self, name, payload): """ Sends a custom event to trigger a sentry action. :param name: the name of the custom event :param payload: the sentry JSON payload """ self.send_custom_event('Custom.Mindstorms.Gadget', name, payload) def _proximity_thread(self): """ Monitors the distance between the robot and an obstacle when sentry mode is activated. If the minimum distance is breached, send a custom event to trigger action on the Alexa skill. """ count = 0 while True: while True: # distance = self.ir.proximity # print("processing IR") self.ir.process() # print("Proximity: {}".format(distance)) # count = count + 1 if distance < 10 else 0 # if count > 3: # print("Proximity breached. Sending event to skill") # self.leds.set_color("LEFT", "RED", 1) # self.leds.set_color("RIGHT", "RED", 1) # # self._send_event("proximity", {'distance': distance}) time.sleep(0.1) # time.sleep(1) def _dance_loop(self, bpm): """ Perform motor movement in sync with the beat per minute value from tempo data. :param bpm: beat per minute from AGT """ color_list = ["GREEN", "RED", "AMBER", "YELLOW"] led_color = random.choice(color_list) motor_speed = 400 milli_per_beat = min(1000, (round(60000 / bpm)) * 0.65) print("Adjusted milli_per_beat: {}".format(milli_per_beat)) while self.trigger_bpm == "on": # Alternate led color and motor direction led_color = "BLACK" if led_color != "BLACK" else random.choice( color_list) motor_speed = -motor_speed self.leds.set_color("LEFT", led_color) self.leds.set_color("RIGHT", led_color) self.right_motor.run_timed(speed_sp=motor_speed, time_sp=150) self.left_motor.run_timed(speed_sp=-motor_speed, time_sp=150) time.sleep(milli_per_beat / 1000) print("Exiting BPM process.")
from ev3dev2.sound import Sound sound = Sound() sound.play_song(( ('D4', 'e3'), ('D4', 'e3'), ('D4', 'e3'), ('G4', 'h'), ('D5', 'h') ))
class MindstormsGadget(AlexaGadget): #A Mindstorms gadget that will react to the Alexa wake word. def __init__(self): #Performs Alexa Gadget initialization routines and ev3dev resource allocation. super().__init__() self.leds = Leds() self.sound = Sound() #Connect the blue motor to Port A self.blueMotor = MediumMotor(OUTPUT_A) #Connect the red motor to Port B self.redMotor = MediumMotor(OUTPUT_B) def on_connected(self, device_addr): """ Gadget connected to the paired Echo device. :param device_addr: the address of the device we connected to """ self.leds.set_color("LEFT", "GREEN") self.leds.set_color("RIGHT", "GREEN") logger.info("Connected to Alexa") gadget.sound.play_song((('C4', 'e'), ('D4', 'e'), ('E5', 'q'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(360)) self.blueMotor.on_for_degrees(speed=flagSpeed, degrees=360) def on_disconnected(self, device_addr): """ Gadget disconnected from the paired Echo device. :param device_addr: the address of the device we disconnected from """ self.leds.set_color("LEFT", "BLACK") self.leds.set_color("RIGHT", "BLACK") logger.info("Disconnected from Alexa") gadget.sound.play_song((('E5', 'e'), ('D4', 'e'), ('C4', 'q'))) def on_alexa_gadget_statelistener_stateupdate(self, directive): """ Listens for the state changes and reacts :param directive: contains a payload with the updated state information from Alexa """ color_list = ['BLACK', 'AMBER', 'YELLOW', 'GREEN'] for state in directive.payload.states: if state.name == 'wakeword': if state.value == 'active': print("Wake word active", file=sys.stderr) self.sound.play_song((('A3', 'e'), ('C5', 'e'))) self.blueMotor.on_for_degrees(speed=flagSpeed, degrees=180) elif state.value == 'cleared': print("Wake word cleared", file=sys.stderr) self.sound.play_song((('C5', 'e'), ('A3', 'e'))) self.blueMotor.on_for_degrees(speed=flagSpeed, degrees=180) elif state.name == 'alarms': if state.value == 'active': print("Alarm active", file=sys.stderr) self.sound.play_song((('B3', 'e'), ('D5', 'e'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(90)) elif state.value == 'cleared': print("Alarm cleared", file=sys.stderr) self.sound.play_song((('B5', 'e'), ('D3', 'e'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(270)) elif state.name == 'timers': if state.value == 'active': print("Timer active", file=sys.stderr) self.sound.play_song((('C3', 'e'), ('E5', 'e'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(180)) elif state.value == 'cleared': print("Timer cleared", file=sys.stderr) self.sound.play_song((('E5', 'e'), ('C3', 'e'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(180)) elif state.name == 'reminders': if state.value == 'active': print("Reminder active", file=sys.stderr) self.sound.play_song((('D3', 'e'), ('F5', 'e'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(270)) elif state.value == 'cleared': print("Reminder cleared", file=sys.stderr) self.sound.play_song((('F5', 'e'), ('D3', 'e'))) self.redMotor.on_for_degrees(speed=flagSpeed, degrees=red_adjust_value(90)) elif state.name == 'timeinfo': print(state.value) logger.info(state.value) self.redMotor.off() self.blueMotor.off()