-
Notifications
You must be signed in to change notification settings - Fork 0
/
flectra-attender.py
180 lines (166 loc) · 7.55 KB
/
flectra-attender.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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#/usr/bin/python
import signal
import sys, getopt, copy
import time, logging
from io import StringIO
import json
from flectraclient_rpc import FlectraClient
from shutil import copyfile
from wifiscanner import WifiScanner,WifiScannerCrash
def loadconfig(scanner, cfg, config_file):
global DEBUG
data = {}
scanner.sendCmd("stopscan",ack=True)
logging.info("reading config.json")
cfgsave = copy.deepcopy(cfg)
flag_config_changed = False
try:
for i in cfg["user"]:
time.sleep(0.1)
scanner.clearRxBuffer()
try:
b = cfg["user"][i]["password"]
except:
if len(cfg["user"][i]["password-encrypted"].strip()) % 4 != 0:
logging.warning("%s: encrypted password is not base64, removing user: %s"%(i,cfg["user"][i]["username"]))
cfg["user"][i]["active"] = False
continue
scanner.sendCmd("decrypt",[cfg["user"][i]["password-encrypted"]])
try:
cfg["user"][i]["password"] = scanner.read()
cfg["user"][i]["active"] = True
logging.debug("%s: %s"%(i,cfg["user"][i]["password"]))
except (UnicodeDecodeError):
logging.warning("%s: could not decrypt password, removing user: %s"%(i,cfg["user"][i]["username"]))
cfg["user"][i]["active"] = False
try:
b = cfg["user"][i]["password-encrypted"]
except:
scanner.sendCmd("encrypt",[cfg["user"][i]["password"]])
cfg["user"][i]["password-encrypted"] = scanner.read()
cfg["user"][i]["active"] = True
logging.debug("%s: %s"%(i,cfg["user"][i]["password-encrypted"]))
cfgsave["user"][i]["password-encrypted"] = cfg["user"][i]["password-encrypted"]
del(cfgsave["user"][i]["password"])
flag_config_changed = True
except (SystemExit):
logging.info("exiting")
scanner.sendCmd("stopscan",ack=True)
scanner.close()
sys.exit(0)
scanner.clearRxBuffer()
logging.debug(cfg["user"])
#do we have a a changed configuration?
if (flag_config_changed):
#copy config file before replaceing it
if (DEBUG):
print("coping config.json -> config.json-backup")
copyfile('config.json', 'config.json-backup')
#create formatted json from cfgsave
formattedconfig = json.dumps(cfgsave,indent=4, separators=(',', ': '))
#write it to config.json
print("new passwords found, saving configuration")
file = open(config_file,"w")
file.write(formattedconfig)
file.close
return data
def scan(scanner, cfg, data):
lasttimestamp = time.time()
#tell device to start sending data
#handle shutdown
logging.info("starting wifi-scanner")
scanner.sendCmd("startscan",ack=True)
logging.info("now scanning....")
while True:
try:
line = scanner.read()
if len(line) == 0:
time.sleep(0.2)
continue
#logging.info(line)
try:
obj = json.loads(line)
#do we have a known mac-address?
if (obj["m"] in cfg["user"] and cfg["user"][obj["m"]]["active"]):
#check if we have the record in memory, if not create it
try:
mydata = data[obj['m']]
except:
scanner.sendCmd("checkin",ack=True)
data[obj['m']] = {'firsttimestamp' : time.time(),'lasttimestamp' : time.time(), "cfg" : cfg["user"][obj['m']]}
mydata = data[obj['m']]
#checkin flectra
logging.info("%s: checkin user %s, checkouttimer: %i sec"%(obj['m'], data[obj['m']]["cfg"]["username"], data[obj['m']]["cfg"]["checkout-trigger-seconds"]))
try:
flc = FlectraClient(data[obj['m']]["cfg"]["username"], data[obj['m']]["cfg"]["password"])
res = flc.attendance_checkin()
except:
logging.warning("Warning: unable to checkin!")
data[obj['m']]["lasttimestamp"] = time.time()
obj['time'] = time.asctime( time.localtime(time.time()) )
logging.debug(data[obj['m']])
else:
#print("ignored mac %s"%(obj['m']))
pass
except json.decoder.JSONDecodeError:
logging.warning("jsonerrror: %s"%(line))
pass
except:
raise
for i in data.copy():
#user expired?
if (time.time()-data[i]['lasttimestamp'] > data[i]["cfg"]["checkout-trigger-seconds"]):
scanner.sendCmd("checkout",ack=True)
logging.info("%s: checkout user %s, checkouttimer %i sec, checkin was %i sec ago"%(i, data[i]["cfg"]["username"],data[i]["cfg"]["checkout-trigger-seconds"],int(time.time()-data[i]['firsttimestamp'])))
try:
#checkout flectra
flc = FlectraClient(data[i]["cfg"]["username"], data[i]["cfg"]["password"])
res = flc.attendance_checkout()
except:
logging.warning("Warning: unable to checkout!")
logging.debug(data[i])
del data[i]
else:
if (data[i].get("lastlogged",data[i]["lasttimestamp"]) != data[i]["lasttimestamp"]):
logging.info("%s: user %s checked in already: %i sec, checkouttimer %i sec, checkin was %i sec ago"%(i, data[i]["cfg"]["username"],int(time.time()-data[i]['lastlogged']),data[i]["cfg"]["checkout-trigger-seconds"],int(time.time()-data[i]['firsttimestamp'])))
data[i]["lastlogged"] = data[i]["lasttimestamp"]
time.sleep(0.02)
except (SystemExit):
logging.info("exiting")
scanner.sendCmd("stopscan",ack=True)
scanner.close()
sys.exit(0)
DEBUG = False
def main(argv):
global DEBUG
config_file = 'config.json'
try:
opts, args = getopt.getopt(argv,"hdc:",["debug","config="])
except getopt.GetoptError:
print('flectra-attender.py -d -c <filename>')
sys.exit(2)
for opt, arg in opts:
if opt == '-h':
print('flectra-attender.py -d -c <filename>')
print(' -d Enable debug output. Also a backup of the configuration will be made before overwriting.')
print(' -c <filename> Alternative configuration file. default: "config.json"')
sys.exit()
elif opt in ("-d", "--debug"):
DEBUG = True
elif opt in ("-c", "--config"):
config_file = arg
if DEBUG:
logging.basicConfig(format='%(asctime)s %(levelname)-2s %(message)s',
level=logging.DEBUG,
datefmt='%Y-%m-%d %H:%M:%S')
else:
logging.basicConfig(format='%(asctime)s %(levelname)-2s %(message)s',
level=logging.INFO,
datefmt='%Y-%m-%d %H:%M:%S')
with open(config_file) as json_data_file:
cfg = json.load(json_data_file)
scanner = WifiScanner(cfg["serial"])
data = loadconfig(scanner, cfg, config_file)
scan(scanner, cfg, data)
if __name__ == "__main__":
main(sys.argv[1:])