diff --git a/Action/Rs232Command.cs b/Action/Rs232Command.cs
index 12db207c..85d24add 100644
--- a/Action/Rs232Command.cs
+++ b/Action/Rs232Command.cs
@@ -12,7 +12,8 @@ public class Rs232Command
private Command _command;
private SerialPort _port;
- private string _toSend;
+ private string _toSend = null;
+ private bool _useHex = false;
public Rs232Command(Command command)
{
@@ -39,7 +40,15 @@ public string Run()
try
{
// Write our data stream
- _port.Write(_toSend);
+ if (_useHex)
+ {
+ byte[] bytes = _toSend.Split(' ').Select(s => Convert.ToByte(s, 16)).ToArray();
+ _port.Write(bytes, 0, bytes.Length);
+ }
+ else
+ {
+ _port.Write(_toSend);
+ }
// Read
if (_command.notifyStatus())
@@ -86,6 +95,9 @@ private void parse()
// Get the actual command to send
_toSend = command[2];
+
+ // Do we have a HEX bit?
+ _useHex = (connection.Length >= 7 && connection[6] == "1");
}
}
}
diff --git a/Action/XmrSubscriber.cs b/Action/XmrSubscriber.cs
index d3c99886..dc766611 100644
--- a/Action/XmrSubscriber.cs
+++ b/Action/XmrSubscriber.cs
@@ -19,6 +19,7 @@ class XmrSubscriber
// Members to stop the thread
private bool _forceStop = false;
+ private ManualResetEvent _manualReset = new ManualResetEvent(false);
///
/// Last Heartbeat packet received
@@ -53,132 +54,259 @@ public ClientInfo ClientInfoForm
}
private ClientInfo _clientInfoForm;
+ ///
+ /// The MQ Poller
+ ///
+ private NetMQPoller _poller;
+
+ ///
+ /// The Init Address
+ ///
+ private string _address;
+
///
/// Runs the agent
///
public void Run()
{
- try
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Thread Started"), LogType.Info.ToString());
+
+ while (!_forceStop)
{
- // Check we have an address to connect to.
- if (string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress))
- throw new Exception("Empty XMR Network Address");
+ lock (_locker)
+ {
+ try
+ {
+ // If we are restarting, reset
+ _manualReset.Reset();
- // Get the Private Key
- AsymmetricCipherKeyPair rsaKey = _hardwareKey.getXmrKey();
+ // Check we have an address to connect to.
+ if (string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress))
+ throw new Exception("Empty XMR Network Address");
- // Connect to XMR
- using (SubscriberSocket socket = new SubscriberSocket())
- {
- // Bind
- socket.Connect(ApplicationSettings.Default.XmrNetworkAddress);
- socket.Subscribe("H");
- socket.Subscribe(_hardwareKey.Channel);
+ // Cache the address for this socket (the setting may change outside).
+ _address = ApplicationSettings.Default.XmrNetworkAddress;
- // Notify
- _clientInfoForm.XmrSubscriberStatus = "Connected to " + ApplicationSettings.Default.XmrNetworkAddress;
+ // Get the Private Key
+ AsymmetricCipherKeyPair rsaKey = _hardwareKey.getXmrKey();
- while (!_forceStop)
- {
- lock (_locker)
+ // Connect to XMR
+ try
{
- try
+ // Create a Poller
+ _poller = new NetMQPoller();
+
+ // Create a Socket
+ using (SubscriberSocket socket = new SubscriberSocket())
{
- NetMQMessage message = socket.ReceiveMultipartMessage();
+ // Options
+ socket.Options.ReconnectInterval = TimeSpan.FromSeconds(5);
+ socket.Options.Linger = TimeSpan.FromSeconds(0);
+
+ // Bind
+ socket.Connect(ApplicationSettings.Default.XmrNetworkAddress);
+ socket.Subscribe("H");
+ socket.Subscribe(_hardwareKey.Channel);
+
+ // Add Socket to Poller
+ _poller.Add(socket);
+
+ // Bind to the receive ready event
+ socket.ReceiveReady += _socket_ReceiveReady;
+
+ // Notify
+ _clientInfoForm.XmrSubscriberStatus = "Connected to " + ApplicationSettings.Default.XmrNetworkAddress + ". Waiting for messages.";
+
+ // Sit and wait, processing messages, indefinitely or until we are interrupted.
+ _poller.Run();
+ }
+ }
+ finally
+ {
+ _poller.Dispose();
+ }
+
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Socket Disconnected, waiting to reconnect."), LogType.Info.ToString());
+ }
+ catch (TerminatingException terminatingEx)
+ {
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "NetMQ terminating: " + terminatingEx.Message), LogType.Audit.ToString());
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unable to Subscribe: " + e.Message), LogType.Info.ToString());
+ _clientInfoForm.XmrSubscriberStatus = e.Message;
+ }
+
+ // Update status
+ _clientInfoForm.XmrSubscriberStatus = "Disconnected, waiting to reconnect, last activity: " + LastHeartBeat.ToString();
+
+ // Sleep for 60 seconds.
+ _manualReset.WaitOne(60 * 1000);
+ }
+ }
+
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Subscriber Stopped"), LogType.Info.ToString());
+ }
+
+ ///
+ /// Receive event
+ ///
+ ///
+ ///
+ private void _socket_ReceiveReady(object sender, NetMQSocketEventArgs e)
+ {
+ try
+ {
+ processMessage(e.Socket.ReceiveMultipartMessage(), _hardwareKey.getXmrKey());
+ }
+ catch (NetMQException netMQException)
+ {
+ throw netMQException;
+ }
+ catch (Exception ex)
+ {
+ // Log this message, but dont abort the thread
+ Trace.WriteLine(new LogMessage("XmrSubscriber - _socket_ReceiveReady", "Exception in Run: " + ex.Message), LogType.Error.ToString());
+ Trace.WriteLine(new LogMessage("XmrSubscriber - _socket_ReceiveReady", e.ToString()), LogType.Audit.ToString());
+ _clientInfoForm.XmrSubscriberStatus = "Error. " + ex.Message;
+ }
+ }
- // Update status
- string statusMessage = "Connected (" + ApplicationSettings.Default.XmrNetworkAddress + "), last activity: " + DateTime.Now.ToString();
+ ///
+ /// Wait for a Message
+ ///
+ private void processMessage(NetMQMessage message, AsymmetricCipherKeyPair rsaKey)
+ {
+ // Update status
+ string statusMessage = "Connected (" + ApplicationSettings.Default.XmrNetworkAddress + "), last activity: " + DateTime.Now.ToString();
- // Write this out to a log
- _clientInfoForm.XmrSubscriberStatus = statusMessage;
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", statusMessage), LogType.Audit.ToString());
+ // Write this out to a log
+ _clientInfoForm.XmrSubscriberStatus = statusMessage;
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", statusMessage), LogType.Audit.ToString());
- // Deal with heart beat
- if (message[0].ConvertToString() == "H")
- {
- LastHeartBeat = DateTime.Now;
- continue;
- }
+ // Deal with heart beat
+ if (message[0].ConvertToString() == "H")
+ {
+ LastHeartBeat = DateTime.Now;
+ return;
+ }
- // Decrypt the message
- string opened = OpenSslInterop.decrypt(message[2].ConvertToString(), message[1].ConvertToString(), rsaKey.Private);
+ // Decrypt the message
+ string opened;
+ try
+ {
+ opened = OpenSslInterop.decrypt(message[2].ConvertToString(), message[1].ConvertToString(), rsaKey.Private);
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("XmrSubscriber - processMessage", "Unopenable Message: " + e.Message), LogType.Error.ToString());
+ Trace.WriteLine(new LogMessage("XmrSubscriber - processMessage", e.ToString()), LogType.Audit.ToString());
+ return;
+ }
- // Decode into a JSON string
- PlayerAction action = JsonConvert.DeserializeObject(opened);
+ // Decode into a JSON string
+ PlayerAction action = JsonConvert.DeserializeObject(opened);
- // Make sure the TTL hasn't expired
- if (DateTime.Now > action.createdDt.AddSeconds(action.ttl))
- {
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Expired Message: " + action.action), LogType.Info.ToString());
- continue;
- }
+ // Make sure the TTL hasn't expired
+ if (DateTime.Now > action.createdDt.AddSeconds(action.ttl))
+ {
+ Trace.WriteLine(new LogMessage("XmrSubscriber - processMessage", "Expired Message: " + action.action), LogType.Info.ToString());
+ return;
+ }
- // Decide what to do with the message, probably raise events according to the type of message we have
- switch (action.action)
- {
- case "commandAction":
+ // Decide what to do with the message, probably raise events according to the type of message we have
+ switch (action.action)
+ {
+ case "commandAction":
- // Create a schedule command out of the message
- Dictionary obj = JsonConvert.DeserializeObject>(opened);
- ScheduleCommand command = new ScheduleCommand();
- string code;
- obj.TryGetValue("commandCode", out code);
- command.Code = code;
+ // Create a schedule command out of the message
+ Dictionary obj = JsonConvert.DeserializeObject>(opened);
+ ScheduleCommand command = new ScheduleCommand();
+ string code;
+ obj.TryGetValue("commandCode", out code);
+ command.Code = code;
- new Thread(new ThreadStart(command.Run)).Start();
- break;
+ new Thread(new ThreadStart(command.Run)).Start();
+ break;
- case "collectNow":
- case RevertToSchedulePlayerAction.Name:
- if (OnAction != null)
- OnAction(action);
- break;
+ case "collectNow":
+ case RevertToSchedulePlayerAction.Name:
+ if (OnAction != null)
+ OnAction(action);
+ break;
- case LayoutChangePlayerAction.Name:
+ case LayoutChangePlayerAction.Name:
- LayoutChangePlayerAction changeLayout = JsonConvert.DeserializeObject(opened);
+ LayoutChangePlayerAction changeLayout = JsonConvert.DeserializeObject(opened);
- if (OnAction != null)
- OnAction(changeLayout);
+ if (OnAction != null)
+ OnAction(changeLayout);
- break;
+ break;
- case OverlayLayoutPlayerAction.Name:
- OverlayLayoutPlayerAction overlayLayout = JsonConvert.DeserializeObject(opened);
+ case OverlayLayoutPlayerAction.Name:
+ OverlayLayoutPlayerAction overlayLayout = JsonConvert.DeserializeObject(opened);
- if (OnAction != null)
- OnAction(overlayLayout);
- break;
+ if (OnAction != null)
+ OnAction(overlayLayout);
+ break;
- case "screenShot":
- ScreenShot.TakeAndSend();
- _clientInfoForm.notifyStatusToXmds();
- break;
+ case "screenShot":
+ ScreenShot.TakeAndSend();
+ _clientInfoForm.notifyStatusToXmds();
+ break;
- default:
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unknown Message: " + action.action), LogType.Info.ToString());
- break;
- }
- }
- catch (Exception ex)
- {
- // Log this message, but dont abort the thread
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString());
- _clientInfoForm.XmrSubscriberStatus = "Error. " + ex.Message;
- }
- }
- }
+ default:
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unknown Message: " + action.action), LogType.Info.ToString());
+ break;
+ }
+ }
+
+ ///
+ /// Wake Up
+ ///
+ public void Restart()
+ {
+ try
+ {
+ // Stop the poller
+ if (_poller != null)
+ {
+ _poller.Stop();
+ }
+
+ // Wakeup
+ _manualReset.Set();
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Restart", "Unable to Restart XMR: " + e.Message), LogType.Info.ToString());
+ }
+ }
+
+ ///
+ /// Stop the agent
+ ///
+ public void Stop()
+ {
+ try
+ {
+ // Stop the poller
+ if (_poller != null)
+ {
+ _poller.Stop();
}
- // Update status
- _clientInfoForm.XmrSubscriberStatus = "Not Running, last activity: " + LastHeartBeat.ToString();
+ // Stop the thread at the next loop
+ _forceStop = true;
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Subscriber Stopped"), LogType.Info.ToString());
+ // Wakeup
+ _manualReset.Set();
}
catch (Exception e)
{
- Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unable to Subscribe to XMR: " + e.Message), LogType.Info.ToString());
- _clientInfoForm.XmrSubscriberStatus = e.Message;
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Stop", "Unable to Stop XMR: " + e.Message), LogType.Info.ToString());
}
}
}
diff --git a/Log/LogMessage.cs b/Log/LogMessage.cs
index a85b9a43..e54ad2fe 100644
--- a/Log/LogMessage.cs
+++ b/Log/LogMessage.cs
@@ -97,7 +97,7 @@ public override string ToString()
// Just do this with a string builder rather than an XML builder.
String theMessage;
- theMessage = String.Format("{0}", LogDate);
+ theMessage = String.Format("{0}", LogDate.ToString("yyyy-MM-dd HH:mm:ss"));
theMessage += String.Format("{0}", _thread);
theMessage += String.Format("{0}", _method);
theMessage += String.Format("{0}", SecurityElement.Escape(_message));
diff --git a/Logic/ApplicationSettings.cs b/Logic/ApplicationSettings.cs
index 96843cf3..aa09be25 100644
--- a/Logic/ApplicationSettings.cs
+++ b/Logic/ApplicationSettings.cs
@@ -40,9 +40,9 @@ public class ApplicationSettings
private List _globalProperties;
// Application Specific Settings we want to protect
- private string _clientVersion = "1.8.1";
+ private string _clientVersion = "1.8.2";
private string _version = "5";
- private int _clientCodeVersion = 128;
+ private int _clientCodeVersion = 129;
public string ClientVersion { get { return _clientVersion; } }
public string Version { get { return _version; } }
@@ -498,6 +498,7 @@ public bool InDownloadWindow
public int CollectInterval { get; set; }
public int MaxConcurrentDownloads { get; set; }
public int ScreenShotRequestInterval { get; set; }
+ public int ScreenShotSize { get; set; }
private int _maxLogFileUploads;
public int MaxLogFileUploads { get { return ((_maxLogFileUploads == 0) ? 10 : _maxLogFileUploads); } set { _maxLogFileUploads = value; } }
diff --git a/Logic/Schedule.cs b/Logic/Schedule.cs
index 1848185b..a0520d28 100644
--- a/Logic/Schedule.cs
+++ b/Logic/Schedule.cs
@@ -273,6 +273,10 @@ void _scheduleManager_OnRefreshSchedule()
///
void _scheduleManager_OnScheduleManagerCheckComplete()
{
+ // XMR address is present and has received at least 1 heart beat
+ bool xmrShouldBeRunning = (!string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress) && _xmrSubscriber.LastHeartBeat != DateTime.MinValue);
+
+ // If the agent threads are all alive, and either XMR shouldn't be running OR the subscriber thread is alive.
if (agentThreadsAlive())
{
// Update status marker on the main thread.
@@ -280,31 +284,23 @@ void _scheduleManager_OnScheduleManagerCheckComplete()
}
else
{
- Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "Agent threads are dead, not updating status.json"), LogType.Error.ToString());
+ Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "Agent threads/XMR is dead, not updating status.json"), LogType.Error.ToString());
}
-
- try
+
+ // Log for overdue XMR
+ if (xmrShouldBeRunning && _xmrSubscriber.LastHeartBeat < DateTime.Now.AddHours(-1))
{
- // See if XMR should be running
- if (!string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress) && _xmrSubscriber.LastHeartBeat != DateTime.MinValue)
- {
- // Log when severly overdue a check
- if (_xmrSubscriber.LastHeartBeat < DateTime.Now.AddHours(-1))
- {
- Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "XMR heart beat last received over an hour ago."));
- }
+ _clientInfoForm.XmrSubscriberStatus = "Long term Inactive (" + ApplicationSettings.Default.XmrNetworkAddress + "), last activity: " + _xmrSubscriber.LastHeartBeat.ToString();
+ Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "XMR heart beat last received over an hour ago."));
- // Check to see if the last update date was over 5 minutes ago
- if (_xmrSubscriber.LastHeartBeat < DateTime.Now.AddMinutes(-5))
- {
- // Reconfigure it
- _registerAgent_OnXmrReconfigure();
- }
- }
+ // Issue an XMR restart if we've gone this long without connecting
+ // we do this because we suspect that the TCP socket has died without notifying the poller
+ restartXmr();
}
- catch (Exception e)
+ else if (xmrShouldBeRunning && _xmrSubscriber.LastHeartBeat < DateTime.Now.AddMinutes(-5))
{
- Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "Error = " + e.Message), LogType.Error.ToString());
+ _clientInfoForm.XmrSubscriberStatus = "Inactive (" + ApplicationSettings.Default.XmrNetworkAddress + "), last activity: " + _xmrSubscriber.LastHeartBeat.ToString();
+ Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "XMR heart beat last received over 5 minutes ago."), LogType.Audit.ToString());
}
}
@@ -317,7 +313,8 @@ private bool agentThreadsAlive()
return _registerAgentThread.IsAlive &&
_scheduleAndRfAgentThread.IsAlive &&
_logAgentThread.IsAlive &&
- _libraryAgentThread.IsAlive;
+ _libraryAgentThread.IsAlive &&
+ _xmrSubscriberThread.IsAlive;
}
///
@@ -325,34 +322,7 @@ private bool agentThreadsAlive()
///
void _registerAgent_OnXmrReconfigure()
{
- try
- {
- // Stop and start the XMR thread
- if (_xmrSubscriberThread != null && _xmrSubscriberThread.IsAlive)
- {
- _xmrSubscriberThread.Abort();
- }
- }
- catch (Exception e)
- {
- Trace.WriteLine(new LogMessage("Schedule - OnXmrReconfigure", "Unable to abort Subscriber. " + e.Message), LogType.Error.ToString());
- }
-
- try
- {
- // Reassert the hardware key, incase its changed at all
- _xmrSubscriber.HardwareKey = _hardwareKey;
-
- // Start the thread again
- _xmrSubscriberThread = new Thread(new ThreadStart(_xmrSubscriber.Run));
- _xmrSubscriberThread.Name = "XmrSubscriber";
-
- _xmrSubscriberThread.Start();
- }
- catch (Exception e)
- {
- Trace.WriteLine(new LogMessage("Schedule - OnXmrReconfigure", "Unable to start Subscriber. " + e.Message), LogType.Error.ToString());
- }
+ restartXmr();
}
///
@@ -438,6 +408,22 @@ public void wakeUpXmds()
_logAgent.WakeUp();
}
+ ///
+ /// Restart XMR
+ ///
+ public void restartXmr()
+ {
+ try
+ {
+ // Stop and start the XMR thread
+ _xmrSubscriber.Restart();
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("Schedule - restartXmr", "Unable to restart XMR: " + e.Message), LogType.Error.ToString());
+ }
+ }
+
///
/// Moves the layout on
///
@@ -604,7 +590,10 @@ public void Stop()
_logAgent.Stop();
// Stop the subsriber thread
- _xmrSubscriberThread.Abort();
+ _xmrSubscriber.Stop();
+
+ // Clean up any NetMQ sockets, etc (false means don't block).
+ NetMQ.NetMQConfig.Cleanup(false);
// Stop the embedded server
_server.Stop();
diff --git a/Logic/ScheduleManager.cs b/Logic/ScheduleManager.cs
index 24532b02..9d810afa 100644
--- a/Logic/ScheduleManager.cs
+++ b/Logic/ScheduleManager.cs
@@ -257,10 +257,6 @@ public void Run()
}
}
}
-
- // Write a flag to the status.xml file
- if (OnScheduleManagerCheckComplete != null)
- OnScheduleManagerCheckComplete();
}
catch (Exception ex)
{
@@ -271,7 +267,8 @@ public void Run()
}
// Completed this check
- OnScheduleManagerCheckComplete();
+ if (OnScheduleManagerCheckComplete != null)
+ OnScheduleManagerCheckComplete();
// Sleep this thread for 10 seconds
_manualReset.WaitOne(10 * 1000);
@@ -286,6 +283,9 @@ public void Run()
///
private bool IsNewScheduleAvailable()
{
+ // Remove completed change actions
+ removeLayoutChangeActionIfComplete();
+
// Remove completed overlay actions
removeOverlayLayoutActionIfComplete();
@@ -789,8 +789,10 @@ private void LoadScheduleFromLayoutChangeActions()
if (action.downloadRequired)
continue;
+ DateTime actionCreateDt = DateTime.Parse(action.createdDt);
+
ScheduleItem item = new ScheduleItem();
- item.FromDt = DateTime.MinValue;
+ item.FromDt = actionCreateDt.AddSeconds(-1);
item.ToDt = DateTime.MaxValue;
item.id = action.layoutId;
item.scheduleid = 0;
@@ -946,6 +948,9 @@ private string LayoutsInSchedule()
foreach (ScheduleItem layoutSchedule in CurrentSchedule)
{
+ if (layoutSchedule.Override)
+ layoutsInSchedule += "API Action ";
+
layoutsInSchedule += "LayoutId: " + layoutSchedule.id + ". Runs from " + layoutSchedule.FromDt.ToString() + Environment.NewLine;
}
@@ -1018,6 +1023,22 @@ public bool removeLayoutChangeActionIfComplete(ScheduleItem item)
return false;
}
+ ///
+ /// Remove Layout Change actions if they have completed
+ ///
+ public void removeLayoutChangeActionIfComplete()
+ {
+ // Check every action to see if complete
+ foreach (LayoutChangePlayerAction action in _layoutChangeActions)
+ {
+ if (action.IsServiced())
+ {
+ _layoutChangeActions.Remove(action);
+ RefreshSchedule = true;
+ }
+ }
+ }
+
///
/// Add an overlay layout action
///
diff --git a/Logic/ScreenShot.cs b/Logic/ScreenShot.cs
index 9d3c2845..2a221359 100644
--- a/Logic/ScreenShot.cs
+++ b/Logic/ScreenShot.cs
@@ -34,18 +34,49 @@ public static void TakeAndSend()
g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy);
}
- using (MemoryStream stream = new MemoryStream())
+ // Resize?
+ if (ApplicationSettings.Default.ScreenShotSize != 0)
{
- bitmap.Save(stream, ImageFormat.Jpeg);
+ Size thumbSize;
+ double ratio = (double)bounds.Width / (double)bounds.Height;
- byte[] bytes = stream.ToArray();
-
- using (xmds.xmds screenShotXmds = new xmds.xmds())
+ if (bounds.Width > bounds.Height)
{
- screenShotXmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
- screenShotXmds.SubmitScreenShotCompleted += screenShotXmds_SubmitScreenShotCompleted;
- screenShotXmds.SubmitScreenShotAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, bytes);
+ // Landscape
+ thumbSize = new Size(ApplicationSettings.Default.ScreenShotSize, (int)(ApplicationSettings.Default.ScreenShotSize / ratio));
}
+ else
+ {
+ // Portrait
+ thumbSize = new Size((int)(ApplicationSettings.Default.ScreenShotSize * ratio), ApplicationSettings.Default.ScreenShotSize);
+ }
+
+ // Create a bitmap at our desired resolution
+ using (Bitmap thumb = new Bitmap(bitmap, thumbSize.Width, thumbSize.Height))
+ {
+ send(thumb);
+ }
+ }
+ else
+ {
+ send(bitmap);
+ }
+ }
+ }
+
+ private static void send(Bitmap bitmap)
+ {
+ using (MemoryStream stream = new MemoryStream())
+ {
+ bitmap.Save(stream, ImageFormat.Jpeg);
+
+ byte[] bytes = stream.ToArray();
+
+ using (xmds.xmds screenShotXmds = new xmds.xmds())
+ {
+ screenShotXmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
+ screenShotXmds.SubmitScreenShotCompleted += screenShotXmds_SubmitScreenShotCompleted;
+ screenShotXmds.SubmitScreenShotAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, bytes);
}
}
}
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 76d8e804..938e014a 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -11,7 +11,7 @@
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Xibo Digital Signage")]
[assembly: AssemblyProduct("Xibo")]
-[assembly: AssemblyCopyright("Copyright Dan Garner © 2008-2016")]
+[assembly: AssemblyCopyright("Copyright Dan Garner © 2008-2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -30,6 +30,6 @@
// Build Number
// Revision
//
-[assembly: AssemblyVersion("10.8.1.0")]
-[assembly: AssemblyFileVersion("10.8.1.0")]
+[assembly: AssemblyVersion("10.8.2.0")]
+[assembly: AssemblyFileVersion("10.8.2.0")]
[assembly: NeutralResourcesLanguageAttribute("en-GB")]
diff --git a/XiboClient.csproj b/XiboClient.csproj
index c9ec5e03..9fc296e1 100644
--- a/XiboClient.csproj
+++ b/XiboClient.csproj
@@ -103,12 +103,11 @@
packages\NetMQ.4.0.0.1\lib\net40\NetMQ.dll
True
-
- packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll
- True
+
+ packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll
-
- packages\NodaTime.1.3.2\lib\net35-Client\NodaTime.dll
+
+ packages\NodaTime.2.0.2\lib\net45\NodaTime.dll
True
@@ -117,13 +116,17 @@
+
+
-
- False
- packages\EmbedIO.1.1.1\lib\net452\Unosquare.Labs.EmbedIO.dll
+
+ packages\EmbedIO.1.6.9\lib\net452\Unosquare.Labs.EmbedIO.dll
+
+
+ packages\Unosquare.Swan.0.14.2\lib\net452\Unosquare.Swan.dll
diff --git a/XmdsAgents/RegisterAgent.cs b/XmdsAgents/RegisterAgent.cs
index f5c4eaa7..93fbbb7d 100644
--- a/XmdsAgents/RegisterAgent.cs
+++ b/XmdsAgents/RegisterAgent.cs
@@ -223,16 +223,16 @@ private string WindowsToIana(string windowsZoneId)
if (windowsZoneId.Equals("UTC", StringComparison.Ordinal))
return "Etc/UTC";
- var tzdbSource = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default;
- var tzi = TimeZoneInfo.FindSystemTimeZoneById(windowsZoneId);
- if (tzi == null)
- return null;
-
- var tzid = tzdbSource.MapTimeZoneId(tzi);
- if (tzid == null)
- return null;
-
- return tzdbSource.CanonicalIdMap[tzid];
+ var source = NodaTime.TimeZones.TzdbDateTimeZoneSource.Default;
+ string result;
+ // If there's no such mapping, result will be null.
+ source.WindowsMapping.PrimaryMapping.TryGetValue(windowsZoneId, out result);
+ // Canonicalize
+ if (result != null)
+ {
+ result = source.CanonicalIdMap[result];
+ }
+ return result;
}
}
}
diff --git a/default.config.xml b/default.config.xml
index e438b2e7..edcc42e3 100644
--- a/default.config.xml
+++ b/default.config.xml
@@ -52,4 +52,5 @@
1
9696
+ 0
\ No newline at end of file
diff --git a/packages.config b/packages.config
index da04f453..0e43a549 100644
--- a/packages.config
+++ b/packages.config
@@ -2,8 +2,9 @@
-
+
-
-
+
+
+
\ No newline at end of file