#!/usr/bin/env python3 import sys import requests import csv from collections import OrderedDict from io import StringIO from hashlib import md5 import os from common import * from hid.DoorController import fieldnames def makeMember(member, doorAuth): """Create an output CSV row for the member""" if member["Access Card Number"] == "": #print(member["First Name"], member["Last Name"], " has no card number, ignoring") return out = {"Forename": member["First Name"], "Surname": member["Last Name"], "Initial": "", "CardNumber": member["Access Card Number"], "CardFormat": "A901146A-" + member["Access Card Facility Code"], "PinRequired": "0", "ExtendedAccess": "0", "ExpiryDate": "", "Email": member["Email"], "Phone": member["Phone"]} if member[doorAuth] == "Y" \ and not member["Account on Hold"] == "Account on Hold": levels = OrderedDict(sorted([(k, v) for k, v in memberLevels.items() if member[k] == k])) out["Custom1"] = "|".join(levels.keys()).replace("&", "and") for index, schedule in enumerate(levels.values(), 1): #TODO: error if people have more than 8? out["Schedule" + str(index)] = schedule return out def makeDoor(door, members, hashes): """Create a CSV for the given door""" outString = StringIO() writer = csv.DictWriter(outString, fieldnames) writer.writeheader() for member in members: member = makeMember(member, "Access " + door.access + "?") if member is not None: writer.writerow(member) import datetime as DT timestamp = DT.datetime.now().strftime("%Y-%m-%d %H:%M:%S") with open("/tmp/" + door.name + timestamp + ".csv", "w") as f: f.write(outString.getvalue()) outString.seek(0) doorHash = md5(bytes(outString.getvalue(), 'utf8')).hexdigest() if doorHash == hashes.get(door.name): print("Door", door.name, "not changed, not updating") else: print("Door", door.name, "changed, trying to update") hashes[door.name] = doorHash try: door.doCSVImport(outString) except (requests.ReadTimeout, requests.ConnectionError): print(f"Import failed on door {door.name}, trying to power cycle it") cycleDoor(door) # write out hash if we sucessfully updated this door with open('/tmp/doorUpdaterLastHash', 'w') as f: json.dump(hashes, f) def cycleDoor(door): if door.mac is None: print(f"Cannot power cycle to door {door.name}, no mac address defined") return doorControllerClient = unifiController.get_client(door.mac) print(doorControllerClient) unifiController._api_write( 'cmd/devmgr', {"cmd": "power-cycle", "mac": doorControllerClient["sw_mac"], "port_idx": doorControllerClient["sw_port"]}) def main(): members = getMembershipworksData( ['members', 'staff', 'misc'], "lvl,xws,xms,xsc,xas,xfd,xac,phn,eml,lbl,xcf,nam") members.sort(key=lambda x: x['Last Name']) if os.path.exists('/tmp/doorUpdaterLastHash'): with open('/tmp/doorUpdaterLastHash', 'r') as f: hashes = json.load(f) else: hashes = {} for door in doors.values(): print(door.name, door.ip) makeDoor(door, members, hashes) if __name__ == '__main__': main()