doorcontrol: Add annotations that decode the hex card number
This commit is contained in:
parent
67f13ce580
commit
906f662419
@ -30,9 +30,10 @@ class HIDEventAdmin(admin.ModelAdmin):
|
||||
"event_type",
|
||||
IsRedFilter,
|
||||
]
|
||||
readonly_fields = ["decoded_card_number"]
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).with_is_red()
|
||||
return super().get_queryset(request).with_is_red().with_decoded_card_number()
|
||||
|
||||
@admin.display(boolean=True)
|
||||
def is_red(self, obj):
|
||||
|
@ -1,5 +1,6 @@
|
||||
from django.db import models
|
||||
from django.db.models import ExpressionWrapper, Q
|
||||
from django.db.models import ExpressionWrapper, F, Func, Q
|
||||
from django.db.models.functions import Mod
|
||||
|
||||
|
||||
class HIDEventQuerySet(models.QuerySet):
|
||||
@ -28,6 +29,42 @@ class HIDEventQuerySet(models.QuerySet):
|
||||
)
|
||||
)
|
||||
|
||||
def with_decoded_card_number(self):
|
||||
# TODO: CONV and BIT_COUNT are MySQL/MariaDB specific
|
||||
class Conv(Func):
|
||||
function = "CONV"
|
||||
arity = 3
|
||||
# This is technically not true, but fine for my purposes
|
||||
output_field = models.IntegerField()
|
||||
|
||||
class BitCount(Func):
|
||||
function = "BIT_COUNT"
|
||||
arity = 1
|
||||
|
||||
return (
|
||||
self.alias(card_number=Conv(F("raw_card_number"), 16, 10))
|
||||
.alias(more_than_26_bits=F("card_number").bitrightshift(26))
|
||||
.annotate(card_is_26_bit=Q(more_than_26_bits=0))
|
||||
.alias(
|
||||
parity_a=Mod(
|
||||
BitCount(F("card_number").bitrightshift(1).bitand(0xFFF)), 2
|
||||
),
|
||||
parity_b=Mod(
|
||||
BitCount(F("card_number").bitrightshift(13).bitand(0xFFF)), 2
|
||||
),
|
||||
)
|
||||
.annotate(
|
||||
card_is_valid_26_bit=~Q(parity_a=F("card_number").bitand(1))
|
||||
& Q(parity_b=F("card_number").bitrightshift(25).bitand(1))
|
||||
)
|
||||
.annotate(
|
||||
card_number_26_bit=F("card_number").bitrightshift(1).bitand(0xFFFF),
|
||||
card_facility_code_26_bit=F("card_number")
|
||||
.bitrightshift(17)
|
||||
.bitand(0xFF),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class HIDEvent(models.Model):
|
||||
objects = HIDEventQuerySet.as_manager()
|
||||
@ -121,6 +158,18 @@ class HIDEvent(models.Model):
|
||||
def __str__(self):
|
||||
return f"{self.door_name} {self.timestamp} - {self.description}"
|
||||
|
||||
def decoded_card_number(self) -> str:
|
||||
"""Requires annotations from `with_decoded_card_number`"""
|
||||
if self.raw_card_number is None:
|
||||
return None
|
||||
elif self.card_is_26_bit:
|
||||
if self.card_is_valid_26_bit:
|
||||
return f"{self.card_facility_code_26_bit} - {self.card_number_26_bit}"
|
||||
else:
|
||||
return "Invalid"
|
||||
else:
|
||||
return "Not 26 bit card"
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(
|
||||
|
Loading…
Reference in New Issue
Block a user