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
This commit is contained in:
chris.watts90@outlook.com 2019-09-11 17:28:34 +01:00
parent e49111ebfc
commit 4c99dfba71
13 changed files with 240 additions and 56 deletions

View File

@ -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

View File

@ -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

View File

@ -0,0 +1,10 @@
using System;
namespace CardReaderService
{
public class CardDataPost
{
public DateTime UtcTimeStamp { get; set; }
public string CardUId { get; set; }
}
}

View File

@ -34,12 +34,12 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="PCSC, Version=4.2.0.0, Culture=neutral, PublicKeyToken=13b76e54a2ee80a7, processorArchitecture=MSIL">
<HintPath>..\packages\PCSC.3.6.0\lib\net40\pcsc-sharp.dll</HintPath>
<HintPath>..\packages\PCSC.4.2.0\lib\net40\PCSC.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
@ -54,6 +54,11 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="CardDataPost.cs" />
<Compile Include="CircularBuffer.cs" />
<Compile Include="ConfigurationManager.cs" />
<Compile Include="ConfigurationProperty.cs" />
<Compile Include="ConfigurationType.cs" />
<Compile Include="ConfigureService.cs" />
<Compile Include="DataCenterHelper.cs" />
<Compile Include="Service1.cs">

View File

@ -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;
}
}

View File

@ -0,0 +1,55 @@
namespace CardReaderService
{
/// <summary>
/// An object used to detail an element that can be configured in the system.
/// </summary>
public class ConfigurationProperty
{
/// <summary>
/// Unique Id for the configuration property.
/// </summary>
public string Id { get; set; }
/// <summary>
/// The display name of the configuration
/// </summary>
public string Name { get; set; }
/// <summary>
/// The group under which this configuration falls (e.g.: TCP Settings - "TCP" or similar.)
/// </summary>
/// <remarks>Application Specific grouping.</remarks>
public string Group { get; set; }
/// <summary>
/// The actual value of the Configuration property
/// </summary>
public string Value { get; set; }
/// <summary>
/// The source of the configuration properties.
/// </summary>
/// <remarks>
/// Using this property allows aggregation of configuration settings
/// by any configuration managers
/// </remarks>
/// <example>{TYPE}.getType().Name (or other suitably unique identifier)</example>
public string Source { get; set; }
/// <summary>
/// The type of the configuration
/// </summary>
/// <remarks>
/// 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)
/// </remarks>
public ConfigurationType Type { get; set; }
/// <summary>
/// Specifies whether the configuration setting can be set by user or is readonly
/// </summary>
public bool ReadOnly { get; set; }
//TODO: in future, add access level, could go read level/edit level
//public UserAccessLevel UserLevel {get;set;}
}
}

View File

@ -0,0 +1,33 @@
namespace CardReaderService
{
/// <summary>
/// The type of the configuration.
/// </summary>
public enum ConfigurationType
{
/// <summary>
/// No Type - shouldnt be used, but default for enum
/// </summary>
NONE,
/// <summary>
/// a string type configuration (could also be used for complex objects, e.g.: a json string/object).
/// </summary>
STRING,
/// <summary>
/// A whole number configuration
/// </summary>
INT,
/// <summary>
/// A number config with a decimal component
/// </summary>
DECIMAL,
/// <summary>
/// A Date Time Configuration
/// </summary>
DATETIME,
/// <summary>
/// A Boolean/TrueFalse configuration property (e.g.: On Off)
/// </summary>
BOOL
}
}

View File

@ -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; }
}
}

View File

@ -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);
@ -94,6 +97,8 @@ namespace CardReaderService
}
private void CardMonitor_CardInserted(object sender, CardStatusEventArgs e)
{
try
{
var ctxFac = ContextFactory.Instance;
using (var ctx = ctxFac.Establish(SCardScope.System))
@ -122,13 +127,13 @@ namespace CardReaderService
MessageLogger.Log("Card Inserted, ATR: " + atrString + ", and UID is: " + uid);
CardDataPost postObj = new CardDataPost { CardUId = uid, UtcTimeStamp = DateTime.UtcNow};
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);
MessageLogger.Log("Failed to Read UID, Error: " + err);
}
}
else
@ -137,6 +142,12 @@ namespace CardReaderService
}
}
}
catch (Exception ex)
{
MessageLogger.Log("Exception has occurred in Card Inserted Event handler. Exception: "+ ex);
throw;
}
}
private void MainWorkerThread()
{
@ -166,6 +177,7 @@ namespace CardReaderService
}
}
//dont actually need to do anything.. but cannot exit right away?
_mre.WaitOne(minimumLoopTimemS);
}
}

View File

@ -34,8 +34,8 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.10.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.12.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" />
@ -53,6 +53,18 @@
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="..\CardReaderService.conf">
<Link>CardReaderService.conf</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\install.sh">
<Link>install.sh</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="..\uninstall.sh">
<Link>uninstall.sh</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>

View File

@ -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));
}
}
}

View File

@ -1,12 +1,21 @@
#!/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

View File

@ -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