from django.http import HttpResponse, HttpResponseRedirect
from django.template import RequestContext
from django.shortcuts import render_to_response
import rfid_lock_management.models
from datetime import datetime
from django.utils import simplejson
from django.contrib.auth.decorators import login_required
from rfid_lock_management.misc_helpers import get_arg_default
from rfid_lock_management.models import *
[docs]def do_json_resp(success, message):
response_data = {
'success': success,
'error_mess': message}
return HttpResponse(simplejson.dumps(response_data),
content_type="application/json")
@login_required
[docs]def chartify(request):
"""
Return data in appropriate format for the HighCharts (JavaScript)
AccessTime plot. Creates a series for each door.
"""
tooltip_dict = {}
tooltip_dict['followPointer'] = 'false'
tooltip_dict['pointFormat'] = '"{point.user}"'
all_series = []
for door in Door.objects.all():
one_series = {}
one_series['name'] = '"%s"' % door.name
one_series['tooltip'] = tooltip_dict
this_door_access_times = AccessTime.objects.filter(door=door)
one_series['data'] = []
for at in this_door_access_times:
one_series['data'].append(simplejson.loads(at.data_point))
all_series.append(one_series)
extra_context = {'chart_data': simplejson.dumps(all_series, indent="")}
return render_to_response('chart.html', dictionary=extra_context,
context_instance=RequestContext(request))
[docs]def get_allowed_rfids(request, doorid):
"""
Returns list of allowed rfid's for the specified door in JSON format
"""
try:
door = Door.objects.get(pk=doorid)
allowed_rfids = door.get_allowed_rfids() # list of Keycard objects
alloweds = [keycard_obj.the_rfid for keycard_obj in allowed_rfids]
except: # door may not exist or any other error . . .
alloweds = "" # but still need to respond
to_json = {"doorid": int(doorid), "allowed_rfids": alloweds}
return HttpResponse(simplejson.dumps(to_json), content_type='application/json')
[docs]def check(request, doorid, rfid):
"""
In addition to checking whether the given rfid is valid for the given door,
this checks whether we're actually trying to assign a new keycard rather
than authenticating. If not doing a new keycard scan, create and save an
AccessTime.
"""
response = 0
# Is the request actually for new keycard assignment?
new_scan_queryset = NewKeycardScan.objects.all()
if new_scan_queryset:
# Note - getting latest NewKeycardScan object by ordering by the field
# time_initiated may not actually return the latest created object if
# 'start scan' was hit many times in a row -- even microseconds don't
# seem to have sufficient resolution to actually get the latest object.
# get the latest NewKeycardScan object
new_scan = new_scan_queryset.latest("pk")
# Issue #e
if new_scan.waiting_for_scan:
# record the door the new scan request came from
new_scan.doorid = doorid
new_scan.rfid = rfid
new_scan.save()
return HttpResponse(response)
# Or is the request actually for authenticating an existing keycard for
# this door? Note -- RFIDkeycard.objects.get(the_rfid=rfid) fails if there
# is more than one item returned. Only one item would be active.
# Issue #i
rfidkeycards_with_same_rfid = RFIDkeycard.objects.filter(the_rfid=rfid)
if not rfidkeycards_with_same_rfid:
# no such keycard, so return response of 0
return HttpResponse(0)
else:
for rfidkeycard in rfidkeycards_with_same_rfid:
# Keycard exists, so moving on to check if it's active and get
# allowed doors (the latter is called on lockuser, so need to check
# if keycard is active first).
if rfidkeycard.is_active():
for door in rfidkeycard.get_allowed_doors():
if door.id == int(doorid):
# So response will be 1 -- authenticated.
response = 1
######################################################
# create the AccessTime for this visit
######################################################
lockuser = rfidkeycard.lockuser
at = AccessTime(
the_rfid=rfid,
door=door,
lockuser=lockuser,
access_time=datetime.datetime.now()
)
# Now create and assign data point dict to JSONify for
# the access times highchart
x_coord = 'Date.UTC(%d,%d,%d)' % (
at.access_time.year, at.access_time.month-1,
at.access_time.day)
y_coord = 'Date.UTC(0,0,0, %d,%d,%d)' % (
at.access_time.hour, at.access_time.minute,
at.access_time.second)
user_name = '"%s %s"' % (
at.lockuser.first_name, at.lockuser.last_name)
data_point_dict = {
'x': x_coord, 'y': y_coord, 'user': user_name}
at.data_point = simplejson.dumps(data_point_dict)
at.save()
return HttpResponse(response)
@login_required
# Issue #k
[docs]def initiate_new_keycard_scan(request, lockuser_object_id):
"""
Try start waiting for new keycard scan; return success/fail message.
"""
# If this lockuser already has a current keycard, don't proceed
# (This should have been prevented at template level also)
try:
lu = LockUser.objects.get(id=lockuser_object_id)
except:
# Probably the error is DoesNotExist: LockUser matching query does not
# exist, but send this response on ANY type of exception.
return do_json_resp(False, "This lock user was probably not found in the system.")
if lu.get_current_rfid():
return do_json_resp(False, "This lock user is already assigned a keycard.")
else:
n = NewKeycardScan()
n.waiting_for_scan = True
n.assigner_user = request.user
n.save()
response_data = {'success': True, 'new_scan_pk': n.pk}
# not do_json_resp, since response_data is different:
return HttpResponse(simplejson.dumps(response_data),
content_type="application/json")
# TODO: raise exceptions.
@login_required
[docs]def finished_new_keycard_scan(request, new_scan_pk):
"""
Verify this is the NewKeycardScan object we initiated, that the rfid is not
the same as that of a currently active keycard, and that we haven't timed
out. Then get the rfid from the newly-scanned card.
The new RFIDkeycard object is created upon LockUser save, after change_form
form has been submitted.
"""
# Verify that the scan object is the one we need - that we have the
# NewKeycardScan object we started with, not one that another staff
# user initiated *after* us, for ex.
new_scan_qs = NewKeycardScan.objects.filter(pk=new_scan_pk)
if not new_scan_qs:
return do_json_resp(False,
"No NewKeycardScan obj with pk {}.".format(new_scan_pk))
new_scan = new_scan_qs[0]
min_till_timeout = 2.0
timed_out = new_scan.timed_out(min_till_timeout)
if timed_out:
return do_json_resp(False,
"Sorry, the system timed out. You have {} minutes to scan the card, then hit 'Done.' ".format(min_till_timeout))
if not new_scan.rfid:
return do_json_resp(False, "NewKeycardScan does not have RFID.")
# Verify that the rfid is not the same as that of another ACTIVE keycard
keycards_with_same_rfid_qs = RFIDkeycard.objects.filter(the_rfid=new_scan.rfid)
for k in keycards_with_same_rfid_qs.select_related():
if k.is_active():
# todo: include link to this lockuser
return do_json_resp(False,
"A keycard with the same RFID is already assigned to {}.".format(k.lockuser))
# OK, so far so good. Set waiting and ready-to-assign status,
# grab the assigner, and save NewKeycardScan object.
new_scan.waiting_for_scan = False
new_scan.ready_to_assign = True
new_scan.assigner_user = request.user # todo: assigner_user already set in initiate
new_scan.save()
response_data = {'success': True, 'rfid': new_scan.rfid}
# not do_json_resp, since response_data is different:
return HttpResponse(simplejson.dumps(response_data), content_type="application/json")