add visitor counter. only run tasks when > 0 visitors

This commit is contained in:
Maxi Quoß
2021-09-21 17:03:30 +02:00
parent 69a4faebe1
commit 6b16a59627
12 changed files with 117 additions and 40 deletions

View File

@@ -4,7 +4,7 @@ A simple wake on lan app written with Django, Django-Channels (websockets), Cele
| Dark | Light |
| -------------------- | --------------------- |
| ![](assets/dark.jpg) | ![](assets/light.jpg) |
| ![](assets/dark.png) | ![](assets/light.png) |
## Run your own instance

View File

@@ -9,14 +9,18 @@ https://docs.djangoproject.com/en/3.1/howto/deployment/asgi/
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_wol.settings")
django_asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from django.core.asgi import get_asgi_application
from wol.routing import ws_urlpatterns
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'django_wol.settings')
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"http": django_asgi_app,
"websocket": AuthMiddlewareStack(URLRouter(ws_urlpatterns))
})

View File

@@ -9,6 +9,10 @@ if [ -n "$DJANGO_SUPERUSER_USER" ] && [ -n "$DJANGO_SUPERUSER_PASSWORD" ]; then
python -u manage.py shell -c "from django.contrib.auth.models import User; User.objects.create_superuser('$DJANGO_SUPERUSER_USER', password='$DJANGO_SUPERUSER_PASSWORD') if not User.objects.filter(username='$DJANGO_SUPERUSER_USER').exists() else print('Django user exists')"
fi
# set visitors to 0
python -u manage.py shell -c "from wol.models import Websocket; [i.delete() for i in Websocket.objects.all()]; Websocket.objects.create(visitors=0)"
celery -A django_wol worker &
celery -A django_wol beat &
gunicorn --bind 0.0.0.0:"$DJANGO_PORT" --workers 4 django_wol.asgi:application -k uvicorn.workers.UvicornWorker

View File

@@ -1,15 +1,55 @@
import json
from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
from .models import Websocket
class WSConsumer(AsyncWebsocketConsumer):
async def connect(self):
await self.channel_layer.group_add("status", self.channel_name)
await self.channel_layer.group_add("wol", self.channel_name)
await self.accept()
await self.add_visitor()
await self.channel_layer.group_send(
"wol", {
"type": "send_visitors",
"message": {
"visitors": await self.get_visitors()
}
}
)
async def disconnect(self, code):
await self.channel_layer.group_discard("status", self.channel_name)
await self.channel_layer.group_discard("wol", self.channel_name)
await self.remove_visitor()
await self.channel_layer.group_send(
"wol", {
"type": "send_visitors",
"message": {
"visitors": await self.get_visitors()
}
}
)
async def send_status(self, event):
text_message = event["status"]
await self.send(event["status"])
await self.send(text_message)
async def send_visitors(self, event):
await self.send(json.dumps(event["message"]))
@database_sync_to_async
def add_visitor(self):
visitor_count = Websocket.objects.first()
visitor_count.visitors += 1
visitor_count.save()
@database_sync_to_async
def remove_visitor(self):
visitor_count = Websocket.objects.first()
visitor_count.visitors -= 1
visitor_count.save()
@database_sync_to_async
def get_visitors(self):
return str(Websocket.objects.first().visitors)

View File

@@ -7,3 +7,6 @@ class Device(models.Model):
ip = models.GenericIPAddressField()
mac = models.CharField(max_length=17)
netmask = models.CharField(max_length=15, default="255.255.255.0", blank=False, null=False)
class Websocket(models.Model):
visitors = models.PositiveSmallIntegerField(blank=False, null=False, default=0)

View File

@@ -42,6 +42,12 @@
background-color: var(--down-red);
}
.button.is-static {
background-color: #dbdbdb;
border-color: transparent;
color: #363636;
}
@media (prefers-color-scheme: dark) {
.box {
background-color: var(--box-bg);

View File

@@ -7,10 +7,16 @@ $('.wake-form').submit(function (e) {
var socket = new WebSocket("ws://" + location.host + "/wol/");
socket.onmessage = function(event) {
var device = JSON.parse(event.data);
console.log(device);
var message = JSON.parse(event.data);
console.log(message);
if ("visitors" in message) {
document.getElementById("visitors").innerHTML = message.visitors + ' Visitors';
return;
}
// get elements
var device = message.device
var deviceBox = document.getElementById(device.id + "-container");
var statusDot = document.getElementById(device.id + "-dot");
var statusPorts = document.getElementById(device.id + "-ports");

View File

@@ -7,7 +7,7 @@ from asgiref.sync import async_to_sync
from celery import shared_task
from channels.layers import get_channel_layer
from .models import Device
from .models import Device, Websocket
channel_layer = get_channel_layer()
@@ -29,6 +29,7 @@ class WolDevice:
def start(self, dev):
data = {
"device": {
"id": dev.id,
"name": dev.name,
"ip": dev.ip,
@@ -38,22 +39,26 @@ class WolDevice:
"rdp": False,
"ssh": False
}
}
if self.ping_device(dev.ip):
data["up"] = True
data["device"]["up"] = True
if self.check_port(dev.ip, 5900):
data["vnc"] = True
data["device"]["vnc"] = True
if self.check_port(dev.ip, 3389):
data["rdp"] = True
data["device"]["rdp"] = True
if self.check_port(dev.ip, 22):
data["ssh"] = True
data["device"]["ssh"] = True
async_to_sync(channel_layer.group_send)(
"status", {"type": "send_status", "status": json.dumps(data)})
"wol", {"type": "send_status", "status": json.dumps(data)})
@shared_task
def status():
if Websocket.objects.first().visitors == 0:
return
devices = Device.objects.all()
for dev in devices:

View File

@@ -27,12 +27,24 @@
</p>
</div>
<div class="column is-one-third">
<div class="field is-grouped">
<p class="control">
<a class="button is-light" href="/admin">
<span>Admin</span>
<span class="icon is-small">
<i class="fas fa-user-cog"></i>
</span>
</a>
</p>
<p class="control">
<div class="button is-static is-light">
<span id="visitors">{{ visitors }} Visitors</span>
<span class="icon is-small">
<i class="fas fa-users"></i>
</span>
</div>
</p>
</div>
</div>
</div>
</div>

View File

@@ -1,22 +1,19 @@
import ipaddress
import json
import subprocess
from platform import system
import wakeonlan
from django.core.serializers import serialize
from django.http import JsonResponse
from django.shortcuts import HttpResponse, get_object_or_404, render
from .forms import WakeDeviceForm
from .models import Device
from .models import Device, Websocket
def index(request):
devices = Device.objects.all().order_by("name")
visitors = Websocket.objects.first().visitors
context = {
"devices": devices
"devices": devices,
"visitors": visitors
}
return render(request, "wol/index.html", context)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 241 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 243 KiB