Es ist s_rae. Ich lerne hart Programmieren.
Als Praxis der Anwendungsentwicklung habe ich eine Schnittstelle erstellt, die den Roboter bedienen kann. https://github.com/samanthanium/dullahan_local Sie können den Quellcode unter sehen.
Im Anschluss an den vorherigen Beitrag werde ich diesmal ein wenig über die Quelle erklären. Letztes Mal: https://qiita.com/s_rae/items/d808c3eccd8e173dc55b
Da es für Hobbyzwecke gemacht wurde, werde ich die Fehlerbehandlung weglassen.
Wir verwenden diese Technologie für dieses Projekt.
Django bediente hauptsächlich Webseiten über HTTP, verwaltete Benutzer in Sitzungen und arbeitete an der SQLite-Datenbank.
Das Django-Projekt besteht übrigens aus mehreren Apps (Code, der für andere Projekte wiederverwendet werden kann).
Dieses Projekt --dullahan (Haupt-App des Projekts) --pages (Für Home, About, Login Webseiten) --control_system (Seite zum Senden von Befehlen und Registrieren von Geräten) --bluetooth_interface (einschließlich Consumer und Funktion des Bluetooth-Geräts)
Es besteht aus "App".
Der Grund, warum ich Django verwendet habe, ist, dass es viele Funktionen hat und schnell erstellt werden kann. Ich wollte auch Python üben.
Django Channels Django Channels ist eine Bibliothek, die für das Django-Framework erstellt wurde. Es ist möglich, dem Django-Framework Funktionen wie Websocket hinzuzufügen.
Channels ist ein Mechanismus, der die Klasse "Consumer" zum Verarbeiten von WebSocket-Nachrichten verwendet. Es kann Funktionen ausführen, die der Ansicht des Django-Frameworks ähneln.
Pybluez Pybluez ist eine Bibliothek, die erstellt wurde, um die Bluetooth-Funktionalität des Systems in Python zu nutzen. Ich werde den Pybluez-Code hier nicht erklären, aber Sie können den Code auf ähnliche Weise wie das Socket-Modul schreiben.
Benutzer meldet sich an> Gerät hinzufügen-> Befehl an Gerät senden Ich werde den Gefühlsfluss erklären.
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})
Hier ist die Funktion für die Benutzeranmeldung. Sie können sich einfach mit der in Djangos Formularen enthaltenen Methode "form.get_user" anmelden.
Nachdem
@login_required
Sie können den aktuellen Benutzer mithilfe des Dekorators von in der Ansicht überprüfen.
Als nächstes wird der Bildschirm angezeigt, auf dem nach den umgebenden Bluetooth-Geräten gesucht und diese aufgezeichnet werden können.
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:
#Fehlerbehandlung
#...
Verwenden Sie bei der Suche nach Bluetooth-Geräten in Ihrer Nähe die Ajax-Anfrage.
bt.search ist eine Funktion zum Suchen nach Bluetooth-Geräten mit Pybluez.
Dieser Kawa verwendet Websocket anstelle von HTTP, um Nachrichten mit dem Roboter auszutauschen.
control_system/consumers.py
#...
class CommandConsumer(WebsocketConsumer):
def connect(self):
#Suchen Sie das Modell des vom Benutzer ausgewählten Geräts
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)
#Ermöglichen Sie dem Consumer für Bluetooth die serielle Kommunikation mit dem Gerät
async_to_sync(self.channel_layer.send)('bt-process', {
'type': 'bt_connect',
'group_name': self.device_group_name,
'uuid': device.uuid,
'device' : device.id,
}
)
#Benutzer zur Gruppe hinzufügen
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']
#Senden Sie Befehle an das Gerät
async_to_sync(self.channel_layer.send)('bt-process', {
'type': 'bt_send_serial',
'device': device_id,
'message': message,
}
)
#...
#Speichern und Weiterleiten von Antwortnachrichten, die von Bluetooth-Geräten empfangen wurden
def command_message(self, event):
message = event['message']
device_id = event['device']
#Mit Zeitstempel im Gerätemodell speichern
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'
#Befehlsverlauf an Benutzer senden
self.send(text_data=json.dumps({
'message': command_history,
'device': device_id
}))
Das ist etwas kompliziert, aber um es kurz zu erklären
--Connect öffnet die Websocket-Kommunikation mit dem Benutzer und ermöglicht die Kommunikation mit dem Bluetooth-Gerät. "Bt-Prozess" bezieht sich auf den Verbraucher für Bluetooth-Geräte, der derzeit im Hintergrund ausgeführt wird. Ich möchte versuchen, "bt_connect" von "bt-process" zu verwenden.
--receive sendet einen Befehl an das in der Nachricht enthaltene Gerät an den Roboter, wenn der Benutzer eine Nachricht über die Webseite sendet. Dies sendet auf die gleiche Weise wie oben auch eine Nachricht an "bt-process".
--command_message speichert die vom Roboter empfangene Antwort im Datenbankmodell des Roboters. Die Nachricht hat eine Eins-zu-Eins-Beziehung zum Robotermodell. Es ist ein Formular, das mit der ID des Roboters verbunden ist.
Als nächstes folgt die Verbraucherklasse für die Kommunikation mit dem Roboter.
bluetooth_interface/consumers.py
#...
from bluetooth_interface import bt_functions
#...
class BTConsumer(SyncConsumer):
def bt_connect(self, message):
#Denken Sie daran, eine Nachricht an den Benutzer senden zu können
self.device_group_name = message['group_name']
self.sock = {}
#Bluetooth-Kommunikationsportnummer
self.port_num = 1
#Machen Sie eine Kommunikationsbuchse
sock, msg = bt_functions.connect(message['uuid'], self.port_num)
#Socket mit Geräte-ID aufzeichnen
if sock != 1:
self.sock = {message['device']:[sock, self.port_num]}
#Kommunikationsstatus an Benutzer senden
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):
#Nehmen Sie die vom Benutzer angeforderte Geräte-ID und Nachricht
device_id = int(event['device'])
message = event['message']
#Wählen Sie einen Socket aus, um mit dem Gerät zu kommunizieren, und senden Sie eine Nachricht
if device_id in self.sock.keys():
result = bt_functions.send_serial(self.sock[device_id][0], message)
#Senden Sie eine Antwortnachricht an den Benutzer
async_to_sync(self.channel_layer.group_send)(
self.device_group_name,
{
'type': 'command_message',
'device': device_id,
'message': result,
}
)
#...
Ich war ziemlich verwirrt darüber, wie ich es hier machen soll. Als Ergebnis
--Erstellen Sie einen Verbraucher, mit dem der Roboter jederzeit Nachrichten (Sensordaten, Antworten auf Befehle usw.) senden kann
Ich habe es möglich gemacht.
Django Channels verwendet die Channels Layer, um die Kommunikation zwischen Consumer-Klassen und -Prozessen zu ermöglichen.
Selbst wenn sich der Benutzer abmeldet oder andere Arbeiten ausführt, sind sie in einem anderen Prozess immer mit dem Roboter verbunden.
Ich habe es noch nicht erstellt, kann aber auf diese Weise immer Sensordaten von Robotern und IoT-Geräten abrufen.
Weitere Informationen finden Sie in der Dokumentation zu Django Channels. https://channels.readthedocs.io/en/latest/topics/channel_layers.html https://channels.readthedocs.io/en/latest/topics/worker.html
Ich denke, es wäre einfacher gewesen, ein Projekt mit Node.js zu erstellen, das mit Async einfach zu verwenden ist.
Ich habe jedoch Django- und Django-Kanäle verwendet, weil ich die vielen Funktionen von Django (Sicherheit, Benutzerverwaltung, Formulare usw.) nutzen wollte.
Es hat ungefähr 2 Wochen gedauert, bis es soweit war. Es gab viele neue Dinge, daher war es meistens Zeit, Dokumente zu lesen und zu studieren.
Vielen Dank, dass Sie diesmal auch gelesen haben.