Paxton offers a product range including IP, wireless and battery powered access control solutions to provide reliable security for any site requirement.
We ordered one door access card reader & control unit, with it comes net2 software shipped, in wich you can manage users access cards (wich doors who can open and when, expiration date etc..)
I will use the access control for a gym, where members can open the front door with their personal (rfid) card, untill their membership expires.
There was no way to automatically re-activate the members card after they renewed their subscription online, but since the net2 software paxton develops has a net2 sdk available, I created a c# application that updates the user automatically.
In this case a simple console application would be enough, wich runs every 5 minutes, checking a directory for xml files.
If a member renews their subscription or a new member is created an xml is sent to the server where the application picks up the xml and updates / creates the user in the net2 database:
class Program
{
private const int REMOTE_PORT = 8025;
private const string REMOTE_HOST = "IPADDRESS NET2 SERVER";
private OemClient _net2Client = new OemClient(REMOTE_HOST, REMOTE_PORT);
private static string logFile = string.Format("log/log-{0}-{1}-{2}.txt", DateTime.Now.Day.ToString(), DateTime.Now.Month.ToString(), DateTime.Now.Year.ToString());
private string sourceDirectory = @"xml";
private string archiveDirectory = @"archive\";
private StreamWriter log = File.AppendText(logFile);
static void Main(string[] args)
{
Program main = new Program();
main.startUp();
}
//Check if there are xml files with user updates in the directory
public int startUp()
{
IEnumerable xmlFiles = Directory.EnumerateFiles(sourceDirectory, "*.xml");
if (xmlFiles.Count() <= 0)
{
Log("Nothing to do, shutting down..");
return 1;
}
bool res = AuthenticateUser("OEM Client", "password");
if(res != true)
{
Log("Authentication failed, exiting application");
return 1;
}
Log("Authentication success");
//Check for available xml files
loadAndParseXml(xmlFiles);
return 1;
}
private void loadAndParseXml(IEnumerable xmlFiles)
{
//Check if there are files
foreach (string file in xmlFiles)
{
Log(file);
string contents = File.ReadAllText(file);
if(parseXml(contents) == true)
{
string fileName = file.Substring(sourceDirectory.Length + 1);
File.Move(file, archiveDirectory + fileName);
}
}
}
private bool parseXml(string xmlstr)
{
Log("Parse XML");
XElement users = XElement.Parse(xmlstr);
Log(users.Name.ToString());
if(users.Name.ToString() == "update")
{
Log("This user needs an update");
updateUsers(users);
}
if(users.Name.ToString() == "create")
{
Log("This user needs an add");
addUsers(users);
}
return true;
}
private DateTime stringToDateTime(string date)
{
// Date strings are interpreted according to the current culture.
// If the culture is en-US, this is interpreted as "January 8, 2008",
// but if the user's computer is fr-FR, this is interpreted as "August 1, 2008"
DateTime dt = Convert.ToDateTime(date);
return dt;
}
/**
* Update existing users in Net2
* Field9_50 is Emailaddress (don't ask me why)
**/
private void updateUsers(XElement users)
{
var data = from item in users.Descendants("user")
select new
{
email = item.Element("emailaddress").Value,
expiration = item.Element("expirationdate").Value,
};
foreach (var p in data)
{
//IUser interface object is returned
IUsers userList = _net2Client.ViewUserRecords(String.Format("Field9_50 = '{0}' AND active=1", p.email));
if (userList.UsersList().Count - 1 > 1)
{
Log("Houston, we've got a problem, multiple users!! Abort Abort!");
Environment.Exit(0);
}
//Since there is always only one user, we can assume the only one in the list is the correct user
var user = userList.UsersList()[userList.UsersList().Keys.ElementAt(userList.UsersList().Count - 1)];
DateTime expDate;
expDate = stringToDateTime(p.expiration);
string[] customFields = new string[] { "" };
bool blnResult = false;
blnResult = _net2Client.UpdateUserRecord(user.UserId,
user.AccessLevelId,
user.DepartmentId,
user.AntiPassbackUser,
user.AlarmUser,
user.FirstName,
user.MiddleName,
user.Surname,
user.Telephone,
user.Extension,
user.PIN,
user.Picture,
user.ActivationDate,
user.Active,
user.Fax,
expDate,
customFields);
Log(string.Format("Update user Status: {0}, Name: {1}, ExpirationDate: {2}", blnResult, user.FirstName, expDate));
}
}
/**
* Authenticate user
* For some reason we can't authenticate with username password, only with userId Password..
* So we need to get the userId and Authenticate with it..
**/
private bool AuthenticateUser(string userName, string password)
{
IOperators operators = _net2Client.GetListOfOperators();
Dictionary<int, string> operatorsList = operators.UsersDictionary();
foreach (int userID in operatorsList.Keys)
{
if (operatorsList[userID] == userName)
{
Dictionary<string, int> methodList = _net2Client.AuthenticateUser(userID, password);
return (methodList != null);
}
}
return false;
}
private void Log(string logMessage)
{
Console.WriteLine(logMessage);
log.Write("\r\nLog Entry : ");
log.WriteLine("{0} {1} : {2}", DateTime.Now.ToShortDateString(),
DateTime.Now.ToLongDateString(), logMessage);
log.WriteLine("-------------------------------");
}
}
The xml files that are added in the xml directory look like this:
<update>
<user>
<email>[email protected]</email>
<expiration>10-08-2016</expiration>
</user>
</update>
After the file has been parsed it will be moved to the archive folder, for later reference or checking.