Nous conduisons l'aspirateur Xiaomi

Alors les vacances du Nouvel An sont arrivées, et avec elles beaucoup de temps libre, et même un aspirateur intelligent est tombé entre mes mains. Dès que j'ai vu le contrôle manuel dans l'application MiHome, j'ai immédiatement réalisé ce que je voulais faire: nous contrôlerons l'aspirateur à l'aide de la manette Dualshock v4!

Étape 1, faites glisser le jeton, clignotant (facultatif)


Nous avons mis l'application MiHome corrigée, qui nous montrera le jeton, puis sélectionnons le firmware racine, télécharger, installer python-miio (pip installer python-miio), essayer d'installer le firmware en utilisant mirobo --ip %ip% --token %token% update-firmware %filename% et à ce stade tout s'est cassé. L'aspirateur a désespérément refusé d'être mis à jour, après plusieurs heures de recherche sur Google, j'ai essayé de voir la sortie de débogage de mirobo et voilà! Étant donné que plusieurs adaptateurs sont installés sur mon ordinateur portable, il a essayé de distribuer le micrologiciel sur le réseau de l'adaptateur VirtualBox Host-Only. Ensuite, je viens de soulever le serveur de fichiers et j'ai mirobo --ip=%ip% --token=%token% raw-command miIO.ota '{"mode":"normal", "install":"1", "app_url":"http://%my_ip:port%/%filename%.pkg", "file_md5":"%md5%","proc":"dnld install"}' cette commande: mirobo --ip=%ip% --token=%token% raw-command miIO.ota '{"mode":"normal", "install":"1", "app_url":"http://%my_ip:port%/%filename%.pkg", "file_md5":"%md5%","proc":"dnld install"}' . Le firmware s'est levé quelque part en 10 minutes, l'accès ssh a fonctionné

Étape 2, essayez de monter le robot


 import miio ip = '' token = '' bot = miio.vacuum.Vacuum(ip, token) bot.manual_start() bot.manual_control(0, 0.3, 2000) # move forward with max speed for 2 seconds bot.manual_control(90, 0, 1000) # rotate bot.manual_stop() 

À ce stade, l'aspirateur devrait dire à l'aide de télécommandes (ou quelque chose de similaire selon le firmware), secouer et arrêter

Étape 3, connectez Dualshock


Après quelques recherches, il a été décidé d'utiliser pygame
Nous regardons de quels boutons / autocollants sont responsables

 BUTTON_SQUARE = 0 BUTTON_X = 1 BUTTON_CIRCLE = 2 BUTTON_TRIANGLE = 3 def init_joystick(): pygame.init() pygame.joystick.init() controller = pygame.joystick.Joystick(0) controller.init() return controller def main(): controller = init_joystick() bot = miio.vacuum.Vacuum(ip, token) modes = ['manual', 'home', 'spot', 'cleaning', 'unk'] mode = 'unk' axis = [0.00 for _ in range(6)] flag = True button = [False for _ in range(14)] print('Press start to start!') while flag: for event in pygame.event.get(): if event.type == pygame.JOYAXISMOTION: axis[event.axis] = round(event.value,2) elif event.type == pygame.JOYBUTTONDOWN: button[event.button] = True # Touchpad to exit if event.button == 13: flag = False elif event.type == pygame.JOYBUTTONUP: if mode == 'unk': print('Ready to go! Press X to start manual mode') if event.button == BUTTON_X: mode = 'manual' bot.manual_start() elif mode == 'manual': if event.button == BUTTON_TRIANGLE: bot.manual_stop() mode = 'unk' elif event.button == BUTTON_X: play_sound('http://192.168.1.43:8080/dejavu.mp3') # see ya later elif event.button == BUTTON_CIRCLE: # stop sound play_sound(';') if mode == 'manual': try: move_robot(bot, button, axis) # see ya in the next step except: bot.manual_start() pass time.sleep(0.01) 

Pour l'instant, dans move_robot, vous pouvez simplement imprimer (axe) et vérifier que le joystick fonctionne.
Ensuite, nous devons faire rouler le robot lorsque vous appuyez sur les boutons / bâtons, j'ai choisi le manche gauche sur l'axe Y (haut -1, bas 1) pour la vitesse et le manche droit sur l'axe X pour l'angle, il s'est avéré comme ceci

 def translate(value, leftMin, leftMax, rightMin, rightMax): leftSpan = leftMax - leftMin rightSpan = rightMax - rightMin valueScaled = float(value - leftMin) / float(leftSpan) return rightMin + (valueScaled * rightSpan) def move_robot(bot, buttons, axis): rot = 0 val = 0 to_min, to_max = -0.3, 0.3 # Right stick X if axis[2] != 0: rot = -translate(axis[2], -1, 1, -90, 90) if abs(rot) < 8: rot = 0 # Left stick Y, -1 up, 1 down if axis[1] != 0: val = -translate(axis[1], -1, 1, to_min, to_max) if abs(val) < 0.07: val = 0 if rot or val: bot.manual_control(rot, val, 150) 

Exécutez le script, appuyez sur X sur le contrôleur et le robot doit rouler et tourner
À ce stade, j'ai eu un problème: pour une raison quelconque, si vous appuyez sur le joystick gauche vers la fin et essayez de tourner, il ne tournera pas, vous devrez d'abord ralentir, si vous essayez de réduire les valeurs de mappage, par exemple, définissez -0,29, 0,29, il commencera à encercler , jusqu'à ce que la position de l'autocollant de gauche change, je n'ai jamais compris quel est le problème

Étape 4, ajoutez de la musique


Nous allons par ssh à notre robot et voyons quels langages de script sont là.

Il n'y avait pas de Python, mais je ne voyais pas l'intérêt de l'installer, mais j'ai trouvé une perle, adaptée à notre petite tâche.

Ensuite, installez sox:

 sudo apt-get install sox, libsox-fmt-mp3 

et écris un petit serveur sur la perle:

 #!/usr/bin/perl use IO::Socket::INET; $| = 1; my $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', LocalPort => '7777', Proto => 'tcp', Listen => 2, Reuse => 1 ); die "cannot create socket $!\n" unless $socket; print "server waiting for client connection on port 7777\n"; while(1) { my $client_socket = $socket->accept(); my $client_address = $client_socket->peerhost(); my $client_port = $client_socket->peerport(); print "connection from $client_address:$client_port\n"; my $data = ""; $client_socket->recv($data, 256); print "received data: $data\n"; my @urls = split /;/, $data; system("killall play > /dev/null"); $data = "ok"; $client_socket->send($data); shutdown($client_socket, 1); if ( $urls[0] ne "") { system("play -q -v 0.4 " . $urls[0] . " &"); } } $socket->close(); 

 sudo perl sound_server.pl 

dans notre console, nous faisons quelque chose comme

 import socket ip = '' s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((ip, 7777)) s.sendall(b'http://%local_ip%:%local_port%/test.mp3;') s.close() 

Et grâce à l'aspirateur, notre test.mp3 devrait jouer (en conséquence, nous devons augmenter le serveur de fichiers sur notre machine locale).

Notre fonction play_sound () fera presque la même chose, seulement sendall (url + ';') le sera, url est l'argument de la fonction.

Résultat


Source: https://habr.com/ru/post/fr435064/


All Articles