-
Notifications
You must be signed in to change notification settings - Fork 4
/
controlled_device.py
154 lines (130 loc) · 5.94 KB
/
controlled_device.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# Raspberry Pi-based RFID Access Control System
# Copyright (C) 2012 Oskar Pearson
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# System-Wide packages
import fileinput
import logging
import logging
import re
# Associated Packages
from quick2wire import gpio
###############################################################################
# Class - ControlledDevice
###############################################################################
# A 'Controlled Device' is some sort of hardware that we are responsible for
# access to. For example, it could be a door or a piece of machinery
class ControlledDevice:
name = 'NOT DEFINED'
# To enable a device, some hardware pins may need to have their pins set
# 'low', while on some other devices, the pins may need to be set 'high'.
#
# Similarly, on a device being 'disabled', the same is true.
#
pin_objects = {} # Objects that are used for interfacing with HW
enable_set_pins_low = []
enable_set_pins_high = []
disable_set_pins_low = []
disable_set_pins_high = []
# Access to a controlled device is based on the card presented,
# with a list of 'allowed cards' stored in a configuration file. The exact
# filename used is supplied in the config file
acl_filename = None
# The 'authorised cards' are read into this in-memory array. Since the
# use-case for the rpac system is less than 1000 cards, we read this
# into memory
authorised_cards = []
# This device is instantiated and configured based on a config file. The
# object is passed a 'configparser' fragment, and needs to set the
# appropriate parameters
def __init__(self, config, acl_path):
"""Device Constructor"""
self.acl_path = acl_path
# Process configuration file fragment
for o, a in config:
if o == 'enable set pins low':
self.enable_set_pins_low = self.parse_pin_parameters(a)
elif o == 'enable set pins high':
self.enable_set_pins_high = self.parse_pin_parameters(a)
elif o == 'disable set pins low':
self.disable_set_pins_low = self.parse_pin_parameters(a)
elif o == 'disable set pins high':
self.disable_set_pins_high = self.parse_pin_parameters(a)
elif o == 'acl filename':
self.acl_filename = a
else:
assert False, "Unsupported parameter '%s' for Device" % o
# Check that everything makes sense in the supplied config
# file, so that if someone leaves out a critical parameter or
# similar, we raise an appropriate error
if not ( \
len(self.enable_set_pins_low) > 0 \
or len(self.enable_set_pins_high) > 0 \
or len(self.disable_set_pins_low) > 0 \
or len(self.disable_set_pins_high) > 0 \
):
assert False, "%s - None of the following set: " \
"enable_set_pins_low, " \
"enable_set_pins_high, " \
"disable_set_pins_low, " \
"disable_set_pins_high " % self.name
if not self.acl_filename:
assert False, "ACL filename not set"
# The pins originally specified in the config file are text, and need
# to be converted to numerics. There can also be more than one per
# config file line, so clean things up and store them in an array
def parse_pin_parameters(self, pins_as_text):
if re.search('[^0-9\ ]+', pins_as_text):
assert False, "Pins parameters supplied is not all-numeric," \
+ " separated by spaces (is '%s')" % pins_as_text
pins = []
for pin_number_as_text in pins_as_text.split():
pin_number = int(pin_number_as_text)
pins.append(pin_number)
# Create a communication object
if pin_number not in self.pin_objects:
pin = gpio.pins.pin(pin_number)
pin.open()
pin.direction = gpio.Out
self.pin_objects[pin_number] = pin
return pins
def check_for_card_in_db(self, card):
logging.info("Card presented to device %s" % self.name)
logging.info("Card id %s" % card)
self._load_card_db()
if card in self.authorised_cards:
logging.info("Card IS authorised");
return self.enable()
else:
logging.info("Card is NOT authorised");
return self.disable()
# STATE CHANGES: enable or disable this device
def enable(self):
self._set_pins(0, self.enable_set_pins_low)
self._set_pins(1, self.enable_set_pins_high)
return True
def disable(self):
self._set_pins(0, self.disable_set_pins_low)
self._set_pins(1, self.disable_set_pins_high)
return False
# Set associated pins low or high
def _set_pins(self, state, pin_list):
for pin_number in pin_list:
self.pin_objects[pin_number].value = state
# Read the card database, and build a list of authorised cards
def _load_card_db(self):
acl_full_path = self.acl_path + '/' + self.acl_filename
self.authorised_cards = []
for line in fileinput.input(acl_full_path):
self.authorised_cards.append(line.rstrip())