From 4c99dfba71d877d9cf5023ee6781d24fd15af202 Mon Sep 17 00:00:00 2001 From: "chris.watts90@outlook.com" Date: Wed, 11 Sep 2019 17:28:34 +0100 Subject: [PATCH] Fix install/uninstall files to use correct path for installation on rpi. Fix CardReaderService.conf for supervisorctl to ensure correct pathing as per install directories. Correct MessageLogger to ensure it appends log messages, previously overwrote the logs. Add manual Reset event in Service1.cs to ensure that we exit when we stop. Add configurationmanager/config property, to allow DataCenterHelper to pull updated configurations at runtime. Add TimeStamp to CardDataPost object #103 --- CardReaderService/CardReaderService.conf | 4 +- CardReaderService/CardReaderService.sln | 7 ++ .../CardReaderService/CardDataPost.cs | 10 +++ .../CardReaderService.csproj | 11 +++- .../CardReaderService/ConfigurationManager.cs | 38 +++++++++++ .../ConfigurationProperty.cs | 55 ++++++++++++++++ .../CardReaderService/ConfigurationType.cs | 33 ++++++++++ .../CardReaderService/DataCenterHelper.cs | 28 ++++---- .../CardReaderService/Service1.cs | 66 +++++++++++-------- .../CardReaderServiceHost.csproj | 16 ++++- CardReaderService/Logger/MessageLogger.cs | 2 +- CardReaderService/install.sh | 17 +++-- CardReaderService/uninstall.sh | 9 ++- 13 files changed, 240 insertions(+), 56 deletions(-) create mode 100644 CardReaderService/CardReaderService/CardDataPost.cs create mode 100644 CardReaderService/CardReaderService/ConfigurationManager.cs create mode 100644 CardReaderService/CardReaderService/ConfigurationProperty.cs create mode 100644 CardReaderService/CardReaderService/ConfigurationType.cs diff --git a/CardReaderService/CardReaderService.conf b/CardReaderService/CardReaderService.conf index 27f379d..802a6f4 100644 --- a/CardReaderService/CardReaderService.conf +++ b/CardReaderService/CardReaderService.conf @@ -1,5 +1,5 @@ [program:CardReaderService] command=mono-service CardReaderService.exe --no-daemon -directory=/home/osboxes/CardReaderService -stdout_logfile=/home/osboxes/CardReaderService/out.log +directory=/DIRECTORYTOSET/CardReaderService +stdout_logfile=/DIRECTORYTOSET/CardReaderService/out.log redirect_stderr=true diff --git a/CardReaderService/CardReaderService.sln b/CardReaderService/CardReaderService.sln index a0006e0..79a69b4 100644 --- a/CardReaderService/CardReaderService.sln +++ b/CardReaderService/CardReaderService.sln @@ -9,6 +9,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CardReaderServiceHost", "Ca EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Logger", "Logger\Logger.csproj", "{42EFE386-DC2E-455A-BA81-5FC9CEE45D02}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Linux Conf", "Linux Conf", "{F9053F37-761D-45EE-9153-46776B083DBA}" + ProjectSection(SolutionItems) = preProject + CardReaderService.conf = CardReaderService.conf + install.sh = install.sh + uninstall.sh = uninstall.sh + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU diff --git a/CardReaderService/CardReaderService/CardDataPost.cs b/CardReaderService/CardReaderService/CardDataPost.cs new file mode 100644 index 0000000..6dfce4c --- /dev/null +++ b/CardReaderService/CardReaderService/CardDataPost.cs @@ -0,0 +1,10 @@ +using System; + +namespace CardReaderService +{ + public class CardDataPost + { + public DateTime UtcTimeStamp { get; set; } + public string CardUId { get; set; } + } +} \ No newline at end of file diff --git a/CardReaderService/CardReaderService/CardReaderService.csproj b/CardReaderService/CardReaderService/CardReaderService.csproj index 371c472..8621c3d 100644 --- a/CardReaderService/CardReaderService/CardReaderService.csproj +++ b/CardReaderService/CardReaderService/CardReaderService.csproj @@ -34,12 +34,12 @@ 4 - - ..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll True - ..\packages\PCSC.3.6.0\lib\net40\pcsc-sharp.dll + ..\packages\PCSC.4.2.0\lib\net40\PCSC.dll True @@ -54,6 +54,11 @@ + + + + + diff --git a/CardReaderService/CardReaderService/ConfigurationManager.cs b/CardReaderService/CardReaderService/ConfigurationManager.cs new file mode 100644 index 0000000..6ce4afa --- /dev/null +++ b/CardReaderService/CardReaderService/ConfigurationManager.cs @@ -0,0 +1,38 @@ +using System; +using System.Configuration; +using System.Linq; +using System.Reflection; + +namespace CardReaderService +{ + public class ConfigurationManager + { + public ConfigurationProperty GetConfiguration(string configName) + { + var cfgManager = GetConfigManager(); + if (cfgManager.AppSettings.Settings.AllKeys.Contains(configName)) + { + var cfg = cfgManager.AppSettings.Settings[configName]; + return new ConfigurationProperty + { + Group=string.Empty, + Id="NOTIMPLEMENTED", + Name = cfg.Key, + Value = cfg.Value, + ReadOnly = false, + Source = "CardReaderService", + Type = ConfigurationType.STRING + }; + } + + return null; + } + + private Configuration GetConfigManager() + { + return System.Configuration.ConfigurationManager.OpenExeConfiguration(ConfigFilePath); + } + + public string ConfigFilePath => new Uri(Assembly.GetEntryAssembly().CodeBase).LocalPath; + } +} \ No newline at end of file diff --git a/CardReaderService/CardReaderService/ConfigurationProperty.cs b/CardReaderService/CardReaderService/ConfigurationProperty.cs new file mode 100644 index 0000000..653f0ab --- /dev/null +++ b/CardReaderService/CardReaderService/ConfigurationProperty.cs @@ -0,0 +1,55 @@ +namespace CardReaderService +{ + /// + /// An object used to detail an element that can be configured in the system. + /// + public class ConfigurationProperty + { + /// + /// Unique Id for the configuration property. + /// + public string Id { get; set; } + /// + /// The display name of the configuration + /// + public string Name { get; set; } + + /// + /// The group under which this configuration falls (e.g.: TCP Settings - "TCP" or similar.) + /// + /// Application Specific grouping. + public string Group { get; set; } + + /// + /// The actual value of the Configuration property + /// + public string Value { get; set; } + + /// + /// The source of the configuration properties. + /// + /// + /// Using this property allows aggregation of configuration settings + /// by any configuration managers + /// + /// {TYPE}.getType().Name (or other suitably unique identifier) + public string Source { get; set; } + + /// + /// The type of the configuration + /// + /// + /// This can be used for UI proofing/validation to ensure a user + /// enters expected format (e.g.: enters a date time for a datetime type) + /// + public ConfigurationType Type { get; set; } + + /// + /// Specifies whether the configuration setting can be set by user or is readonly + /// + public bool ReadOnly { get; set; } + + //TODO: in future, add access level, could go read level/edit level + //public UserAccessLevel UserLevel {get;set;} + } +} \ No newline at end of file diff --git a/CardReaderService/CardReaderService/ConfigurationType.cs b/CardReaderService/CardReaderService/ConfigurationType.cs new file mode 100644 index 0000000..0f82c40 --- /dev/null +++ b/CardReaderService/CardReaderService/ConfigurationType.cs @@ -0,0 +1,33 @@ +namespace CardReaderService +{ + /// + /// The type of the configuration. + /// + public enum ConfigurationType + { + /// + /// No Type - shouldnt be used, but default for enum + /// + NONE, + /// + /// a string type configuration (could also be used for complex objects, e.g.: a json string/object). + /// + STRING, + /// + /// A whole number configuration + /// + INT, + /// + /// A number config with a decimal component + /// + DECIMAL, + /// + /// A Date Time Configuration + /// + DATETIME, + /// + /// A Boolean/TrueFalse configuration property (e.g.: On Off) + /// + BOOL + } +} \ No newline at end of file diff --git a/CardReaderService/CardReaderService/DataCenterHelper.cs b/CardReaderService/CardReaderService/DataCenterHelper.cs index 3cfe5a1..9c42926 100644 --- a/CardReaderService/CardReaderService/DataCenterHelper.cs +++ b/CardReaderService/CardReaderService/DataCenterHelper.cs @@ -1,36 +1,40 @@ using System; -using System.Collections.Generic; -using System.Configuration; -using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; +using Logger; using Newtonsoft.Json; namespace CardReaderService { static class DataCenterHelper { + static DataCenterHelper() + { + } + public static void Post(CardDataPost postObject, string url) { - var endpointConfig = ConfigurationManager.AppSettings["DataCenterServiceEndpoint"] ?? - "http://localhost:8800"; + var cfgMgr = new ConfigurationManager(); + //using ConfigurationManager means we can change the value at runtime without having to restart the service. + var endpointConfig = cfgMgr.GetConfiguration("DataCenterServiceEndpoint")?.Value?? "http://localhost:8800"; + MessageLogger.Log("Targeting Endpoint: " + endpointConfig); using (var client = new HttpClient()) { var jsonObject = JsonConvert.SerializeObject(postObject); var content = new StringContent(jsonObject, Encoding.UTF8, "application/json"); try { - Console.WriteLine("Writing"); + MessageLogger.Log("Writing uid: "+ postObject.CardUId + " to the server."); var fullUrl = endpointConfig + url; + MessageLogger.Log("Writing to URL: " + fullUrl); var response = client.PostAsync(fullUrl, content).Result; - Console.WriteLine("Written"); + MessageLogger.Log("Successfully written to server"); } catch (Exception) { - Console.WriteLine("exceptioning"); - //ignore + MessageLogger.Log("Failed to send log to server."); } } } @@ -40,10 +44,4 @@ namespace CardReaderService return Task.Run(() => Post(postObject, url)); } } - - public class CardDataPost - { - public DateTime UtcTimeStamp { get; set; } - public string CardUId { get; set; } - } } diff --git a/CardReaderService/CardReaderService/Service1.cs b/CardReaderService/CardReaderService/Service1.cs index 1943312..c50d4dd 100644 --- a/CardReaderService/CardReaderService/Service1.cs +++ b/CardReaderService/CardReaderService/Service1.cs @@ -15,6 +15,7 @@ namespace CardReaderService { private Thread _mainWorkThread; private bool _stopMainWorkerThread; + private readonly ManualResetEvent _mre; private string _readerName = string.Empty; private SCardMonitor _cardMonitor; @@ -22,6 +23,7 @@ namespace CardReaderService public Service1() { InitializeComponent(); + _mre = new ManualResetEvent(false); } public void Start() @@ -64,6 +66,7 @@ namespace CardReaderService { MessageLogger.Log("Stopping.."); _stopMainWorkerThread = true; + _mre.Set(); if (_mainWorkThread != null && _mainWorkThread.IsAlive) { _mainWorkThread.Join(3000); @@ -95,46 +98,54 @@ namespace CardReaderService private void CardMonitor_CardInserted(object sender, CardStatusEventArgs e) { - var ctxFac = ContextFactory.Instance; - using (var ctx = ctxFac.Establish(SCardScope.System)) + try { - var reader = new SCardReader(ctx); - byte[] rcvBuffer = new byte[256]; - - if (_readerName == string.Empty) + var ctxFac = ContextFactory.Instance; + using (var ctx = ctxFac.Establish(SCardScope.System)) { - MessageLogger.Log("Reader name is somehow empty... WTF!"); - _stopMainWorkerThread = true; - return; - } + var reader = new SCardReader(ctx); + byte[] rcvBuffer = new byte[256]; - var err = reader.Connect(_readerName, SCardShareMode.Shared, SCardProtocol.Any); - if (err == SCardError.Success) - { - var pci = SCardPCI.GetPci(reader.ActiveProtocol); - - err = reader.Transmit(pci, CardCommands.GetUid, ref rcvBuffer); + if (_readerName == string.Empty) + { + MessageLogger.Log("Reader name is somehow empty... WTF!"); + _stopMainWorkerThread = true; + return; + } + var err = reader.Connect(_readerName, SCardShareMode.Shared, SCardProtocol.Any); if (err == SCardError.Success) { - var uid = ConvertByteUIDToString(rcvBuffer); - var atrString = ConvertByteUIDToString(e.Atr); + var pci = SCardPCI.GetPci(reader.ActiveProtocol); - MessageLogger.Log("Card Inserted, ATR: " + atrString + ", and UID is: " + uid); + err = reader.Transmit(pci, CardCommands.GetUid, ref rcvBuffer); - CardDataPost postObj = new CardDataPost { CardUId = uid, UtcTimeStamp = DateTime.UtcNow}; - DataCenterHelper.PostAsync(postObj, "/api/swipedata"); - MessageLogger.Log("Posted to Server"); + if (err == SCardError.Success) + { + var uid = ConvertByteUIDToString(rcvBuffer); + var atrString = ConvertByteUIDToString(e.Atr); + + MessageLogger.Log("Card Inserted, ATR: " + atrString + ", and UID is: " + uid); + + CardDataPost postObj = new CardDataPost { CardUId = uid, UtcTimeStamp = DateTime.UtcNow }; + DataCenterHelper.PostAsync(postObj, "/api/swipedata"); + MessageLogger.Log("Posted to Server"); + } + else + { + MessageLogger.Log("Failed to Read UID, Error: " + err); + } } else { - MessageLogger.Log("Failed to Read UID, Error: "+ err); + MessageLogger.Log("Reader failed to connect, error: " + Enum.GetName(typeof(SCardError), err)); } } - else - { - MessageLogger.Log("Reader failed to connect, error: " + Enum.GetName(typeof(SCardError), err)); - } + } + catch (Exception ex) + { + MessageLogger.Log("Exception has occurred in Card Inserted Event handler. Exception: "+ ex); + throw; } } @@ -166,6 +177,7 @@ namespace CardReaderService } } //dont actually need to do anything.. but cannot exit right away? + _mre.WaitOne(minimumLoopTimemS); } } diff --git a/CardReaderService/CardReaderServiceHost/CardReaderServiceHost.csproj b/CardReaderService/CardReaderServiceHost/CardReaderServiceHost.csproj index db0a5cd..61b73b5 100644 --- a/CardReaderService/CardReaderServiceHost/CardReaderServiceHost.csproj +++ b/CardReaderService/CardReaderServiceHost/CardReaderServiceHost.csproj @@ -34,8 +34,8 @@ 4 - - ..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll True @@ -53,6 +53,18 @@ + + CardReaderService.conf + PreserveNewest + + + install.sh + PreserveNewest + + + uninstall.sh + PreserveNewest + diff --git a/CardReaderService/Logger/MessageLogger.cs b/CardReaderService/Logger/MessageLogger.cs index e8aa791..a693525 100644 --- a/CardReaderService/Logger/MessageLogger.cs +++ b/CardReaderService/Logger/MessageLogger.cs @@ -14,7 +14,7 @@ namespace Logger public static void Log(string message) { Console.WriteLine(message); - System.IO.File.WriteAllText(_logPath, string.Format("{0} | {1}", DateTime.Now, message)); + File.AppendAllText(_logPath, string.Format("{0} | {1}{2}", DateTime.Now, message, Environment.NewLine)); } } } diff --git a/CardReaderService/install.sh b/CardReaderService/install.sh index 5a13335..a90cdb9 100644 --- a/CardReaderService/install.sh +++ b/CardReaderService/install.sh @@ -1,15 +1,24 @@ #!/bin/sh +if [ -z "$1" ] + then + echo "No arguments supplied, supply the base path" +fi echo "Installing dependencies" apt-get install mono-complete pcscd supervisor -y + +echo "Modifying supervisor conf file" +sed -i "s|/DIRECTORYTOSET|$1|g" CardReaderService.conf + echo "Installing service configuration file" cp CardReaderService.conf /etc/supervisor/conf.d/ + echo "Installing applicaton" -mkdir /home/osboxes/CardReaderService -cp CardReaderServiceHost/bin/Debug/*.* /home/osboxes/CardReaderService -cd /home/osboxes/CardReaderService +mkdir $1/CardReaderService +cp ./*.* $1/CardReaderService +cd $1/CardReaderService rm *.pdb rm *.vshost.exe rm *.vshost.exe.config rm *.vshost.exe.manifest echo "Starting application........." -service supervisor restart +service supervisor restart \ No newline at end of file diff --git a/CardReaderService/uninstall.sh b/CardReaderService/uninstall.sh index 5012336..5cb65ce 100644 --- a/CardReaderService/uninstall.sh +++ b/CardReaderService/uninstall.sh @@ -1,7 +1,12 @@ -echo "Stopping application...." +#!/bin/sh +if [ -z "$1" ] + then + echo "No arguments supplied, supply the base path" +fi +echo "Stopping service...." service supervisor stop rm -f /etc/supervisor/conf.d/CardReaderService.conf echo "Removing Application.." -rm -r -f /home/osboxes/CardReaderService +rm -r -f $1/CardReaderService echo "Removing application dependencies.." apt-get remove pcscd supervisor mono-complete -y