Added Scanner identification and MQTT handling
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
from django.contrib import admin
|
||||
from .models import Scanner
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(Scanner)
|
||||
|
54
booker/booker_fe_consumer.py
Normal file
54
booker/booker_fe_consumer.py
Normal file
@@ -0,0 +1,54 @@
|
||||
from channels.generic.websocket import AsyncWebsocketConsumer
|
||||
import json
|
||||
import logging
|
||||
from homelog import settings
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BookerFeConsumer(AsyncWebsocketConsumer):
|
||||
|
||||
async def connect(self):
|
||||
self.scanner_id = self.scope['url_route']['kwargs']['scanner_id']
|
||||
self.scanner_group_name = self.scanner_id
|
||||
self.group_name = self.scanner_group_name
|
||||
#self.group_name = settings.MQTT_CHANNEL_NAME
|
||||
# join to group
|
||||
await self.channel_layer.group_add(self.scanner_group_name, self.channel_name)
|
||||
topic = f"barcodescanner/{self.scanner_id}/scan"
|
||||
LOGGER.debug(f"send mqtt_subscribe topic {topic} to channel group {self.scanner_group_name} (my channel is {self.channel_name})")
|
||||
await self.channel_layer.send(settings.MQTT_CHANNEL_NAME, {
|
||||
"type": "mqtt.subscribe",
|
||||
"topic": topic,
|
||||
"group": self.scanner_group_name
|
||||
})
|
||||
await self.accept()
|
||||
|
||||
async def disconnect(self):
|
||||
# leave group
|
||||
await self.channel_layer.group_discard(self.group_name, self.channel_name)
|
||||
LOGGER.debug(f"disconnect from channel group {self.group_name}")
|
||||
|
||||
async def receive(self, text_data):
|
||||
print('>>>', text_data)
|
||||
msg = '{"message":"pong!"}' if text_data == '{"message":"ping"}' else text_data
|
||||
print('<<<', msg)
|
||||
await self.channel_layer.group_send(
|
||||
self.scanner_group_name,
|
||||
{
|
||||
'type': 'distribute',
|
||||
'text': msg
|
||||
}
|
||||
)
|
||||
|
||||
async def distribute(self, event):
|
||||
valother = event['text']
|
||||
LOGGER.debug(f"distribute text={valother}")
|
||||
await self.send(text_data=valother)
|
||||
|
||||
async def mqtt_message(self, event):
|
||||
message = event['message']
|
||||
topic = message['topic']
|
||||
payload = message['payload']
|
||||
LOGGER.debug(f"Received message with payload={payload}, topic={topic}")
|
||||
await self.send(text_data=json.dumps({'message': payload, 'topic': topic}))
|
@@ -1,3 +1,18 @@
|
||||
from django.db import models
|
||||
from django.conf import settings
|
||||
from homelog.system_user import get_deleted_user
|
||||
|
||||
# Create your models here.
|
||||
|
||||
class Scanner(models.Model):
|
||||
named_id = models.CharField(max_length=40, unique=True)
|
||||
description = models.CharField(max_length=200)
|
||||
lwt_topic = models.CharField(max_length=200)
|
||||
last_online_ts = models.DateTimeField('last datetime this scanner has been online')
|
||||
assigned_channel_name = models.CharField(max_length=200)
|
||||
assigned_group_name = models.CharField(max_length=200)
|
||||
created_ts = models.DateTimeField('datetime created', auto_now_add=True)
|
||||
created_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_deleted_user),
|
||||
related_name='created_scanners')
|
||||
changed_ts = models.DateTimeField('datetime updated', auto_now=True)
|
||||
changed_by = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET(get_deleted_user),
|
||||
related_name='changed_scanners')
|
||||
|
@@ -1,48 +0,0 @@
|
||||
from channels.generic.websocket import AsyncWebsocketConsumer
|
||||
import json
|
||||
|
||||
'''
|
||||
class ScannerCollector(WebsocketConsumer):
|
||||
def connect(self):
|
||||
self.accept()
|
||||
|
||||
def disconnect(self, close_code):
|
||||
pass
|
||||
|
||||
def receive(self, text_data):
|
||||
text_data_json = json.loads(text_data)
|
||||
message = text_data_json['message']
|
||||
|
||||
self.send(text_data=json.dumps({
|
||||
'message': message
|
||||
}))
|
||||
'''
|
||||
|
||||
class ScannerCollector(AsyncWebsocketConsumer):
|
||||
|
||||
async def connect(self):
|
||||
self.group_name = 'scanner'
|
||||
# join to group
|
||||
await self.channel_layer.group_add(self.group_name, self.channel_name)
|
||||
await self.accept()
|
||||
|
||||
async def disconnect(self):
|
||||
# leave group
|
||||
await self.channel_layer.group_discard(self.group_name, self.channel_name)
|
||||
|
||||
async def receive(self, text_data):
|
||||
print('>>>', text_data)
|
||||
msg = '{"message":"pong!"}' if text_data == '{"message":"ping"}' else text_data
|
||||
print('<<<', msg)
|
||||
await self.channel_layer.group_send(
|
||||
self.group_name,
|
||||
{
|
||||
'type': 'distribute',
|
||||
'text': msg
|
||||
}
|
||||
)
|
||||
|
||||
async def distribute(self, event):
|
||||
valother = event['text']
|
||||
await self.send(text_data=valother)
|
||||
|
77
booker/scanner_announce_consumer.py
Normal file
77
booker/scanner_announce_consumer.py
Normal file
@@ -0,0 +1,77 @@
|
||||
import datetime
|
||||
import logging
|
||||
import re
|
||||
import json
|
||||
from channels.generic.websocket import AsyncWebsocketConsumer
|
||||
from booker.models import Scanner
|
||||
from asgiref.sync import sync_to_async
|
||||
from channels.db import database_sync_to_async
|
||||
from django.contrib.auth import get_user_model
|
||||
from homelog.system_user import get_system_user
|
||||
from homelog import settings
|
||||
from django.core.exceptions import ObjectDoesNotExist
|
||||
|
||||
LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class ScannerAnnounceConsumer(AsyncWebsocketConsumer):
|
||||
|
||||
async def connect(self):
|
||||
self.group_name = 'scanner-announce'
|
||||
# join to group
|
||||
await self.channel_layer.group_add(self.group_name, self.channel_name)
|
||||
LOGGER.debug(f"send mqtt_subscribe to channel layer {settings.MQTT_CHANNEL_NAME} to answer on channel {self.group_name} (my channel is {self.channel_name})")
|
||||
await self.channel_layer.send(settings.MQTT_CHANNEL_NAME, {
|
||||
"type": "mqtt.subscribe",
|
||||
"topic": "barcodescanner/+/status",
|
||||
"group": self.group_name
|
||||
})
|
||||
LOGGER.debug("ScannerAnnounceConsumer initialized")
|
||||
await self.accept()
|
||||
|
||||
async def receive(self, mqtt_message):
|
||||
pass
|
||||
|
||||
async def disconnect(self, code):
|
||||
await self.channel_layer.send(settings.MQTT_CHANNEL_NAME, {
|
||||
"type": "mqtt.unsubscribe",
|
||||
"topic": "barcodescanner/#/status",
|
||||
"group": self.group_name
|
||||
})
|
||||
LOGGER.debug(f"Disconnect from scanner-announce, unsubscribing topic; code={code}")
|
||||
await self.channel_layer.group_discard(self.group_name, self.channel_name)
|
||||
|
||||
async def distribute(self, event):
|
||||
valother = event['text']
|
||||
await self.send(text_data=valother)
|
||||
|
||||
@database_sync_to_async
|
||||
def get_or_create_scanner(self, named_id, topic):
|
||||
scanner, created = Scanner.objects.get_or_create(named_id=named_id, defaults={
|
||||
'lwt_topic': topic,
|
||||
'last_online_ts': datetime.datetime.now(),
|
||||
'created_by': get_system_user(),
|
||||
'changed_by': get_system_user()
|
||||
})
|
||||
if created:
|
||||
LOGGER.debug(f"Created new scanner entry for {named_id}")
|
||||
else:
|
||||
LOGGER.debug(f"Updated scanner entry for {named_id}")
|
||||
return scanner
|
||||
|
||||
async def mqtt_message(self, event):
|
||||
message = event['message']
|
||||
topic = message['topic']
|
||||
qos = message['qos']
|
||||
payload = message['payload']
|
||||
print('Received a message at topic: ', topic)
|
||||
print('with payload ', payload)
|
||||
print('and QOS ', qos)
|
||||
named_id = 'invalid'
|
||||
m = re.match(r'barcodescanner\/(barcodescan-[0-9,a-f]{6})\/status', topic)
|
||||
if m:
|
||||
named_id = m[1]
|
||||
await self.send(text_data=json.dumps({'message': payload, 'scanner': named_id, 'topic': topic}))
|
||||
LOGGER.debug(f"Got MQTT message from {topic} with payload {payload}")
|
||||
if payload == 'Online' or payload == 'online':
|
||||
scanner = await self.get_or_create_scanner(named_id=named_id, topic=topic)
|
@@ -4,21 +4,55 @@
|
||||
{% block title %}Scanner Index{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
What chat room would you like to enter?<br>
|
||||
<input id="room-name-input" type="text" size="100"><br>
|
||||
<input id="room-name-submit" type="button" value="Enter">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<h1>Booker</h1>
|
||||
<p>Choose a scanner you want to use to book assets and container into/outof containers.</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="cols-12">
|
||||
<textarea id="chat-log" cols="100" rows="7"></textarea><br>
|
||||
|
||||
<script>
|
||||
document.querySelector('#room-name-input').focus();
|
||||
document.querySelector('#room-name-input').onkeyup = function(e) {
|
||||
if (e.keyCode === 13) { // enter, return
|
||||
document.querySelector('#room-name-submit').click();
|
||||
}
|
||||
};
|
||||
What scanner would you like to use? (Refresh page if your new scanner is not shown)<br>
|
||||
{% for scanner in object_list %}
|
||||
<a href="/booker/{{ scanner.named_id }}/">{{ scanner.named_id }}: {{ scanner.description }}</a><br />
|
||||
{% endfor %}
|
||||
<input id="scanner-name-input" type="text" size="100"><br>
|
||||
<input id="scanner-name-submit" type="button" value="Enter">
|
||||
|
||||
document.querySelector('#room-name-submit').onclick = function(e) {
|
||||
var roomName = document.querySelector('#room-name-input').value;
|
||||
window.location.pathname = '/booker/' + roomName + '/';
|
||||
};
|
||||
</script>
|
||||
<script>
|
||||
document.querySelector('#scanner-name-input').focus();
|
||||
document.querySelector('#scanner-name-input').onkeyup = function(e) {
|
||||
if (e.keyCode === 13) { // enter, return
|
||||
document.querySelector('#scanner-name-submit').click();
|
||||
}
|
||||
};
|
||||
|
||||
document.querySelector('#scanner-name-submit').onclick = function(e) {
|
||||
var scannerName = document.querySelector('#scanner-name-input').value;
|
||||
window.location.pathname = '/booker/' + scannerName + '/';
|
||||
};
|
||||
</script>
|
||||
|
||||
<script>
|
||||
const chatSocket = new WebSocket(
|
||||
'ws://'
|
||||
+ window.location.host
|
||||
+ '/ws/scanner-announce/'
|
||||
);
|
||||
|
||||
chatSocket.onmessage = function(e) {
|
||||
const data = JSON.parse(e.data);
|
||||
document.querySelector('#chat-log').value += (data.scanner + ': ' + data.message + '\n');
|
||||
};
|
||||
|
||||
chatSocket.onclose = function(e) {
|
||||
console.error('Chat socket closed unexpectedly');
|
||||
document.querySelector('#chat-log').value += ('ERROR: Chat socket closed unexpectedly!\n');
|
||||
};
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
@@ -7,15 +7,15 @@
|
||||
<textarea id="chat-log" cols="100" rows="20"></textarea><br>
|
||||
<input id="chat-message-input" type="text" size="100"><br>
|
||||
<input id="chat-message-submit" type="button" value="Send">
|
||||
{{ scanner_id|json_script:"room-name" }}
|
||||
{{ scanner_id|json_script:"scanner_id" }}
|
||||
<script>
|
||||
const roomName = JSON.parse(document.getElementById('room-name').textContent);
|
||||
const scannerId = JSON.parse(document.getElementById('scanner_id').textContent);
|
||||
|
||||
const chatSocket = new WebSocket(
|
||||
'ws://'
|
||||
+ window.location.host
|
||||
+ '/ws/scannerdata/'
|
||||
+ roomName
|
||||
+ '/ws/scanner/'
|
||||
+ scannerId
|
||||
+ '/'
|
||||
);
|
||||
|
||||
|
@@ -4,6 +4,6 @@ from . import views
|
||||
app_name = 'booker'
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.index, name='index'),
|
||||
path('', views.IndexView.as_view(), name='index'),
|
||||
path('<str:scanner_id>/', views.scanner, name='scanner')
|
||||
]
|
||||
|
@@ -1,10 +1,14 @@
|
||||
from django.shortcuts import render
|
||||
from django.views.generic import ListView
|
||||
from .models import Scanner
|
||||
|
||||
|
||||
def index(request):
|
||||
return render(request, 'booker/index.html')
|
||||
class IndexView(ListView):
|
||||
model = Scanner
|
||||
template_name = 'booker/index.html'
|
||||
|
||||
|
||||
def scanner(request, scanner_id):
|
||||
return render(request, 'booker/scanner.html', {
|
||||
'scanner_id': scanner_id
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user