[PYTHON] "2/2" Je crée une application Web simple pour le fonctionnement du robot. «Chaînes Raspberry Pi 3B + et Django»

Intro

C'est s_rae. J'étudie la programmation dur.

En tant que pratique de développement d'applications, j'ai créé une interface permettant de faire fonctionner le robot. https://github.com/samanthanium/dullahan_local Vous pouvez voir le code source sur.

Poursuivant le post précédent, cette fois, je vais expliquer un peu la source. Dernière fois: https://qiita.com/s_rae/items/d808c3eccd8e173dc55b

Comme il a été fait à des fins de passe-temps, j'omettrai la gestion des erreurs.

Cadres et bibliothèques utilisés

Nous utilisons cette technologie pour ce projet.

Cadre Django

Django servait principalement des pages Web via HTTP, gérait les utilisateurs en sessions et travaillait sur la base de données sqlite.

Soit dit en passant, le projet Django se compose de plusieurs «applications» (code qui peut être réutilisé pour d’autres projets).

Ce projet --dullahan (application principale du projet) --pages (pour les pages Web Accueil, À propos, Connexion) --control_system (page d'envoi de commandes et d'enregistrement des périphériques) --bluetooth_interface (y compris le consommateur et la fonction du périphérique Bluetooth)

Il est composé de «app».

La raison pour laquelle j'ai utilisé Django est qu'il a de nombreuses fonctions et peut être créé rapidement. Je voulais aussi pratiquer Python.

Django Channels Django Channels est une bibliothèque créée pour le framework Django. Il est possible d'ajouter des fonctionnalités telles que Websocket au framework Django.

Channels est un mécanisme qui utilise la classe «Consommateur» pour traiter les messages WebSocket. Il peut exécuter des fonctions similaires à la vue du framework Django.

Pybluez Pybluez est une bibliothèque créée pour utiliser la fonction Bluetooth du système en Python. Je n'expliquerai pas le code Pybluez ici, mais vous pouvez écrire le code de la même manière que le module socket.

Description du code

L'utilisateur se connecte dans> Ajouter un appareil-> Envoyer la commande à l'appareil J'expliquerai le flux des sentiments.

pages/views.py


#...
def log_in(req):
    form = AuthenticationForm()
    if req.method == 'POST':
        form = AuthenticationForm(data=req.POST)
        if form.is_valid():
            login(req, form.get_user())
            return redirect(reverse('get_home'))
        else:
            return render(req, 'login.html', {'form': form})
    return render(req, 'login.html', {'form': form})
#...
def sign_up(req):
    form = UserCreationForm()
    if req.method == 'POST':
        form = UserCreationForm(data=req.POST)
        if form.is_valid():
            form.save()
            return redirect(reverse('log_in'))
        else:
            print(form.errors)
    return render(req, 'signup.html', {'form': form})

Voici la fonction de connexion utilisateur. Vous pouvez facilement vous connecter en utilisant la méthode "form.get_user" incluse dans Django's Forms.

Après ça

@login_required

Vous pouvez vérifier l'utilisateur actuel en utilisant le décorateur de dans la vue.

Vient ensuite l'écran pour rechercher et enregistrer les périphériques Bluetooth environnants.

control_system/views.py


from bluetooth_interface import bt_functions as bt
#...
@login_required
def device_search_ajax(req):
    try:
        if req.method == "GET":
            nearby_devices = json.dumps(bt.search())
            return JsonResponse({'nearby_devices':nearby_devices}, status=200)
        else:
            #...
    except:
        #Poignée d'erreur
#...

Lorsque vous recherchez des appareils Bluetooth autour de vous, utilisez la requête Ajax.

bt.search est une fonction de recherche d'appareils Bluetooth à l'aide de Pybluez.

Ce Kawa utilise Websocket au lieu de HTTP pour échanger des messages avec le robot.

control_system/consumers.py


#...
class CommandConsumer(WebsocketConsumer):
    def connect(self):
        #Trouver le modèle de l'appareil sélectionné par l'utilisateur
        self.device_id = self.scope['url_route']['kwargs']['device_id']
        self.device_group_name = 'command_%s' % self.device_id
        device = Device.objects.get(id=self.device_id)

        #Autoriser le consommateur pour Bluetooth à communiquer en série avec l'appareil
        async_to_sync(self.channel_layer.send)('bt-process', {
            'type': 'bt_connect',
            'group_name': self.device_group_name,
            'uuid': device.uuid,
            'device' : device.id,
            }
        )

        #Ajouter un utilisateur au groupe
        async_to_sync(self.channel_layer.group_add)(
            self.device_group_name,
            self.channel_name
        )

        self.accept()

    #...

    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        device_id = text_data_json['device']

        #Envoyer des commandes à l'appareil
        async_to_sync(self.channel_layer.send)('bt-process', {
            'type': 'bt_send_serial',
            'device': device_id,
            'message': message,
            }
        )

        #...

    #Enregistrer et transférer les messages de réponse reçus des appareils Bluetooth
    def command_message(self, event):
        message = event['message']
        device_id = event['device']
        
        #Enregistrer dans le modèle d'appareil avec horodatage
        device = Device.objects.get(id=device_id)
        new_history = CommandHistory(device=device, command=message )
        new_history.save()

        command_history = {}
        all_history = device.history.all()
        for command in all_history:
            command_history[command.timestamp.strftime('%H:%M:%S')] = command.command + '\n'


        #Envoyer l'historique des commandes à l'utilisateur
        self.send(text_data=json.dumps({
            'message': command_history,
            'device': device_id
        }))

C'est un peu compliqué, mais pour l'expliquer brièvement

--Connect ouvre la communication Websocket avec l'utilisateur et active la communication avec le périphérique Bluetooth. «Processus Bt» fait référence au consommateur des appareils Bluetooth actuellement exécutés en arrière-plan. J'ai envie d'essayer d'utiliser «bt_connect» de «bt-process».

--Receive envoie une commande à l'appareil contenu dans le message au robot lorsque l'utilisateur envoie un message à l'aide de la page Web. Cela envoie également un message à «bt-process» de la même manière que ci-dessus.

--command_message enregistre la réponse reçue du robot dans le modèle de base de données du robot. Le message a une relation plusieurs-à-un avec le modèle de robot. C'est un formulaire qui est connecté en utilisant l'identifiant du robot.

Vient ensuite la classe consommateur pour communiquer avec le robot.

bluetooth_interface/consumers.py


#...
from bluetooth_interface import bt_functions
#...
class BTConsumer(SyncConsumer):

    def bt_connect(self, message):
            #N'oubliez pas de pouvoir envoyer un message à l'utilisateur
            self.device_group_name = message['group_name']
            self.sock = {}

            #Numéro de port de communication Bluetooth
            self.port_num = 1

            #Créer une prise de communication
            sock, msg = bt_functions.connect(message['uuid'], self.port_num)

            #Prise d'enregistrement avec identifiant de l'appareil
            if sock != 1: 
                self.sock = {message['device']:[sock, self.port_num]}

            #Envoyer l'état de la communication à l'utilisateur
            async_to_sync(self.channel_layer.group_send)(
                    self.device_group_name,
                    {
                        'type': 'command_message',
                        'device': message['device'],
                        'message': msg,
                        }
                    )

    #...

    def bt_send_serial(self, event):
        
        #Prenez l'identifiant de l'appareil et le message demandé par l'utilisateur
        device_id = int(event['device'])
        message = event['message']

        #Sélectionnez une prise pour communiquer avec l'appareil et envoyer un message
        if device_id in self.sock.keys():
            result = bt_functions.send_serial(self.sock[device_id][0], message)
        #Envoyer un message de réponse à l'utilisateur
            async_to_sync(self.channel_layer.group_send)(
                    self.device_group_name,
                    {
                        'type': 'command_message',
                        'device': device_id,
                        'message': result,
                        }
                    )

    #...

J'étais assez confus sur la façon de le faire ici. Par conséquent

--Créez un consommateur qui permet au robot d'envoyer des messages (données de capteur, réponses aux commandes, etc.) à tout moment

Je l'ai rendu possible.

Django Channels utilise la couche Channels pour permettre la communication entre les classes et les processus Consumer.

Ainsi, même si l'utilisateur se déconnecte ou effectue un autre travail, il est toujours connecté au robot dans un autre processus.

Je ne l'ai pas encore créé, mais je peux toujours obtenir des données de capteur à partir de robots et d'appareils IoT de cette manière.

Consultez la documentation des canaux Django pour plus de détails. https://channels.readthedocs.io/en/latest/topics/channel_layers.html https://channels.readthedocs.io/en/latest/topics/worker.html

finalement

Je pense qu'il aurait été plus facile de créer un projet avec Node.js, qui est facile à utiliser avec Async.

Cependant, j'ai utilisé Django et Django Channels car je voulais utiliser les nombreuses fonctionnalités de Django (sécurité, gestion des utilisateurs, formulaires, etc.).

Il a fallu environ 2 semaines pour arriver à ce point. Il y avait beaucoup de nouveautés, il était donc surtout temps de lire et d'étudier des documents.

Merci d'avoir lu cette fois aussi.

Recommended Posts

"2/2" Je crée une application Web simple pour le fonctionnement du robot. «Chaînes Raspberry Pi 3B + et Django»
"1/2" Je crée une application Web simple pour le fonctionnement du robot. «Chaînes Raspberry Pi 3B + et Django»
J'ai fait une application WEB avec Django
[Pour les débutants] J'ai fait un capteur humain avec Raspberry Pi et notifié LINE!
Créez une caméra de surveillance WEB avec Raspberry Pi et OpenCV
J'ai essayé de connecter Raspeye et conect + avec l'API Web
J'ai créé un moniteur de ressources pour Raspberry Pi avec une feuille de calcul
(Pour les débutants) Essayez de créer une API Web simple avec Django
J'ai créé un serveur Web avec Razpai pour regarder des anime
Fabriquez un incubateur à CO2 simple à l'aide de Raspberry PI et d'un capteur de CO2 (MH-Z14A)
Lancement d'une application Web sur AWS avec django et modification des tâches
Créer une application Web avec Django
Créez un convertisseur Ethernet LAN sans fil et un routeur simple avec Raspberry Pi
Je souhaite créer une application Web en utilisant React et Python flask
Expliquez doucement le processus de création d'une simple caméra de surveillance sans serveur à l'aide de Raspeye, de l'API Gmail et de l'API Line
[Raspberry Pi] Ajouter un thermomètre et un hygromètre
J'ai essayé de comparer le cadre d'application Web
Source compilez Apache2.4 + PHP7.4 avec Raspberry Pi et construisez un serveur Web --2 introduction PHP
Source compilez Apache2.4 + PHP7.4 avec Raspberry Pi et créez un serveur Web ―― 1. Introduction à Apache
J'ai essayé d'exécuter Flask sur Raspberry Pi 3 Model B + en utilisant Nginx et uWSGI
L'histoire de la création d'une application Web qui enregistre des lectures approfondies avec Django
J'ai essayé de créer un bouton pour Slack avec Raspeye + Tact Switch
Essayez de créer une application Web avec Vue.js et Django (édition Mac) - (1) Construction d'environnement, création d'application