2023-01-24 21:21:26 -05:00
|
|
|
from django.db import models
|
2023-04-03 17:16:48 -04:00
|
|
|
from django.db.models import ExpressionWrapper, Q
|
|
|
|
|
|
|
|
|
|
|
|
class HIDEventQuerySet(models.QuerySet):
|
|
|
|
def with_is_red(self):
|
|
|
|
"""Based on `function isRedEvent` from /html/hid-global.js on a HID EDGE EVO Solo"""
|
|
|
|
return self.annotate(
|
|
|
|
is_red=ExpressionWrapper(
|
|
|
|
Q(
|
|
|
|
event_type__in=[
|
|
|
|
1022,
|
|
|
|
1023,
|
|
|
|
2024,
|
|
|
|
2029,
|
|
|
|
2036,
|
|
|
|
2042,
|
|
|
|
2043,
|
|
|
|
2046,
|
|
|
|
4041,
|
|
|
|
4042,
|
|
|
|
4043,
|
|
|
|
4044,
|
|
|
|
4045,
|
|
|
|
]
|
|
|
|
),
|
|
|
|
output_field=models.BooleanField(),
|
|
|
|
)
|
|
|
|
)
|
2023-01-24 21:21:26 -05:00
|
|
|
|
|
|
|
|
|
|
|
class HIDEvent(models.Model):
|
2023-04-03 17:16:48 -04:00
|
|
|
objects = HIDEventQuerySet.as_manager()
|
|
|
|
|
2023-01-24 21:21:26 -05:00
|
|
|
class EventType(models.IntegerChoices):
|
|
|
|
DENIED_ACCESS_CARD_NOT_FOUND = 1022, "Denied Access: Card Not Found"
|
|
|
|
DENIED_ACCESS_ACCESS_PIN_NOT_FOUND = 1023, "Denied Access Access: PIN Not Found"
|
|
|
|
GRANTED_ACCESS = 2020, "Granted Access"
|
|
|
|
GRANTED_ACCESS_EXTENDED_TIME = 2021, "Granted Access: Extended Time"
|
|
|
|
DENIED_ACCESS_SCHEDULE = 2024, "Denied Access: Schedule"
|
|
|
|
DENIED_ACCESS_WRONG_PIN = 2029, "Denied Access: Wrong PIN"
|
|
|
|
DENIED_ACCESS_CARD_EXPIRED = 2036, "Denied Access: Card Expired"
|
|
|
|
DENIED_ACCESS_PIN_LOCKOUT = 2042, "Denied Access: PIN Lockout"
|
|
|
|
DENIED_ACCESS_UNASSIGNED_CARD = 2043, "Denied Access: Unassigned Card"
|
|
|
|
DENIED_ACCESS_UNASSIGNED_ACCESS_PIN = (
|
|
|
|
2044,
|
|
|
|
"Denied Access: Unassigned Access PIN",
|
|
|
|
)
|
|
|
|
DENIED_ACCESS_PIN_EXPIRED = 2046, "Denied Access: PIN Expired"
|
|
|
|
ALARM_ACKNOWLEDGED = 4034, "Alarm Acknowledged"
|
|
|
|
DOOR_LOCKED_SCHEDULED = 4035, "Door Locked: Scheduled"
|
|
|
|
DOOR_UNLOCKED_SCHEDULED = 4036, "Door Unlocked: Scheduled"
|
|
|
|
DOOR_FORCED_ALARM = 4041, "Door Forced Alarm"
|
|
|
|
DOOR_HELD_ALARM = 4042, "Door Held Alarm"
|
|
|
|
TAMPER_SWITCH_ALARM = 4043, "Tamper Switch Alarm"
|
|
|
|
AC_FAILURE = 4044, "AC Failure"
|
|
|
|
BATTERY_FAILURE = 4045, "Battery Failure"
|
|
|
|
REX_SWITCH_ALARM = 4051, "REX Switch Alarm"
|
|
|
|
TIME_SET_TO = 7020, "Time Set To"
|
|
|
|
GRANTED_ACCESS_MANUAL = 12031, "Granted Access: Manual"
|
|
|
|
DOOR_UNLOCKED = 12032, "Door Unlocked"
|
|
|
|
DOOR_LOCKED = 12033, "Door Locked"
|
|
|
|
|
|
|
|
door_name = models.CharField(max_length=64, db_column="doorName")
|
|
|
|
timestamp = models.DateTimeField()
|
|
|
|
event_type = models.IntegerField(db_column="eventType", choices=EventType.choices)
|
|
|
|
reader_address = models.IntegerField(db_column="readerAddress")
|
|
|
|
cardholder_id = models.IntegerField(blank=True, null=True, db_column="cardholderID")
|
|
|
|
command_status = models.BooleanField(
|
|
|
|
blank=True, null=True, db_column="commandStatus"
|
|
|
|
)
|
|
|
|
forename = models.TextField(blank=True, null=True)
|
|
|
|
surname = models.TextField(blank=True, null=True)
|
|
|
|
io_state = models.BooleanField(blank=True, null=True, db_column="ioState")
|
|
|
|
new_time = models.DateTimeField(blank=True, null=True, db_column="newTime")
|
|
|
|
old_time = models.DateTimeField(blank=True, null=True, db_column="oldTime")
|
|
|
|
raw_card_number = models.CharField(
|
|
|
|
max_length=8, blank=True, null=True, db_column="rawCardNumber"
|
|
|
|
)
|
|
|
|
|
|
|
|
@property
|
|
|
|
def description(self):
|
|
|
|
"""
|
|
|
|
Based on `Global.localeStrings` from /html/en_EN/en_EN.js
|
|
|
|
and `function eventDataHandler` from /html/modules/hid-dashboard.js
|
|
|
|
on a HID EDGE EVO Solo
|
|
|
|
"""
|
|
|
|
|
|
|
|
name = f"{self.forename} {self.surname}"
|
|
|
|
direction = "IN" if self.reader_address == 0 else "OUT"
|
|
|
|
|
|
|
|
event_types = {
|
|
|
|
1022: f"Denied Access, {direction} Card Not Found {self.raw_card_number}",
|
|
|
|
1023: f"Denied Access, {direction} Access PIN Not Found {self.raw_card_number}",
|
|
|
|
2020: f"Granted Access, {direction} {name}",
|
|
|
|
2021: f"Granted Access, {direction} Extended Time {name}",
|
|
|
|
2024: f"Denied Access, {direction} Schedule {name}",
|
|
|
|
2029: f"Denied Access, {direction} Wrong PIN {name}",
|
|
|
|
2036: f"Denied Access, {direction} Card Expired {name}",
|
|
|
|
2042: f"Denied Access, {direction} PIN Lockout {name}",
|
|
|
|
2043: f"Denied Access, {direction} Unassigned Card {self.raw_card_number}",
|
|
|
|
2044: f"Denied Access, {direction} Unassigned Access PIN {self.raw_card_number}",
|
|
|
|
2046: f"Denied Access - PIN Expired {name}",
|
|
|
|
4034: "Alarm Acknowledged",
|
|
|
|
4035: "Door Locked-Scheduled",
|
|
|
|
4036: "Door Unlocked-Scheduled",
|
|
|
|
4041: "Door Forced Alarm",
|
|
|
|
4042: "Door Held Alarm",
|
|
|
|
4043: "Tamper Switch Alarm",
|
|
|
|
4044: "AC Failure",
|
|
|
|
4045: "Battery Failure",
|
|
|
|
4051: "REX Switch Alarm",
|
|
|
|
7020: f"Time Set to: {self.new_time}",
|
|
|
|
12031: f"Granted Access, {direction} Manual",
|
|
|
|
12032: "Door Unlocked",
|
|
|
|
12033: "Door Locked",
|
|
|
|
}
|
|
|
|
|
|
|
|
return event_types.get(self.event_type, f"Unknown Event Type {self.event_type}")
|
|
|
|
|
|
|
|
def __str__(self):
|
|
|
|
return f"{self.door_name} {self.timestamp} - {self.description}"
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
constraints = [
|
|
|
|
models.UniqueConstraint(
|
|
|
|
fields=["door_name", "timestamp", "event_type"], name="unique_hidevent"
|
|
|
|
)
|
|
|
|
]
|
|
|
|
managed = False
|
|
|
|
db_table = "hidevent"
|
|
|
|
ordering = ("-timestamp",)
|