diff --git a/Action/Command.cs b/Action/Command.cs
new file mode 100644
index 00000000..ae3cfc07
--- /dev/null
+++ b/Action/Command.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+namespace XiboClient.Logic
+{
+ [Serializable]
+ public class Command
+ {
+ public string Code;
+ public string CommandString;
+ public string Validation;
+
+ public bool notifyStatus()
+ {
+ return !string.IsNullOrEmpty(Validation);
+ }
+
+ ///
+ /// Run the Command
+ ///
+ /// true on success
+ public bool Run()
+ {
+ if (string.IsNullOrEmpty(CommandString))
+ throw new ArgumentNullException("Command string is empty, please check your Display Profile " + Code + " command for a valid command string.");
+
+ // Parse the command string to work out how we should run this command.
+ if (CommandString.StartsWith("rs232"))
+ {
+ Rs232Command rs232 = new Rs232Command(this);
+ string line = rs232.Run();
+
+ if (notifyStatus())
+ {
+ return line == Validation;
+ }
+ else
+ {
+ return true;
+ }
+ }
+ else
+ {
+ // Process with CMD
+ using (Process process = new Process())
+ {
+ ProcessStartInfo startInfo = new ProcessStartInfo();
+
+ startInfo.CreateNoWindow = true;
+ startInfo.WindowStyle = ProcessWindowStyle.Hidden;
+ startInfo.FileName = "cmd.exe";
+ startInfo.Arguments = "/C " + CommandString;
+ startInfo.UseShellExecute = false;
+
+ if (notifyStatus())
+ startInfo.RedirectStandardOutput = true;
+
+ process.StartInfo = startInfo;
+ process.Start();
+
+ if (notifyStatus())
+ {
+ string line = "";
+ while (!process.StandardOutput.EndOfStream)
+ {
+ line += process.StandardOutput.ReadLine();
+ }
+
+ return line == Validation;
+ }
+ else
+ return true;
+ }
+ }
+ }
+
+ ///
+ /// Get a command from Application Settings based on its Command Code
+ ///
+ ///
+ ///
+ public static Command GetByCode(string code)
+ {
+ foreach (Command command in ApplicationSettings.Default.Commands)
+ {
+ if (command.Code == code)
+ return command;
+ }
+
+ throw new KeyNotFoundException("Command Not Found");
+ }
+ }
+}
diff --git a/Action/PlayerAction.cs b/Action/PlayerAction.cs
new file mode 100644
index 00000000..7b0ae634
--- /dev/null
+++ b/Action/PlayerAction.cs
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace XiboClient.Action
+{
+ class PlayerAction
+ {
+ public string action;
+
+ public DateTime createdDt;
+ public int ttl;
+ }
+}
diff --git a/Action/Rs232Command.cs b/Action/Rs232Command.cs
new file mode 100644
index 00000000..7b17912f
--- /dev/null
+++ b/Action/Rs232Command.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO.Ports;
+using System.Linq;
+using System.Text;
+
+namespace XiboClient.Logic
+{
+ public class Rs232Command
+ {
+ private Command _command;
+
+ private SerialPort _port;
+ private string _toSend;
+
+ public Rs232Command(Command command)
+ {
+ _command = command;
+ }
+
+ ///
+ /// Run the command
+ ///
+ public string Run()
+ {
+ string response = "";
+
+ // Parse and configure the port
+ parse();
+
+ // try to open the COM port
+ if (!_port.IsOpen)
+ _port.Open();
+
+ try
+ {
+ // Write our data stream
+ _port.Write(_toSend);
+
+ // Read
+ if (_command.notifyStatus())
+ {
+ _port.ReadTimeout = 5000;
+ response = _port.ReadLine();
+ }
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("CommandRs232 - run", e.Message), LogType.Error.ToString());
+ }
+ finally
+ {
+ // Close the port
+ _port.Close();
+ }
+
+ return response;
+ }
+
+ ///
+ /// Parses the command string
+ ///
+ private void parse()
+ {
+ if (!_command.CommandString.StartsWith("rs232"))
+ throw new ArgumentException("Not a RS232 command");
+
+ // Split the command string by "space"
+ string[] command = _command.CommandString.Split('|');
+
+ // The second part of the string is our comma separated connection string
+ // Port,Baud,Data,Parity,Stop,Flow
+ string[] connection = command[1].Split(',');
+
+ _port = new SerialPort();
+ _port.PortName = connection[0];
+ _port.BaudRate = Convert.ToInt32(connection[1]);
+ _port.DataBits = Convert.ToInt16(connection[2]);
+ _port.Parity = (Parity)Enum.Parse(typeof(Parity), connection[3]);
+ _port.StopBits = (StopBits)Enum.Parse(typeof(StopBits), connection[4]);
+ _port.Handshake = (Handshake)Enum.Parse(typeof(Handshake), connection[5]);
+
+ // Get the actual command to send
+ _toSend = command[2];
+ }
+ }
+}
diff --git a/Action/ScheduleCommand.cs b/Action/ScheduleCommand.cs
new file mode 100644
index 00000000..8e93e7e3
--- /dev/null
+++ b/Action/ScheduleCommand.cs
@@ -0,0 +1,55 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+
+namespace XiboClient.Logic
+{
+ public class ScheduleCommand
+ {
+ public DateTime Date { get; set; }
+ public String Code { get; set; }
+ public Command Command { get; set; }
+ public int ScheduleId { get; set; }
+
+ private bool _run = false;
+ public bool HasRun
+ {
+ get
+ {
+ return _run;
+ }
+ set
+ {
+ _run = value;
+ }
+ }
+
+ public void Run()
+ {
+ bool success;
+
+ try
+ {
+ // Get a fresh command from settings
+ Command = Command.GetByCode(Code);
+
+ // Run the command.
+ success = Command.Run();
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("CommandSchedule - Run", "Cannot start Run Command: " + e.Message), LogType.Error.ToString());
+ success = false;
+ }
+
+ // Notify the state of the command (success or failure)
+ using (xmds.xmds statusXmds = new xmds.xmds())
+ {
+ statusXmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
+ statusXmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, "{\"lastCommandSuccess\":" + success + "}");
+ }
+ }
+ }
+}
diff --git a/Action/XmrSubscriber.cs b/Action/XmrSubscriber.cs
new file mode 100644
index 00000000..33c9f8e6
--- /dev/null
+++ b/Action/XmrSubscriber.cs
@@ -0,0 +1,161 @@
+using NetMQ;
+using NetMQ.Sockets;
+using Newtonsoft.Json;
+using Org.BouncyCastle.Crypto;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using XiboClient.Action;
+using XiboClient.Log;
+
+namespace XiboClient.Logic
+{
+ class XmrSubscriber
+ {
+ public static object _locker = new object();
+
+ // Members to stop the thread
+ private bool _forceStop = false;
+
+ ///
+ /// Last Heartbeat packet received
+ ///
+ public DateTime LastHeartBeat = DateTime.MinValue;
+
+ // Events
+ public delegate void OnCollectNowActionDelegate();
+ public event OnCollectNowActionDelegate OnCollectNowAction;
+
+ ///
+ /// Client Hardware key
+ ///
+ public HardwareKey HardwareKey
+ {
+ set
+ {
+ _hardwareKey = value;
+ }
+ }
+ private HardwareKey _hardwareKey;
+
+ ///
+ /// Client Info Form
+ ///
+ public ClientInfo ClientInfoForm
+ {
+ set
+ {
+ _clientInfoForm = value;
+ }
+ }
+ private ClientInfo _clientInfoForm;
+
+ ///
+ /// Runs the agent
+ ///
+ public void Run()
+ {
+ try
+ {
+ // Check we have an address to connect to.
+ if (string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress))
+ throw new Exception("Empty XMR Network Address");
+
+ // Get the Private Key
+ AsymmetricCipherKeyPair rsaKey = _hardwareKey.getXmrKey();
+
+ // Connect to XMR
+ using (NetMQContext context = NetMQContext.Create())
+ {
+ using (SubscriberSocket socket = context.CreateSubscriberSocket())
+ {
+ // Bind
+ socket.Connect(ApplicationSettings.Default.XmrNetworkAddress);
+ socket.Subscribe("H");
+ socket.Subscribe(_hardwareKey.Channel);
+
+ // Notify
+ _clientInfoForm.XmrSubscriberStatus = "Connected to " + ApplicationSettings.Default.XmrNetworkAddress;
+
+ while (!_forceStop)
+ {
+ lock (_locker)
+ {
+ try
+ {
+ NetMQMessage message = socket.ReceiveMultipartMessage();
+
+ // Update status
+ _clientInfoForm.XmrSubscriberStatus = "Connected (" + ApplicationSettings.Default.XmrNetworkAddress + "), last activity: " + DateTime.Now.ToString();
+
+ // Deal with heart beat
+ if (message[0].ConvertToString() == "H")
+ {
+ LastHeartBeat = DateTime.Now;
+ continue;
+ }
+
+ // Decrypt the message
+ string opened = OpenSslInterop.decrypt(message[2].ConvertToString(), message[1].ConvertToString(), rsaKey.Private);
+
+ // 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;
+ }
+
+ // 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;
+
+ new Thread(new ThreadStart(command.Run)).Start();
+ break;
+
+ case "collectNow":
+ OnCollectNowAction();
+ 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;
+ }
+ }
+ }
+ }
+ }
+
+ // Update status
+ _clientInfoForm.XmrSubscriberStatus = "Not Running, last activity: " + LastHeartBeat.ToString();
+
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Subscriber Stopped"), LogType.Info.ToString());
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("XmrSubscriber - Run", "Unable to Subscribe to XMR: " + e.Message), LogType.Error.ToString());
+ _clientInfoForm.XmrSubscriberStatus = e.Message;
+ }
+ }
+ }
+}
diff --git a/Forms/OptionForm.cs b/Forms/OptionForm.cs
index 9010a4b1..d186072d 100644
--- a/Forms/OptionForm.cs
+++ b/Forms/OptionForm.cs
@@ -133,7 +133,17 @@ private void buttonSaveSettings_Click(object sender, EventArgs e)
ApplicationSettings.Default.Save();
// Call register
- xmds1.RegisterDisplayAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, ApplicationSettings.Default.DisplayName, "windows", ApplicationSettings.Default.ClientVersion, ApplicationSettings.Default.ClientCodeVersion, Environment.OSVersion.ToString(), _hardwareKey.MacAddress, ApplicationSettings.Default.Version);
+ xmds1.RegisterDisplayAsync(
+ ApplicationSettings.Default.ServerKey,
+ ApplicationSettings.Default.HardwareKey,
+ ApplicationSettings.Default.DisplayName,
+ "windows",
+ ApplicationSettings.Default.ClientVersion,
+ ApplicationSettings.Default.ClientCodeVersion,
+ Environment.OSVersion.ToString(),
+ _hardwareKey.MacAddress,
+ _hardwareKey.Channel,
+ _hardwareKey.getXmrPublicKey());
}
catch (Exception ex)
{
diff --git a/Log/ClientInfo.Designer.cs b/Log/ClientInfo.Designer.cs
index fed61e07..db995695 100644
--- a/Log/ClientInfo.Designer.cs
+++ b/Log/ClientInfo.Designer.cs
@@ -46,6 +46,8 @@ private void InitializeComponent()
this.scheduleManagerStatus = new System.Windows.Forms.TextBox();
this.saveLogToDisk = new System.Windows.Forms.Button();
this.saveFileDialog = new System.Windows.Forms.SaveFileDialog();
+ this.label3 = new System.Windows.Forms.Label();
+ this.xmrStatus = new System.Windows.Forms.Label();
((System.ComponentModel.ISupportInitialize)(this.logDataGridView)).BeginInit();
this.SuspendLayout();
//
@@ -137,7 +139,7 @@ private void InitializeComponent()
// scheduleStatusLabel
//
this.scheduleStatusLabel.AutoSize = true;
- this.scheduleStatusLabel.Location = new System.Drawing.Point(148, 11);
+ this.scheduleStatusLabel.Location = new System.Drawing.Point(103, 11);
this.scheduleStatusLabel.Name = "scheduleStatusLabel";
this.scheduleStatusLabel.Size = new System.Drawing.Size(61, 13);
this.scheduleStatusLabel.TabIndex = 2;
@@ -195,11 +197,31 @@ private void InitializeComponent()
//
this.saveFileDialog.FileOk += new System.ComponentModel.CancelEventHandler(this.saveFileDialog_FileOk);
//
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(103, 734);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(67, 13);
+ this.label3.TabIndex = 10;
+ this.label3.Text = "XMR Status:";
+ //
+ // xmrStatus
+ //
+ this.xmrStatus.AutoSize = true;
+ this.xmrStatus.Location = new System.Drawing.Point(176, 734);
+ this.xmrStatus.Name = "xmrStatus";
+ this.xmrStatus.Size = new System.Drawing.Size(61, 13);
+ this.xmrStatus.TabIndex = 11;
+ this.xmrStatus.Text = "Not Started";
+ //
// ClientInfo
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(810, 758);
+ this.Controls.Add(this.xmrStatus);
+ this.Controls.Add(this.label3);
this.Controls.Add(this.saveLogToDisk);
this.Controls.Add(this.scheduleManagerStatus);
this.Controls.Add(this.requiredFilesTextBox);
@@ -233,5 +255,7 @@ private void InitializeComponent()
private System.Windows.Forms.TextBox scheduleManagerStatus;
private System.Windows.Forms.Button saveLogToDisk;
private System.Windows.Forms.SaveFileDialog saveFileDialog;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.Label xmrStatus;
}
}
\ No newline at end of file
diff --git a/Log/ClientInfo.cs b/Log/ClientInfo.cs
index 13f4b14b..35a52dd4 100644
--- a/Log/ClientInfo.cs
+++ b/Log/ClientInfo.cs
@@ -89,6 +89,24 @@ public string CurrentLayoutId
}
}
+ ///
+ /// XMR Status
+ ///
+ public string XmrSubscriberStatus
+ {
+ set
+ {
+ if (InvokeRequired)
+ {
+ BeginInvoke(new StatusDelegate(SetXmrStatus), value);
+ }
+ else
+ {
+ SetXmrStatus(value);
+ }
+ }
+ }
+
///
/// Client Info Object
///
@@ -150,6 +168,15 @@ public void SetCurrentlyPlaying(string layoutName)
Text = "Client Information and Status - " + ApplicationSettings.Default.ServerUri + " - Currently Showing: " + layoutName;
}
+ ///
+ /// Sets the XMR Status
+ ///
+ ///
+ public void SetXmrStatus(string status)
+ {
+ xmrStatus.Text = status;
+ }
+
///
/// Adds a log message
///
diff --git a/Logic/ApplicationSettings.cs b/Logic/ApplicationSettings.cs
index 52a06a0a..93087ae2 100644
--- a/Logic/ApplicationSettings.cs
+++ b/Logic/ApplicationSettings.cs
@@ -26,6 +26,7 @@
using System.Text;
using System.Windows.Forms;
using System.Xml.Serialization;
+using XiboClient.Logic;
namespace XiboClient
{
@@ -38,7 +39,7 @@ public class ApplicationSettings
// Application Specific Settings we want to protect
private string _clientVersion = "1.7.5";
- private string _version = "4";
+ private string _version = "5";
private int _clientCodeVersion = 109;
public string ClientVersion { get { return _clientVersion; } }
@@ -161,6 +162,7 @@ public object this[string propertyName]
public string LogToDiskLocation { get; set; }
public string CursorStartPosition { get; set; }
public string ClientInformationKeyCode { get; set; }
+ public string XmrNetworkAddress { get; set; }
// Download window
@@ -286,6 +288,8 @@ public void IncrementXmdsErrorCount()
};
}
+ public List Commands { get; set; }
+
// Settings HASH
public string Hash { get; set; }
}
diff --git a/Logic/HardwareKey.cs b/Logic/HardwareKey.cs
index ea5dfbc7..20a74e6a 100644
--- a/Logic/HardwareKey.cs
+++ b/Logic/HardwareKey.cs
@@ -23,6 +23,12 @@
using System.Management;
using System.Text;
using System.Diagnostics;
+using System.Security.Cryptography;
+using System.Windows.Forms;
+using Org.BouncyCastle.Security;
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.OpenSsl;
+using System.IO;
namespace XiboClient
{
@@ -32,6 +38,26 @@ class HardwareKey
private string _hardwareKey;
private string _macAddress;
+ private string _channel;
+
+ public string Channel
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(_channel))
+ {
+ // Channel is based on the CMS URL, CMS Key and Hardware Key
+ _channel = Hashes.MD5(ApplicationSettings.Default.ServerUri + ApplicationSettings.Default.ServerKey + _hardwareKey);
+ }
+
+ return _channel;
+ }
+ }
+
+ public void clearChannel()
+ {
+ _channel = null;
+ }
public string MacAddress
{
@@ -171,5 +197,40 @@ public string GetCPUId()
return cpuInfo;
}
}
+
+ ///
+ /// Get the XMR public key
+ ///
+ ///
+ public AsymmetricCipherKeyPair getXmrKey()
+ {
+ const int PROVIDER_RSA_FULL = 1;
+ CspParameters cspParams;
+ cspParams = new CspParameters(PROVIDER_RSA_FULL);
+ cspParams.KeyContainerName = Application.ProductName + "RsaKey";
+ cspParams.Flags = CspProviderFlags.UseMachineKeyStore;
+ cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
+
+ using (RSACryptoServiceProvider provider = new RSACryptoServiceProvider(cspParams))
+ {
+ RSAParameters keyInfo = provider.ExportParameters(true);
+
+ return DotNetUtilities.GetRsaKeyPair(keyInfo);
+ }
+ }
+
+ public string getXmrPublicKey()
+ {
+ AsymmetricCipherKeyPair key = getXmrKey();
+
+ using (TextWriter textWriter = new StringWriter())
+ {
+ PemWriter writer = new PemWriter(textWriter);
+ writer.WriteObject(key.Public);
+ writer.Writer.Flush();
+
+ return textWriter.ToString();
+ }
+ }
}
}
diff --git a/Logic/OpenSslInterop.cs b/Logic/OpenSslInterop.cs
new file mode 100644
index 00000000..3f073b54
--- /dev/null
+++ b/Logic/OpenSslInterop.cs
@@ -0,0 +1,32 @@
+using Org.BouncyCastle.Crypto;
+using Org.BouncyCastle.Crypto.Parameters;
+using Org.BouncyCastle.Security;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+
+namespace XiboClient.Logic
+{
+ public class OpenSslInterop
+ {
+ public static string decrypt(string cypherText, string cypherKey, AsymmetricKeyParameter privateKey)
+ {
+ // Create a RSA cypher
+ IBufferedCipher rsaCipher = CipherUtilities.GetCipher("RSA//PKCS1PADDING");
+ rsaCipher.Init(false, privateKey);
+
+ // Get the decrypted key
+ byte[] key = rsaCipher.DoFinal(Convert.FromBase64String(cypherKey));
+
+ // Use this Key to decrypt the main message
+ IBufferedCipher rsaKeyCipher = CipherUtilities.GetCipher("RC4");
+ KeyParameter parameter = new KeyParameter(key);
+ rsaKeyCipher.Init(false, parameter);
+
+ byte[] opened = rsaKeyCipher.DoFinal(Convert.FromBase64String(cypherText));
+
+ return Encoding.ASCII.GetString(opened);
+ }
+ }
+}
diff --git a/Logic/Schedule.cs b/Logic/Schedule.cs
index b767c8d5..6f9e3ddb 100644
--- a/Logic/Schedule.cs
+++ b/Logic/Schedule.cs
@@ -31,6 +31,7 @@
using System.Threading;
using XiboClient.Properties;
using XiboClient.Log;
+using XiboClient.Logic;
/// 17/02/12 Dan Removed Schedule call, introduced ScheduleAgent
/// 21/02/12 Dan Named the threads
@@ -81,6 +82,10 @@ class Schedule
private LogAgent _logAgent;
Thread _logAgentThread;
+ // XMR Subscriber
+ private XmrSubscriber _xmrSubscriber;
+ Thread _xmrSubscriberThread;
+
///
/// Client Info Form
///
@@ -111,6 +116,7 @@ public Schedule(string scheduleLocation, ref CacheManager cacheManager, ref Clie
// Create a Register Agent
_registerAgent = new RegisterAgent();
+ _registerAgent.OnXmrReconfigure += _registerAgent_OnXmrReconfigure;
_registerAgentThread = new Thread(new ThreadStart(_registerAgent.Run));
_registerAgentThread.Name = "RegisterAgentThread";
@@ -118,6 +124,7 @@ public Schedule(string scheduleLocation, ref CacheManager cacheManager, ref Clie
_scheduleManager = new ScheduleManager(_cacheManager, scheduleLocation);
_scheduleManager.OnNewScheduleAvailable += new ScheduleManager.OnNewScheduleAvailableDelegate(_scheduleManager_OnNewScheduleAvailable);
_scheduleManager.OnRefreshSchedule += new ScheduleManager.OnRefreshScheduleDelegate(_scheduleManager_OnRefreshSchedule);
+ _scheduleManager.OnScheduleManagerCheckComplete += _scheduleManager_OnScheduleManagerCheckComplete;
_scheduleManager.ClientInfoForm = _clientInfoForm;
// Create a schedule manager thread
@@ -158,6 +165,16 @@ public Schedule(string scheduleLocation, ref CacheManager cacheManager, ref Clie
_logAgent = new LogAgent();
_logAgentThread = new Thread(new ThreadStart(_logAgent.Run));
_logAgentThread.Name = "LogAgent";
+
+ // XMR Subscriber
+ _xmrSubscriber = new XmrSubscriber();
+ _xmrSubscriber.HardwareKey = _hardwareKey;
+ _xmrSubscriber.ClientInfoForm = _clientInfoForm;
+ _xmrSubscriber.OnCollectNowAction += _xmrSubscriber_OnCollectNowAction;
+
+ // Thread start
+ _xmrSubscriberThread = new Thread(new ThreadStart(_xmrSubscriber.Run));
+ _xmrSubscriberThread.Name = "XmrSubscriber";
}
///
@@ -182,6 +199,9 @@ public void InitializeComponents()
// Start the LogAgent thread
_logAgentThread.Start();
+
+ // Start the subscriber thread
+ _xmrSubscriberThread.Start();
}
///
@@ -206,6 +226,77 @@ void _scheduleManager_OnRefreshSchedule()
_layoutSchedule = _scheduleManager.CurrentSchedule;
}
+ ///
+ /// Schedule Manager has completed a cycle
+ ///
+ void _scheduleManager_OnScheduleManagerCheckComplete()
+ {
+ try
+ {
+ // See if XMR should be running
+ if (!string.IsNullOrEmpty(ApplicationSettings.Default.XmrNetworkAddress) && _xmrSubscriber.LastHeartBeat != DateTime.MinValue)
+ {
+ // Check to see if the last update date was over 5 minutes ago
+ if (_xmrSubscriber.LastHeartBeat < DateTime.Now.AddSeconds(-90))
+ {
+ // Reconfigure it
+ _registerAgent_OnXmrReconfigure();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("Schedule - OnScheduleManagerCheckComplete", "Error = " + e.Message), LogType.Error.ToString());
+ }
+ }
+
+ ///
+ /// XMR Reconfigure
+ ///
+ 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());
+ }
+ }
+
+ ///
+ /// Collect Now Action
+ ///
+ void _xmrSubscriber_OnCollectNowAction()
+ {
+ // Run all of the various agents
+ _registerAgent.WakeUp();
+ _scheduleAgent.WakeUp();
+ _requiredFilesAgent.WakeUp();
+ _logAgent.WakeUp();
+ }
+
///
/// Moves the layout on
///
@@ -315,6 +406,9 @@ public void Stop()
// Stop the LogAgent Thread
_logAgent.Stop();
+
+ // Stop the subsriber thread
+ _xmrSubscriberThread.Abort();
}
}
}
diff --git a/Logic/ScheduleManager.cs b/Logic/ScheduleManager.cs
index fbaf791b..8970c5bb 100644
--- a/Logic/ScheduleManager.cs
+++ b/Logic/ScheduleManager.cs
@@ -57,10 +57,16 @@ class ScheduleManager
public delegate void OnRefreshScheduleDelegate();
public event OnRefreshScheduleDelegate OnRefreshSchedule;
+ // Event for Subscriber inactive
+ public delegate void OnScheduleManagerCheckCompleteDelegate();
+ public event OnScheduleManagerCheckCompleteDelegate OnScheduleManagerCheckComplete;
+
// Member Varialbes
private string _location;
private Collection _layoutSchedule;
private Collection _currentSchedule;
+ private Collection _commands;
+
private bool _refreshSchedule;
private CacheManager _cacheManager;
private DateTime _lastScreenShotDate;
@@ -89,6 +95,7 @@ public ScheduleManager(CacheManager cacheManager, string scheduleLocation)
// Create an empty layout schedule
_layoutSchedule = new Collection();
_currentSchedule = new Collection();
+ _commands = new Collection();
_lastScreenShotDate = DateTime.MinValue;
}
@@ -182,6 +189,29 @@ public void Run()
_lastScreenShotDate = DateTime.Now;
}
+ // Run any commands that occur in the next 10 seconds.
+ DateTime now = DateTime.Now;
+ DateTime tenSecondsTime = now.AddSeconds(10);
+
+ foreach (ScheduleCommand command in _commands)
+ {
+ if (command.Date >= now && command.Date < tenSecondsTime && !command.HasRun)
+ {
+ try
+ {
+ // We need to run this command
+ new Thread(new ThreadStart(command.Run)).Start();
+
+ // Mark run
+ command.HasRun = true;
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("ScheduleManager - Run", "Cannot start Thread to Run Command: " + e.Message), LogType.Error.ToString());
+ }
+ }
+ }
+
// Write a flag to the status.xml file
File.WriteAllText(Path.Combine(ApplicationSettings.Default.LibraryPath, "status.json"), "{\"lastActivity\":\"" + DateTime.Now.ToString() + "\"}");
}
@@ -193,6 +223,9 @@ public void Run()
}
}
+ // Completed this check
+ OnScheduleManagerCheckComplete();
+
// Sleep this thread for 10 seconds
_manualReset.WaitOne(10 * 1000);
}
@@ -341,6 +374,9 @@ private void LoadScheduleFromFile()
// Empty the current schedule collection
_layoutSchedule.Clear();
+ // Clear the list of commands
+ _commands.Clear();
+
// Get the schedule XML
XmlDocument scheduleXml = GetScheduleXml();
@@ -366,6 +402,27 @@ private void LoadScheduleFromFile()
{
// Do nothing for now
}
+ else if (temp.NodeName == "command")
+ {
+ // Try to get the command using the code
+ try
+ {
+ // Pull attributes from layout nodes
+ XmlAttributeCollection attributes = node.Attributes;
+
+ ScheduleCommand command = new ScheduleCommand();
+ command.Date = DateTime.Parse(attributes["date"].Value, CultureInfo.InvariantCulture);
+ command.Code = attributes["code"].Value;
+ command.ScheduleId = int.Parse(attributes["scheduleid"].Value);
+
+ // Add to the collection
+ _commands.Add(command);
+ }
+ catch (Exception e)
+ {
+ Trace.WriteLine(new LogMessage("ScheduleManager - LoadScheduleFromFile", e.Message), LogType.Error.ToString());
+ }
+ }
else
{
// Pull attributes from layout nodes
diff --git a/Media/ShellCommand.cs b/Media/ShellCommand.cs
index 7189a403..423b67bb 100644
--- a/Media/ShellCommand.cs
+++ b/Media/ShellCommand.cs
@@ -22,61 +22,95 @@
using System.Text;
using System.Diagnostics;
using XiboClient.Properties;
+using XiboClient.Logic;
namespace XiboClient
{
class ShellCommand : Media
{
string _command = "";
+ string _code = "";
public ShellCommand(RegionOptions options)
: base(options.width, options.height, options.top, options.left)
{
_command = Uri.UnescapeDataString(options.Dictionary.Get("windowsCommand")).Replace('+', ' ');
+ _code = options.Dictionary.Get("commandCode");
}
public override void RenderMedia()
{
- // Is this module enabled?
- if (ApplicationSettings.Default.EnableShellCommands)
+ if (!string.IsNullOrEmpty(_code))
{
- // Check to see if we have an allow list
- if (!string.IsNullOrEmpty(ApplicationSettings.Default.ShellCommandAllowList))
+ // Stored command
+ bool success;
+
+ try
+ {
+ Command command = Command.GetByCode(_code);
+ success = command.Run();
+ }
+ catch (Exception e)
{
- // Array of allowed commands
- string[] allowedCommands = ApplicationSettings.Default.ShellCommandAllowList.Split(',');
+ Trace.WriteLine(new LogMessage("ScheduleManager - Run", "Cannot run Command: " + e.Message), LogType.Error.ToString());
+ success = false;
+ }
- // Check we are allowed to execute the command
- bool found = false;
+ // Notify the state of the command (success or failure)
+ using (xmds.xmds statusXmds = new xmds.xmds())
+ {
+ statusXmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
+ statusXmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, "{\"lastCommandSuccess\":" + success + "}");
+ }
+ }
+ else
+ {
+ // shell command
- foreach (string allowedCommand in allowedCommands)
+ // Is this module enabled?
+ if (ApplicationSettings.Default.EnableShellCommands)
+ {
+ // Check to see if we have an allow list
+ if (!string.IsNullOrEmpty(ApplicationSettings.Default.ShellCommandAllowList))
{
- if (_command.StartsWith(allowedCommand))
+ // Array of allowed commands
+ string[] allowedCommands = ApplicationSettings.Default.ShellCommandAllowList.Split(',');
+
+ // Check we are allowed to execute the command
+ bool found = false;
+
+ foreach (string allowedCommand in allowedCommands)
{
- found = true;
- ExecuteShellCommand();
- break;
+ if (_command.StartsWith(allowedCommand))
+ {
+ found = true;
+ ExecuteShellCommand();
+ break;
+ }
}
- }
- if (!found)
- Trace.WriteLine(new LogMessage("ShellCommand - RenderMedia", "Shell Commands not in allow list: " + ApplicationSettings.Default.ShellCommandAllowList), LogType.Error.ToString());
+ if (!found)
+ Trace.WriteLine(new LogMessage("ShellCommand - RenderMedia", "Shell Commands not in allow list: " + ApplicationSettings.Default.ShellCommandAllowList), LogType.Error.ToString());
+ }
+ else
+ {
+ // All commands are allowed
+ ExecuteShellCommand();
+ }
}
else
{
- // All commands are allowed
- ExecuteShellCommand();
+ Trace.WriteLine(new LogMessage("ShellCommand - RenderMedia", "Shell Commands are disabled"), LogType.Error.ToString());
}
}
- else
- {
- Trace.WriteLine(new LogMessage("ShellCommand - RenderMedia", "Shell Commands are disabled"), LogType.Error.ToString());
- }
// All shell commands have a duration of 1
base.RenderMedia();
}
+ ///
+ /// Execute the shell command
+ ///
private void ExecuteShellCommand()
{
Trace.WriteLine(new LogMessage("ShellCommand - ExecuteShellCommand", _command), LogType.Info.ToString());
diff --git a/Web References/xmds/Reference.cs b/Web References/xmds/Reference.cs
index 6e46e00e..e6c5e8c5 100644
--- a/Web References/xmds/Reference.cs
+++ b/Web References/xmds/Reference.cs
@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
//
// This code was generated by a tool.
-// Runtime Version:4.0.30319.18444
+// Runtime Version:4.0.30319.34209
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
@@ -9,7 +9,7 @@
//------------------------------------------------------------------------------
//
-// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.18444.
+// This source code was auto-generated by Microsoft.VSDesigner, Version 4.0.30319.34209.
//
#pragma warning disable 1591
@@ -23,7 +23,7 @@ namespace XiboClient.xmds {
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="xmdsBinding", Namespace="urn:xmds")]
@@ -55,7 +55,7 @@ public partial class xmds : System.Web.Services.Protocols.SoapHttpClientProtocol
///
public xmds() {
- this.Url = "http://172.28.128.3/xmds.php?v=4";
+ this.Url = "http://192.168.0.28/xmds.php?v=5";
if ((this.IsLocalFileSystemWebService(this.Url) == true)) {
this.UseDefaultCredentials = true;
this.useDefaultCredentialsSetExplicitly = false;
@@ -125,7 +125,7 @@ public xmds() {
///
[System.Web.Services.Protocols.SoapRpcMethodAttribute("urn:xmds#RegisterDisplay", RequestNamespace="urn:xmds", ResponseNamespace="urn:xmds")]
[return: System.Xml.Serialization.SoapElementAttribute("ActivationMessage")]
- public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string clientType, string clientVersion, int clientCode, string operatingSystem, string macAddress) {
+ public string RegisterDisplay(string serverKey, string hardwareKey, string displayName, string clientType, string clientVersion, int clientCode, string operatingSystem, string macAddress, string xmrChannel, string xmrPubKey) {
object[] results = this.Invoke("RegisterDisplay", new object[] {
serverKey,
hardwareKey,
@@ -134,17 +134,19 @@ public string RegisterDisplay(string serverKey, string hardwareKey, string displ
clientVersion,
clientCode,
operatingSystem,
- macAddress});
+ macAddress,
+ xmrChannel,
+ xmrPubKey});
return ((string)(results[0]));
}
///
- public void RegisterDisplayAsync(string serverKey, string hardwareKey, string displayName, string clientType, string clientVersion, int clientCode, string operatingSystem, string macAddress) {
- this.RegisterDisplayAsync(serverKey, hardwareKey, displayName, clientType, clientVersion, clientCode, operatingSystem, macAddress, null);
+ public void RegisterDisplayAsync(string serverKey, string hardwareKey, string displayName, string clientType, string clientVersion, int clientCode, string operatingSystem, string macAddress, string xmrChannel, string xmrPubKey) {
+ this.RegisterDisplayAsync(serverKey, hardwareKey, displayName, clientType, clientVersion, clientCode, operatingSystem, macAddress, xmrChannel, xmrPubKey, null);
}
///
- public void RegisterDisplayAsync(string serverKey, string hardwareKey, string displayName, string clientType, string clientVersion, int clientCode, string operatingSystem, string macAddress, object userState) {
+ public void RegisterDisplayAsync(string serverKey, string hardwareKey, string displayName, string clientType, string clientVersion, int clientCode, string operatingSystem, string macAddress, string xmrChannel, string xmrPubKey, object userState) {
if ((this.RegisterDisplayOperationCompleted == null)) {
this.RegisterDisplayOperationCompleted = new System.Threading.SendOrPostCallback(this.OnRegisterDisplayOperationCompleted);
}
@@ -156,7 +158,9 @@ public void RegisterDisplayAsync(string serverKey, string hardwareKey, string di
clientVersion,
clientCode,
operatingSystem,
- macAddress}, this.RegisterDisplayOperationCompleted, userState);
+ macAddress,
+ xmrChannel,
+ xmrPubKey}, this.RegisterDisplayOperationCompleted, userState);
}
private void OnRegisterDisplayOperationCompleted(object arg) {
@@ -536,11 +540,11 @@ private bool IsLocalFileSystemWebService(string url) {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void RegisterDisplayCompletedEventHandler(object sender, RegisterDisplayCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class RegisterDisplayCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -562,11 +566,11 @@ public string Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void RequiredFilesCompletedEventHandler(object sender, RequiredFilesCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class RequiredFilesCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -588,11 +592,11 @@ public string Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void GetFileCompletedEventHandler(object sender, GetFileCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class GetFileCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -614,11 +618,11 @@ public byte[] Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void ScheduleCompletedEventHandler(object sender, ScheduleCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class ScheduleCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -640,11 +644,11 @@ public string Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void BlackListCompletedEventHandler(object sender, BlackListCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class BlackListCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -666,11 +670,11 @@ public bool Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void SubmitLogCompletedEventHandler(object sender, SubmitLogCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class SubmitLogCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -692,11 +696,11 @@ public bool Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void SubmitStatsCompletedEventHandler(object sender, SubmitStatsCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class SubmitStatsCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -718,11 +722,11 @@ public bool Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void MediaInventoryCompletedEventHandler(object sender, MediaInventoryCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class MediaInventoryCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -744,11 +748,11 @@ public bool Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void GetResourceCompletedEventHandler(object sender, GetResourceCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class GetResourceCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -770,11 +774,11 @@ public string Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void NotifyStatusCompletedEventHandler(object sender, NotifyStatusCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class NotifyStatusCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
@@ -796,11 +800,11 @@ public bool Result {
}
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
public delegate void SubmitScreenShotCompletedEventHandler(object sender, SubmitScreenShotCompletedEventArgs e);
///
- [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.18408")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Web.Services", "4.0.30319.34209")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class SubmitScreenShotCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
diff --git a/Web References/xmds/Reference.map b/Web References/xmds/Reference.map
index f0d7f68d..9933f18d 100644
--- a/Web References/xmds/Reference.map
+++ b/Web References/xmds/Reference.map
@@ -1,6 +1,6 @@
-
+
\ No newline at end of file
diff --git a/Web References/xmds/xmds.wsdl b/Web References/xmds/xmds.wsdl
index 477728ce..ef22c111 100644
--- a/Web References/xmds/xmds.wsdl
+++ b/Web References/xmds/xmds.wsdl
@@ -1,271 +1,273 @@
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Register the Display with the CMS
-
-
-
-
+
+
+
+
The files required by the requesting display
-
-
-
-
+
+
+
+
Gets the file requested
-
-
-
-
+
+
+
+
Gets the schedule
-
-
-
-
+
+
+
+
Set media to be blacklisted
-
-
-
-
+
+
+
+
Submit Logging from the Client
-
-
-
-
+
+
+
+
Submit Display statistics from the Client
-
-
-
-
+
+
+
+
Report back the clients MediaInventory
-
-
-
-
+
+
+
+
Gets the file requested
-
-
-
-
+
+
+
+
Report back the current status
-
-
-
-
+
+
+
+
Submit a screen shot for a display
-
-
-
-
-
+
+
+
+
+
-
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
+
+
+
-
+
-
-
+
+
-
-
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/XiboClient.csproj b/XiboClient.csproj
index ca96c04b..3051178d 100644
--- a/XiboClient.csproj
+++ b/XiboClient.csproj
@@ -76,16 +76,28 @@
false
+
+ packages\AsyncIO.0.1.18.0\lib\net40\AsyncIO.dll
+
False
wmpdll\AxInterop.WMPLib.dll
False
+
+ packages\BouncyCastle.1.7.0\lib\Net40-Client\BouncyCastle.Crypto.dll
+
False
False
wmpdll\Interop.WMPLib.dll
+
+ packages\NetMQ.3.3.2.2\lib\net40\NetMQ.dll
+
+
+ packages\Newtonsoft.Json.7.0.1\lib\net40\Newtonsoft.Json.dll
+
@@ -103,6 +115,7 @@
+
Component
@@ -114,12 +127,17 @@
+
+
+
+
+
Form
@@ -183,6 +201,7 @@
+
SettingsSingleFileGenerator
Settings.Designer.cs
@@ -265,10 +284,10 @@
-
+
Static
Web References\xmds\
- http://172.28.128.3/xmds.php%3fv=4&WSDL
+ http://192.168.0.28/xmds.php%3fv=5&WSDL
diff --git a/XiboClient.v11.suo b/XiboClient.v11.suo
index a098a0bc..62c2f29f 100644
Binary files a/XiboClient.v11.suo and b/XiboClient.v11.suo differ
diff --git a/XmdsAgents/LogAgent.cs b/XmdsAgents/LogAgent.cs
index 46daf08f..cace906a 100644
--- a/XmdsAgents/LogAgent.cs
+++ b/XmdsAgents/LogAgent.cs
@@ -36,6 +36,14 @@ class LogAgent
private bool _forceStop = false;
private ManualResetEvent _manualReset = new ManualResetEvent(false);
+ ///
+ /// Wake Up
+ ///
+ public void WakeUp()
+ {
+ _manualReset.Set();
+ }
+
///
/// Stops the thread
///
diff --git a/XmdsAgents/RegisterAgent.cs b/XmdsAgents/RegisterAgent.cs
index 622a0b21..274aaa00 100644
--- a/XmdsAgents/RegisterAgent.cs
+++ b/XmdsAgents/RegisterAgent.cs
@@ -37,6 +37,18 @@ class RegisterAgent
private bool _forceStop = false;
private ManualResetEvent _manualReset = new ManualResetEvent(false);
+ // Events
+ public delegate void OnXmrReconfigureDelegate();
+ public event OnXmrReconfigureDelegate OnXmrReconfigure;
+
+ ///
+ /// Wake Up
+ ///
+ public void WakeUp()
+ {
+ _manualReset.Set();
+ }
+
///
/// Stops the thread
///
@@ -72,7 +84,20 @@ public void Run()
xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds;
xmds.UseDefaultCredentials = false;
- RegisterAgent.ProcessRegisterXml(xmds.RegisterDisplay(ApplicationSettings.Default.ServerKey, key.Key, ApplicationSettings.Default.DisplayName, "windows", ApplicationSettings.Default.ClientVersion, ApplicationSettings.Default.ClientCodeVersion, Environment.OSVersion.ToString(), key.MacAddress));
+ // Store the XMR address
+ string xmrAddress = ApplicationSettings.Default.XmrNetworkAddress;
+
+ RegisterAgent.ProcessRegisterXml(xmds.RegisterDisplay(
+ ApplicationSettings.Default.ServerKey,
+ key.Key,
+ ApplicationSettings.Default.DisplayName,
+ "windows",
+ ApplicationSettings.Default.ClientVersion,
+ ApplicationSettings.Default.ClientCodeVersion,
+ Environment.OSVersion.ToString(),
+ key.MacAddress,
+ key.Channel,
+ key.getXmrPublicKey()));
// Set the flag to indicate we have a connection to XMDS
ApplicationSettings.Default.XmdsLastConnection = DateTime.Now;
@@ -83,6 +108,12 @@ public void Run()
ApplicationSettings.Default.ScreenShotRequested = false;
ScreenShot.TakeAndSend();
}
+
+ // Has the XMR address changed?
+ if (xmrAddress != ApplicationSettings.Default.XmrNetworkAddress)
+ {
+ OnXmrReconfigure();
+ }
}
}
catch (WebException webEx)
@@ -145,41 +176,67 @@ public static string ProcessRegisterXml(string xml)
foreach (XmlNode node in result.DocumentElement.ChildNodes)
{
- Object value = node.InnerText;
-
- switch (node.Attributes["type"].Value)
+ // Are we a commands node?
+ if (node.Name == "commands")
{
- case "int":
- value = Convert.ToInt32(value);
- break;
-
- case "double":
- value = Convert.ToDecimal(value);
- break;
-
- case "string":
- case "word":
- value = node.InnerText;
- break;
-
- case "checkbox":
- value = (node.InnerText == "0") ? false : true;
- break;
-
- default:
- message += String.Format("Unable to set {0} with value {1}", node.Name, value) + Environment.NewLine;
- continue;
- }
+ List commands = new List();
- // Match these to settings
- try
- {
- ApplicationSettings.Default[node.Name] = Convert.ChangeType(value, ApplicationSettings.Default[node.Name].GetType());
+ foreach (XmlNode commandNode in node.ChildNodes)
+ {
+ Command command = new Command();
+ command.Code = commandNode.Name;
+ command.CommandString = commandNode.SelectSingleNode("commandString").InnerText;
+ command.Validation = commandNode.SelectSingleNode("validationString").InnerText;
+
+ commands.Add(command);
+ }
+
+ // Store commands
+ ApplicationSettings.Default.Commands = commands;
}
- catch
+ else
{
- error = true;
- message += "Invalid Configuration Option from CMS [" + node.Name + "]" + Environment.NewLine;
+ Object value = node.InnerText;
+
+ switch (node.Attributes["type"].Value)
+ {
+ case "int":
+ value = Convert.ToInt32(value);
+ break;
+
+ case "double":
+ value = Convert.ToDecimal(value);
+ break;
+
+ case "string":
+ case "word":
+ value = node.InnerText;
+ break;
+
+ case "checkbox":
+ value = (node.InnerText == "0") ? false : true;
+ break;
+
+ default:
+ message += String.Format("Unable to set {0} with value {1}", node.Name, value) + Environment.NewLine;
+ continue;
+ }
+
+ // Match these to settings
+ try
+ {
+ if (ApplicationSettings.Default[node.Name] != null)
+ {
+ value = Convert.ChangeType(value, ApplicationSettings.Default[node.Name].GetType());
+ }
+
+ ApplicationSettings.Default[node.Name] = value;
+ }
+ catch
+ {
+ error = true;
+ message += "Invalid Configuration Option from CMS [" + node.Name + "]" + Environment.NewLine;
+ }
}
}
diff --git a/XmdsAgents/RequiredFilesAgent.cs b/XmdsAgents/RequiredFilesAgent.cs
index 63a8d9af..86874d6b 100644
--- a/XmdsAgents/RequiredFilesAgent.cs
+++ b/XmdsAgents/RequiredFilesAgent.cs
@@ -96,6 +96,14 @@ public RequiredFilesAgent()
_requiredFiles = new RequiredFiles();
}
+ ///
+ /// Wake Up
+ ///
+ public void WakeUp()
+ {
+ _manualReset.Set();
+ }
+
///
/// Stops the thread
///
diff --git a/XmdsAgents/ScheduleAgent.cs b/XmdsAgents/ScheduleAgent.cs
index 20998677..fdd7ee61 100644
--- a/XmdsAgents/ScheduleAgent.cs
+++ b/XmdsAgents/ScheduleAgent.cs
@@ -87,6 +87,14 @@ public ClientInfo ClientInfoForm
}
private ClientInfo _clientInfoForm;
+ ///
+ /// Wake Up
+ ///
+ public void WakeUp()
+ {
+ _manualReset.Set();
+ }
+
///
/// Stops the thread
///
diff --git a/app.config b/app.config
index b21fe50b..c0003477 100644
--- a/app.config
+++ b/app.config
@@ -1,10 +1,17 @@
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/bin/x86/Release/Xibo.scr b/bin/x86/Release/Xibo.scr
index f6ec0aab..d02af6db 100644
Binary files a/bin/x86/Release/Xibo.scr and b/bin/x86/Release/Xibo.scr differ
diff --git a/default.config.xml b/default.config.xml
index cd468504..73df049f 100644
--- a/default.config.xml
+++ b/default.config.xml
@@ -51,4 +51,5 @@
0
0
0
+
\ No newline at end of file
diff --git a/packages.config b/packages.config
new file mode 100644
index 00000000..a13b0fb0
--- /dev/null
+++ b/packages.config
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file