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.R23SignageClient_xmds_xmds; statusXmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, "{\"lastCommandSuccess\":" + success + "}"); } }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { try { // If we are restarting, reset _manualReset.Reset(); HardwareKey key = new HardwareKey(); Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Woken and Lock Obtained"), LogType.Info.ToString()); using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; 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)); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; // Do we need to send a screenshot? if (ApplicationSettings.Default.ScreenShotRequested) { ApplicationSettings.Default.ScreenShotRequested = false; ScreenShot.TakeAndSend(); } } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RegisterAgent - Run", "WebException in Run: " + webEx.Message), LogType.Error.ToString()); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("LogAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { try { // If we are restarting, reset _manualReset.Reset(); HardwareKey key = new HardwareKey(); Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Woken and Lock Obtained"), LogType.Info.ToString()); using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.R23SignageClient_xmds_xmds; xmds.UseDefaultCredentials = false; // Log ProcessFiles(xmds, key.Key, ApplicationSettings.Default.LogLocation); // Stat ProcessFiles(xmds, key.Key, ApplicationSettings.Default.StatsLogFile); } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("LogAgent - Run", "WebException in Run: " + webEx.Message), LogType.Error.ToString()); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("LogAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("LogAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
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 + "&method=submitScreenshot"; screenShotXmds.SubmitScreenShotCompleted += screenShotXmds_SubmitScreenShotCompleted; screenShotXmds.SubmitScreenShotAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, bytes); } } }
private void ProcessFiles(xmds.xmds xmds, string key, string type) { // Get a list of all the log files waiting to be sent to XMDS. string[] logFiles = Directory.GetFiles(ApplicationSettings.Default.LibraryPath, "*" + type + "*"); // Track processed files int filesProcessed = 0; // Loop through each file foreach (string fileName in logFiles) { // Only process as many files in one go as configured if (filesProcessed >= ApplicationSettings.Default.MaxLogFileUploads) { break; } // construct the log message StringBuilder builder = new StringBuilder(); builder.Append("<log>"); foreach (string entry in File.ReadAllLines(fileName)) { builder.Append(entry); } builder.Append("</log>"); if (type == ApplicationSettings.Default.StatsLogFile) { xmds.SubmitStats(ApplicationSettings.Default.ServerKey, key, builder.ToString()); } else { xmds.SubmitLog(ApplicationSettings.Default.ServerKey, key, builder.ToString()); } // Delete the file we are on File.Delete(fileName); // Increment files processed filesProcessed++; } }
private void reportStorage() { // Use Drive Info foreach (DriveInfo drive in DriveInfo.GetDrives()) { if (drive.IsReady && ApplicationSettings.Default.LibraryPath.Contains(drive.RootDirectory.FullName)) { using (xmds.xmds xmds = new xmds.xmds()) { string status = "{\"availableSpace\":\"" + drive.TotalFreeSpace + "\", \"totalSpace\":\"" + drive.TotalSize + "\"}"; xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = false; xmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, status); } break; } } }
public void notifyStatusToXmds() { try { StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); using (JsonWriter writer = new JsonTextWriter(sw)) { writer.Formatting = Formatting.None; writer.WriteStartObject(); writer.WritePropertyName("lastActivity"); writer.WriteValue(DateTime.Now.ToString()); writer.WritePropertyName("applicationState"); writer.WriteValue(Thread.State.ToString()); writer.WritePropertyName("xmdsLastActivity"); writer.WriteValue(ApplicationSettings.Default.XmdsLastConnection.ToString()); writer.WritePropertyName("scheduleStatus"); writer.WriteValue(scheduleStatusLabel.Text); writer.WritePropertyName("requiredFilesStatus"); writer.WriteValue(requiredFilesStatus.Text); writer.WritePropertyName("xmrStatus"); writer.WriteValue(xmrStatus.Text); writer.WriteEndObject(); } // Notify the state of the command (success or failure) using (xmds.xmds statusXmds = new xmds.xmds()) { statusXmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=notifyStatus"; statusXmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, sb.ToString()); } } catch (Exception e) { Trace.WriteLine(new LogMessage("ClientInfo - notifyStatusToXmds", "Failed to notify status to XMDS. e = " + e.Message), LogType.Error.ToString()); } }
private void reportStorage() { StringBuilder sb = new StringBuilder(); StringWriter sw = new StringWriter(sb); using (JsonWriter writer = new JsonTextWriter(sw)) { writer.Formatting = Newtonsoft.Json.Formatting.None; writer.WriteStartObject(); writer.WritePropertyName("deviceName"); writer.WriteValue(Environment.MachineName); // Use Drive Info foreach (DriveInfo drive in DriveInfo.GetDrives()) { if (drive.IsReady && ApplicationSettings.Default.LibraryPath.Contains(drive.RootDirectory.FullName)) { writer.WritePropertyName("availableSpace"); writer.WriteValue(drive.TotalFreeSpace); writer.WritePropertyName("totalSpace"); writer.WriteValue(drive.TotalSize); break; } } writer.WriteEndObject(); // Report using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=notifyStatus"; xmds.UseDefaultCredentials = false; xmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, sb.ToString()); } } }
public static void TakeAndSend() { Rectangle bounds; // Override the default size if necessary if (ApplicationSettings.Default.SizeX != 0) { bounds = new Rectangle((int)ApplicationSettings.Default.OffsetX, (int)ApplicationSettings.Default.OffsetY, (int)ApplicationSettings.Default.SizeX, (int)ApplicationSettings.Default.SizeY); } else { bounds = new Rectangle(0, 0, SystemInformation.PrimaryMonitorSize.Width, SystemInformation.PrimaryMonitorSize.Height); } using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height)) { using (Graphics g = Graphics.FromImage(bitmap)) { Point p = new Point(bounds.X, bounds.Y); g.CopyFromScreen(bounds.X, bounds.Y, 0, 0, bounds.Size, CopyPixelOperation.SourceCopy); } 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); } } } }
/// <summary> /// Adds a media item to the Black list. Adds Locally and to the WebService /// </summary> /// <param name="id">The Media ID</param> /// <param name="type">The BlackListType, either All (to blacklist on all displays) or Single (to blacklist only on this display)</param> /// <param name="reason">The reason for the blacklist</param> public void Add(string id, BlackListType type, string reason) { // Do some validation if (reason == "") { reason = "No reason provided"; } int mediaId; if (!int.TryParse(id, out mediaId)) { System.Diagnostics.Trace.WriteLine(String.Format("Currently can only append Integer media types. Id {0}", id), "BlackList - Add"); } // Send to the webservice xmds1 = new XiboClient.xmds.xmds(); xmds1.BlackListCompleted += new XiboClient.xmds.BlackListCompletedEventHandler(xmds1_BlackListCompleted); xmds1.BlackListAsync(ApplicationSettings.Default.ServerKey, hardwareKey.Key, mediaId, type.ToString(), reason, ApplicationSettings.Default.Version); // Add to the local list AddLocal(id); }
/// <summary> /// Schedule Agent /// </summary> private void scheduleAgent() { try { // If we are restarting, reset _manualReset.Reset(); Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Thread Woken and Lock Obtained"), LogType.Audit.ToString()); _clientInfoForm.ScheduleStatus = "Running: Get Data from Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=schedule"; xmds.UseDefaultCredentials = false; string scheduleXml = xmds.Schedule(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; _clientInfoForm.ScheduleStatus = "Running: Data Received"; // Hash of the result string md5NewSchedule = Hashes.MD5(scheduleXml); string md5CurrentSchedule = Hashes.MD5(ScheduleManager.GetScheduleXmlString(_scheduleLocation)); // Compare the results of the HASH if (md5CurrentSchedule != md5NewSchedule) { Trace.WriteLine(new LogMessage("Schedule Agent - Run", "Received new schedule")); _clientInfoForm.ScheduleStatus = "Running: New Schedule Received"; // Write the result to the schedule xml location ScheduleManager.WriteScheduleXmlToDisk(_scheduleLocation, scheduleXml); // Indicate to the schedule manager that it should read the XML file _scheduleManager.RefreshSchedule = true; } _clientInfoForm.ScheduleStatus = "Sleeping"; } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); _clientInfoForm.ScheduleStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); _clientInfoForm.ScheduleStatus = "Error. " + ex.Message; } }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { try { // If we are restarting, reset _manualReset.Reset(); Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Thread Woken and Lock Obtained"), LogType.Info.ToString()); _clientInfoForm.ScheduleStatus = "Running: Get Data from Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.R23SignageClient_xmds_xmds; xmds.UseDefaultCredentials = false; string scheduleXml = xmds.Schedule(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; _clientInfoForm.ScheduleStatus = "Running: Data Received"; // Hash of the result string md5NewSchedule = Hashes.MD5(scheduleXml); string md5CurrentSchedule = Hashes.MD5(ScheduleManager.GetScheduleXmlString(_scheduleLocation)); // Compare the results of the HASH if (md5CurrentSchedule != md5NewSchedule) { Trace.WriteLine(new LogMessage("Schedule Agent - Run", "Received new schedule")); _clientInfoForm.ScheduleStatus = "Running: New Schedule Received"; // Write the result to the schedule xml location ScheduleManager.WriteScheduleXmlToDisk(_scheduleLocation, scheduleXml); // Indicate to the schedule manager that it should read the XML file _scheduleManager.RefreshSchedule = true; } _clientInfoForm.ScheduleStatus = "Sleeping"; } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "WebException in Run: " + webEx.Message), LogType.Error.ToString()); _clientInfoForm.ScheduleStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); _clientInfoForm.ScheduleStatus = "Error. " + ex.Message; } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("LogAgent - Run", "Thread Started"), LogType.Info.ToString()); int retryAfterSeconds = 0; while (!_forceStop) { lock (_locker) { try { // If we are restarting, reset _manualReset.Reset(); // Reset backOff retryAfterSeconds = 0; HardwareKey key = new HardwareKey(); Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Woken and Lock Obtained"), LogType.Audit.ToString()); using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=submitLog"; xmds.UseDefaultCredentials = false; // Log ProcessFiles(xmds, key.Key, ApplicationSettings.Default.LogLocation); } } catch (WebException webEx) when(webEx.Response is HttpWebResponse httpWebResponse && (int)httpWebResponse.StatusCode == 429) { // Get the header for how long we ought to wait retryAfterSeconds = webEx.Response.Headers["Retry-After"] != null?int.Parse(webEx.Response.Headers["Retry-After"]) : 120; // Log it. Trace.WriteLine(new LogMessage("LogAgent", "Run: 429 received, waiting for " + retryAfterSeconds + " seconds."), LogType.Info.ToString()); } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("LogAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("LogAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); } } if (retryAfterSeconds > 0) { // Sleep this thread until we've fulfilled our try after _manualReset.WaitOne(retryAfterSeconds * 1000); } else { // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } } Trace.WriteLine(new LogMessage("LogAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
private void reportStorage() { // Use Drive Info foreach (DriveInfo drive in DriveInfo.GetDrives()) { if (drive.IsReady && ApplicationSettings.Default.LibraryPath.Contains(drive.RootDirectory.FullName)) { using (xmds.xmds xmds = new xmds.xmds()) { string status = "{\"availableSpace\":\"" + drive.TotalFreeSpace + "\", \"totalSpace\":\"" + drive.TotalSize + "\"}"; xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.R23SignageClient_xmds_xmds; xmds.UseDefaultCredentials = false; xmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, status); } break; } } }
/// <summary> /// Schedule Agent /// </summary> private void scheduleAgent() { try { if (!ShouldCheckSchedule()) { ClientInfo.Instance.ScheduleStatus = "Sleeping: last check was not required."; return; } Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Thread Woken and Lock Obtained"), LogType.Audit.ToString()); ClientInfo.Instance.ScheduleStatus = "Running: Get Data from Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=schedule"; xmds.UseDefaultCredentials = false; string scheduleXml = xmds.Schedule(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; ClientInfo.Instance.ScheduleStatus = "Running: Data Received"; // Calculate and store a CRC32 _lastCheckSchedule = Crc32Algorithm.Compute(Encoding.UTF8.GetBytes(scheduleXml)).ToString(); // Hash of the result // TODO: we can probably remove this at some point in the future, given later CMS instances output CRC32's to indicate whether // the schedule has changed. string md5NewSchedule = Hashes.MD5(scheduleXml); string md5CurrentSchedule = Hashes.MD5(ScheduleManager.GetScheduleXmlString(_scheduleLocation)); // Compare the results of the HASH if (md5CurrentSchedule != md5NewSchedule) { Trace.WriteLine(new LogMessage("Schedule Agent - Run", "Received new schedule")); ClientInfo.Instance.ScheduleStatus = "Running: New Schedule Received"; // Write the result to the schedule xml location ScheduleManager.WriteScheduleXmlToDisk(_scheduleLocation, scheduleXml); // Indicate to the schedule manager that it should read the XML file _scheduleManager.RefreshSchedule = true; } ClientInfo.Instance.ScheduleStatus = "Sleeping"; } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); ClientInfo.Instance.ScheduleStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("ScheduleAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); ClientInfo.Instance.ScheduleStatus = "Error. " + ex.Message; } }
/// <summary> /// Report the timezone to XMDS /// </summary> private void NotifyStatus() { StringBuilder sb = new StringBuilder(); using (StringWriter sw = new StringWriter(sb)) using (JsonWriter writer = new JsonTextWriter(sw)) { writer.Formatting = Newtonsoft.Json.Formatting.None; writer.WriteStartObject(); writer.WritePropertyName("deviceName"); writer.WriteValue(Environment.MachineName); writer.WritePropertyName("width"); writer.WriteValue(ClientInfo.Instance.PlayerWidth); writer.WritePropertyName("height"); writer.WriteValue(ClientInfo.Instance.PlayerHeight); // GeoLocation if (ClientInfo.Instance.CurrentGeoLocation != null && !ClientInfo.Instance.CurrentGeoLocation.IsUnknown) { writer.WritePropertyName("latitude"); writer.WriteValue(ClientInfo.Instance.CurrentGeoLocation.Latitude); writer.WritePropertyName("longitude"); writer.WriteValue(ClientInfo.Instance.CurrentGeoLocation.Longitude); } try { // Use Drive Info foreach (DriveInfo drive in DriveInfo.GetDrives()) { if (drive.IsReady && ApplicationSettings.Default.LibraryPath.Contains(drive.RootDirectory.FullName)) { writer.WritePropertyName("availableSpace"); writer.WriteValue(drive.TotalFreeSpace); writer.WritePropertyName("totalSpace"); writer.WriteValue(drive.TotalSize); break; } } } catch { Trace.WriteLine(new LogMessage("NotifyStatus", "Unable to get drive info"), LogType.Info.ToString()); } // Timezone // we only do the timezone if it is currently empty, otherwise we stick with whatever has been set. if (string.IsNullOrEmpty(ApplicationSettings.Default.DisplayTimeZone)) { writer.WritePropertyName("timeZone"); writer.WriteValue(WindowsToIana(TimeZone.CurrentTimeZone.StandardName)); } // Finish writer.WriteEndObject(); // Report using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=notifyStatus"; xmds.UseDefaultCredentials = false; xmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, sb.ToString()); } } sb.Clear(); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("StatAgent", "Run: Thread Started"), LogType.Info.ToString()); // Assume no backlog when we first start out. bool isBacklog = false; int retryAfterSeconds = 0; int countBacklogBatches = 0; int processing = 0; while (!_forceStop) { lock (_locker) { // What is out processing flag? processing = (new Random()).Next(1, 1000); try { // If we are restarting, reset _manualReset.Reset(); // Reset backOff retryAfterSeconds = 0; // How many records do we have to send? int recordsReady = StatManager.Instance.TotalReady(); // Does this mean we're in a backlog situation? isBacklog = (recordsReady >= 500); // Check to see if we have anything to send if (StatManager.Instance.MarkRecordsForSend(processing, isBacklog)) { HardwareKey key = new HardwareKey(); Trace.WriteLine(new LogMessage("StatAgent", "Run: Thread Woken and Lock Obtained, Key: " + processing), LogType.Audit.ToString()); using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=submitStats"; xmds.UseDefaultCredentials = false; // Get the starts we've marked to process as XML. xmds.SubmitStats(ApplicationSettings.Default.ServerKey, key.Key, StatManager.Instance.GetXmlForSend(processing)); } // Update the last send date to indicate we've just done so StatManager.Instance.LastSendDate = DateTime.Now; // Remove the ones we've just sent StatManager.Instance.DeleteSent(processing); } } catch (WebException webEx) when(webEx.Response is HttpWebResponse httpWebResponse && (int)httpWebResponse.StatusCode == 429) { // We got a backoff, so none of those records are processed. StatManager.Instance.UnmarkRecordsForSend(processing); // Get the header for how long we ought to wait retryAfterSeconds = webEx.Response.Headers["Retry-After"] != null?int.Parse(webEx.Response.Headers["Retry-After"]) : 120; // Log it. Trace.WriteLine(new LogMessage("StatAgent", "Run: 429 received, waiting for " + retryAfterSeconds + " seconds."), LogType.Info.ToString()); } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("StatAgent", "Run: WebException in Run: " + webEx.Message), LogType.Info.ToString()); // Something went wrong sending those records, set them to be reprocessed StatManager.Instance.UnmarkRecordsForSend(processing); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("StatAgent", "Run: Exception in Run: " + ex.Message), LogType.Error.ToString()); // Something went wrong sending those records, set them to be reprocessed StatManager.Instance.UnmarkRecordsForSend(processing); } } if (retryAfterSeconds > 0) { // Sleep this thread until we've fulfilled our try after _manualReset.WaitOne(retryAfterSeconds * 1000); } else if (isBacklog) { // We've just completed a send in backlog mode, so add to batches. countBacklogBatches++; // How many batches have we sent without a cooldown? if (countBacklogBatches > 2) { // Reset batches countBacklogBatches = 0; // Come back in 30 seconds _manualReset.WaitOne(30000); } else { // Come back much more quickly (10 seconds) _manualReset.WaitOne(10000); } } else { // Reset batches countBacklogBatches = 0; // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } } Trace.WriteLine(new LogMessage("StatAgent", "Run: Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Run Thread /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { if (ApplicationSettings.Default.InDownloadWindow) { try { // If we are restarting, reset _manualReset.Reset(); int filesToDownload = _requiredFiles.FilesDownloading; // If we are currently downloading something, we have to wait if (filesToDownload > 0) { _clientInfoForm.RequiredFilesStatus = string.Format("Waiting: {0} Active Downloads", filesToDownload.ToString()); Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Currently Downloading Files, skipping collect"), LogType.Audit.ToString()); } else { _clientInfoForm.RequiredFilesStatus = "Running: Requesting connection to Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = false; // Get required files from XMDS string requiredFilesXml = xmds.RequiredFiles(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; _clientInfoForm.RequiredFilesStatus = "Running: Data received from Xibo Server"; // Load the XML file RF call XmlDocument xml = new XmlDocument(); xml.LoadXml(requiredFilesXml); // Create a required files object and set it to contain the RF returned this tick _requiredFiles = new RequiredFiles(); _requiredFiles.CurrentCacheManager = _cacheManager; _requiredFiles.RequiredFilesXml = xml; // List of Threads to start // TODO: Track these threads so that we can abort them if the application closes List <Thread> threadsToStart = new List <Thread>(); // Required files now contains a list of files to download (this will be updated by the various worker threads) foreach (RequiredFile fileToDownload in _requiredFiles.RequiredFileList) { // Skip downloaded files if (fileToDownload.Complete) { continue; } // Spawn a thread to download this file. FileAgent fileAgent = new FileAgent(); fileAgent.FileDownloadLimit = _fileDownloadLimit; fileAgent.HardwareKey = _hardwareKey; fileAgent.RequiredFiles = _requiredFiles; fileAgent.RequiredFileId = fileToDownload.Id; fileAgent.RequiredFileType = fileToDownload.FileType; fileAgent.OnComplete += new FileAgent.OnCompleteDelegate(fileAgent_OnComplete); fileAgent.OnPartComplete += new FileAgent.OnPartCompleteDelegate(fileAgent_OnPartComplete); // Create the thread and add it to the list of threads to start Thread thread = new Thread(new ThreadStart(fileAgent.Run)); thread.Name = "FileAgent_" + fileToDownload.FileType + "_Id_" + fileToDownload.Id.ToString(); threadsToStart.Add(thread); } // Start the threads after we have built them all - otherwise they will modify the collection we // are iterating over. foreach (Thread thread in threadsToStart) { thread.Start(); } // Report what we are doing back to MediaInventory _requiredFiles.ReportInventory(); // Write Required Files _requiredFiles.WriteRequiredFiles(); // Write the Cache Manager to Disk _cacheManager.WriteCacheManager(); // Report the storage usage reportStorage(); // Set the status on the client info screen if (threadsToStart.Count == 0) { _clientInfoForm.RequiredFilesStatus = "Sleeping (inside download window)"; } else { _clientInfoForm.RequiredFilesStatus = string.Format("{0} files to download", threadsToStart.Count.ToString()); } _clientInfoForm.UpdateRequiredFiles(RequiredFilesString()); } } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + ex.Message; } } else { _clientInfoForm.RequiredFilesStatus = string.Format("Outside Download Window {0} - {1}", ApplicationSettings.Default.DownloadStartWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture), ApplicationSettings.Default.DownloadEndWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture)); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("FileAgent - Run", "Thread Started"), LogType.Info.ToString()); // Get the required file id from the list of required files. RequiredFile file = _requiredFiles.GetRequiredFile(_requiredFileId, _requiredFileType); // Set downloading to be true file.Downloading = true; // Wait for the Semaphore lock to become available _fileDownloadLimit.WaitOne(); try { Trace.WriteLine(new LogMessage("FileAgent - Run", "Thread alive and Lock Obtained"), LogType.Info.ToString()); if (file.FileType == "resource") { // Download using GetResource using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = Settings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = true; string result = xmds.GetResource(Settings.Default.ServerKey, Settings.Default.hardwareKey, file.LayoutId, file.RegionId, file.MediaId, Settings.Default.Version); // Write the result to disk using (StreamWriter sw = new StreamWriter(File.Open(Settings.Default.LibraryPath + @"\" + file.Path, FileMode.Create, FileAccess.Write, FileShare.Read))) { sw.Write(result); sw.Close(); } // File completed file.Downloading = false; file.Complete = true; } } else { while (!file.Complete) { byte[] getFileReturn; // Call XMDS GetFile using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = Settings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = false; getFileReturn = xmds.GetFile(Settings.Default.ServerKey, _hardwareKey, file.Path, file.FileType, file.ChunkOffset, file.ChunkSize, Settings.Default.Version); } // Set the flag to indicate we have a connection to XMDS Settings.Default.XmdsLastConnection = DateTime.Now; if (file.FileType == "layout") { // Decode this byte[] into a string and stick it in the file. string layoutXml = Encoding.UTF8.GetString(getFileReturn); // Full file is downloaded using (StreamWriter sw = new StreamWriter(File.Open(Settings.Default.LibraryPath + @"\" + file.Path, FileMode.Create, FileAccess.Write, FileShare.Read))) { sw.Write(layoutXml); sw.Close(); } file.Complete = true; } else { // Media file // Need to write to the file - in append mode using (FileStream fs = new FileStream(Settings.Default.LibraryPath + @"\" + file.Path, FileMode.Append, FileAccess.Write)) { fs.Write(getFileReturn, 0, getFileReturn.Length); fs.Close(); } // Increment the offset by the amount we just asked for file.ChunkOffset = file.ChunkOffset + file.ChunkSize; // Has the offset reached the total size? if (file.Size > file.ChunkOffset) { int remaining = file.Size - file.ChunkOffset; // There is still more to come if (remaining < file.ChunkSize) { // Get the remaining file.ChunkSize = remaining; } // Part is complete OnPartComplete(file.Id); } else { // File complete file.Complete = true; } } getFileReturn = null; } // File completed file.Downloading = false; // Check MD5 string md5 = _requiredFiles.CurrentCacheManager.GetMD5(file.Path); if (file.Md5 == md5) { // Mark it as complete _requiredFiles.MarkComplete(_requiredFileId, file.Md5); // Add it to the cache manager _requiredFiles.CurrentCacheManager.Add(file.Path, file.Md5); Trace.WriteLine(new LogMessage("FileAgent - Run", "File Downloaded Successfully. " + file.Path), LogType.Info.ToString()); } else { // Just error - we will pick it up again the next time we download Trace.WriteLine(new LogMessage("FileAgent - Run", "Downloaded file failed MD5 check. Calculated [" + md5 + "] & XMDS [ " + file.Md5 + "] . " + file.Path), LogType.Error.ToString()); } } // Inform the Player thread that a file has been modified. OnComplete(file.Id, file.FileType); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("FileAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); // Mark as not downloading file.Downloading = false; } // Release the Semaphore Trace.WriteLine(new LogMessage("FileAgent - Run", "Releasing Lock"), LogType.Info.ToString()); _fileDownloadLimit.Release(); }
public override void RenderMedia(double position) { if (!string.IsNullOrEmpty(_code)) { // Stored command bool success; try { Command command = Command.GetByCode(_code); success = command.Run(); } catch (Exception e) { Trace.WriteLine(new LogMessage("ScheduleManager - Run", "Cannot 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 + "&method=notifyStatus"; statusXmds.NotifyStatusAsync(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, "{\"lastCommandSuccess\":" + success + "}"); } } else { // shell command // Is this module enabled? if (ApplicationSettings.Default.EnableShellCommands) { // Check to see if we have an allow list if (!string.IsNullOrEmpty(ApplicationSettings.Default.ShellCommandAllowList)) { // 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) { 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()); } } else { // All commands are allowed ExecuteShellCommand(); } } else { Trace.WriteLine(new LogMessage("ShellCommand - RenderMedia", "Shell Commands are disabled"), LogType.Error.ToString()); } } // All shell commands have a duration of 1 base.RenderMedia(position); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("FileAgent - Run", "Thread Started"), LogType.Audit.ToString()); // Get the required file id from the list of required files. RequiredFile file = _requiredFiles.GetRequiredFile(_requiredFileId, _requiredFileType); // Set downloading to be true file.Downloading = true; // Wait for the Semaphore lock to become available _fileDownloadLimit.WaitOne(); try { Trace.WriteLine(new LogMessage("FileAgent - Run", "Thread alive and Lock Obtained"), LogType.Audit.ToString()); if (file.FileType == "resource") { // Download using XMDS GetResource using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = true; string result = xmds.GetResource(ApplicationSettings.Default.ServerKey, ApplicationSettings.Default.HardwareKey, file.LayoutId, file.RegionId, file.MediaId); // Write the result to disk using (FileStream fileStream = File.Open(ApplicationSettings.Default.LibraryPath + @"\" + file.SaveAs, FileMode.Create, FileAccess.Write, FileShare.Read)) { using (StreamWriter sw = new StreamWriter(fileStream)) { sw.Write(result); sw.Close(); } } // File completed file.Downloading = false; file.Complete = true; } } else if (file.FileType == "media" && file.Http) { // Download using HTTP and the rf.Path using (WebClient wc = new WebClient()) { wc.DownloadFile(file.Path, ApplicationSettings.Default.LibraryPath + @"\" + file.SaveAs); } // File completed file.Downloading = false; // Check MD5 string md5 = _requiredFiles.CurrentCacheManager.GetMD5(file.SaveAs); if (file.Md5 == md5) { // Mark it as complete _requiredFiles.MarkComplete(_requiredFileId, file.Md5); // Add it to the cache manager _requiredFiles.CurrentCacheManager.Add(file.SaveAs, file.Md5); Trace.WriteLine(new LogMessage("FileAgent - Run", "File Downloaded Successfully. " + file.SaveAs), LogType.Info.ToString()); } else { // Just error - we will pick it up again the next time we download Trace.WriteLine(new LogMessage("FileAgent - Run", "Downloaded file failed MD5 check. Calculated [" + md5 + "] & XMDS [ " + file.Md5 + "] . " + file.SaveAs), LogType.Info.ToString()); } } else { // Download using XMDS GetFile while (!file.Complete) { byte[] getFileReturn; // Call XMDS GetFile using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds; xmds.UseDefaultCredentials = false; getFileReturn = xmds.GetFile(ApplicationSettings.Default.ServerKey, _hardwareKey, file.Id, file.FileType, file.ChunkOffset, file.ChunkSize); } // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; if (file.FileType == "layout") { // Decode this byte[] into a string and stick it in the file. string layoutXml = Encoding.UTF8.GetString(getFileReturn); // Full file is downloaded using (FileStream fileStream = File.Open(ApplicationSettings.Default.LibraryPath + @"\" + file.SaveAs, FileMode.Create, FileAccess.Write, FileShare.Read)) { using (StreamWriter sw = new StreamWriter(fileStream)) { sw.Write(layoutXml); sw.Close(); } } file.Complete = true; } else { // Media file // Need to write to the file - in append mode using (FileStream fs = new FileStream(ApplicationSettings.Default.LibraryPath + @"\" + file.Path, FileMode.Append, FileAccess.Write)) { fs.Write(getFileReturn, 0, getFileReturn.Length); fs.Close(); } // Increment the offset by the amount we just asked for file.ChunkOffset = file.ChunkOffset + file.ChunkSize; // Has the offset reached the total size? if (file.Size > file.ChunkOffset) { double remaining = file.Size - file.ChunkOffset; // There is still more to come if (remaining < file.ChunkSize) { // Get the remaining file.ChunkSize = remaining; } // Part is complete OnPartComplete(file.Id); } else { // File complete file.Complete = true; } } getFileReturn = null; } // File completed file.Downloading = false; // Check MD5 string md5 = _requiredFiles.CurrentCacheManager.GetMD5(file.SaveAs); if (file.Md5 == md5) { // Mark it as complete _requiredFiles.MarkComplete(_requiredFileId, file.Md5); // Add it to the cache manager _requiredFiles.CurrentCacheManager.Add(file.SaveAs, file.Md5); Trace.WriteLine(new LogMessage("FileAgent - Run", "File Downloaded Successfully. " + file.SaveAs), LogType.Info.ToString()); } else { // Just error - we will pick it up again the next time we download Trace.WriteLine(new LogMessage("FileAgent - Run", "Downloaded file failed MD5 check. Calculated [" + md5 + "] & XMDS [ " + file.Md5 + "] . " + file.SaveAs), LogType.Info.ToString()); } } // Inform the Player thread that a file has been modified. OnComplete(file.Id, file.FileType); } catch (WebException webEx) { // Remove from the cache manager _requiredFiles.CurrentCacheManager.Remove(file.SaveAs); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("FileAgent - Run", "Web Exception in Run: " + webEx.Message), LogType.Info.ToString()); // Mark as not downloading file.Downloading = false; } catch (Exception ex) { // Remove from the cache manager _requiredFiles.CurrentCacheManager.Remove(file.SaveAs); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("FileAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); // Mark as not downloading file.Downloading = false; } // Release the Semaphore Trace.WriteLine(new LogMessage("FileAgent - Run", "Releasing Lock"), LogType.Audit.ToString()); _fileDownloadLimit.Release(); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { try { // If we are restarting, reset _manualReset.Reset(); HardwareKey key = new HardwareKey(); Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Woken and Lock Obtained"), LogType.Info.ToString()); using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=registerDisplay"; xmds.UseDefaultCredentials = false; // 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; // Has the XMR address changed? if (xmrAddress != ApplicationSettings.Default.XmrNetworkAddress) { OnXmrReconfigure(); } // Is the timezone empty? if (string.IsNullOrEmpty(ApplicationSettings.Default.DisplayTimeZone)) { reportTimezone(); } } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RegisterAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Exception in Run: " + ex.Message), LogType.Info.ToString()); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Run Thread /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Started"), LogType.Info.ToString()); while (!_forceStop) { lock (_locker) { if (ApplicationSettings.Default.InDownloadWindow) { try { // If we are restarting, reset _manualReset.Reset(); int filesToDownload = _requiredFiles.FilesDownloading; // If we are currently downloading something, we have to wait if (filesToDownload > 0) { _clientInfoForm.RequiredFilesStatus = string.Format("Waiting: {0} Active Downloads", filesToDownload.ToString()); Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Currently Downloading Files, skipping collect"), LogType.Info.ToString()); } else { _clientInfoForm.RequiredFilesStatus = "Running: Requesting connection to Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.R23SignageClient_xmds_xmds; xmds.UseDefaultCredentials = false; // Get required files from XMDS string requiredFilesXml = xmds.RequiredFiles(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; _clientInfoForm.RequiredFilesStatus = "Running: Data received from Xibo Server"; // Load the XML file RF call XmlDocument xml = new XmlDocument(); xml.LoadXml(requiredFilesXml); // Create a required files object and set it to contain the RF returned this tick _requiredFiles = new RequiredFiles(); _requiredFiles.CurrentCacheManager = _cacheManager; _requiredFiles.RequiredFilesXml = xml; // List of Threads to start // TODO: Track these threads so that we can abort them if the application closes List<Thread> threadsToStart = new List<Thread>(); // Required files now contains a list of files to download (this will be updated by the various worker threads) foreach (RequiredFile fileToDownload in _requiredFiles.RequiredFileList) { // Skip downloaded files if (fileToDownload.Complete) continue; // Spawn a thread to download this file. FileAgent fileAgent = new FileAgent(); fileAgent.FileDownloadLimit = _fileDownloadLimit; fileAgent.HardwareKey = _hardwareKey; fileAgent.RequiredFiles = _requiredFiles; fileAgent.RequiredFileId = fileToDownload.Id; fileAgent.RequiredFileType = fileToDownload.FileType; fileAgent.OnComplete += new FileAgent.OnCompleteDelegate(fileAgent_OnComplete); fileAgent.OnPartComplete += new FileAgent.OnPartCompleteDelegate(fileAgent_OnPartComplete); // Create the thread and add it to the list of threads to start Thread thread = new Thread(new ThreadStart(fileAgent.Run)); thread.Name = "FileAgent_" + fileToDownload.FileType + "_Id_" + fileToDownload.Id.ToString(); threadsToStart.Add(thread); } // Start the threads after we have built them all - otherwise they will modify the collection we // are iterating over. foreach (Thread thread in threadsToStart) thread.Start(); // Report what we are doing back to MediaInventory _requiredFiles.ReportInventory(); // Write Required Files _requiredFiles.WriteRequiredFiles(); // Write the Cache Manager to Disk _cacheManager.WriteCacheManager(); // Report the storage usage reportStorage(); // Set the status on the client info screen if (threadsToStart.Count == 0) _clientInfoForm.RequiredFilesStatus = "Sleeping (inside download window)"; else _clientInfoForm.RequiredFilesStatus = string.Format("{0} files to download", threadsToStart.Count.ToString()); _clientInfoForm.UpdateRequiredFiles(RequiredFilesString()); } } } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "WebException in Run: " + webEx.Message), LogType.Error.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); _clientInfoForm.RequiredFilesStatus = "Error: " + ex.Message; } } else { _clientInfoForm.RequiredFilesStatus = string.Format("Outside Download Window {0} - {1}", ApplicationSettings.Default.DownloadStartWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture), ApplicationSettings.Default.DownloadEndWindowTime.ToString("HH:mm", CultureInfo.InvariantCulture)); } } // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Runs the agent /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Started"), LogType.Info.ToString()); int retryAfterSeconds = 0; while (!_forceStop) { lock (_locker) { try { // If we are restarting, reset _manualReset.Reset(); // Reset backOff retryAfterSeconds = 0; HardwareKey key = new HardwareKey(); Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Woken and Lock Obtained"), LogType.Info.ToString()); using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=registerDisplay"; xmds.UseDefaultCredentials = false; // Store the XMR address string xmrAddress = ApplicationSettings.Default.XmrNetworkAddress; RegisterAgent.ProcessRegisterXml(callRegister(xmds, key)); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; // Has the XMR address changed? if (xmrAddress != ApplicationSettings.Default.XmrNetworkAddress) { OnXmrReconfigure(); } // Notify Status NotifyStatus(); // Have we been asked to move CMS instance? // CMS MOVE // -------- if (!string.IsNullOrEmpty(ApplicationSettings.Default.NewCmsAddress) && !string.IsNullOrEmpty(ApplicationSettings.Default.NewCmsKey) && ApplicationSettings.Default.NewCmsAddress != ApplicationSettings.Default.ServerUri ) { // Make a call using the new details, and see if it works. string oldUri = ApplicationSettings.Default.ServerUri; string oldKey = ApplicationSettings.Default.ServerKey; ApplicationSettings.Default.ServerUri = ApplicationSettings.Default.NewCmsAddress; ApplicationSettings.Default.ServerKey = ApplicationSettings.Default.NewCmsKey; Trace.WriteLine(new LogMessage("RegisterAgent - Run", "We have been asked to move to a new CMS. " + ApplicationSettings.Default.NewCmsAddress), LogType.Info.ToString()); // Try it and see. try { xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=registerDisplay"; string xml = callRegister(xmds, key); // If that worked (no errors), update our settings ApplicationSettings.Default.NewCmsAddress = ""; ApplicationSettings.Default.NewCmsKey = ""; // ServerUri/Key will be updated too. ApplicationSettings.Default.Save(); ProcessRegisterXml(xml); } catch (Exception e) { Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Error swapping to new CMS. E = " + e.Message.ToString()), LogType.Error.ToString()); // Switch back to the old values for subsequent tries ApplicationSettings.Default.ServerUri = oldUri; ApplicationSettings.Default.ServerKey = oldKey; } } // Have we been asked to switch to HTTPS? // HTTPS MOVE // ---------- if (ApplicationSettings.Default.ForceHttps && xmds.Url.ToLowerInvariant().StartsWith("http://")) { Trace.WriteLine(new LogMessage("RegisterAgent - Run", "We have been asked to move to HTTPS from our current HTTP."), LogType.Info.ToString()); // Try it and see. try { string url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=registerDisplay"; xmds.Url = url.Replace("http://", "https://"); callRegister(xmds, key); // If that worked (no errors), update our setting ApplicationSettings.Default.ServerUri = ApplicationSettings.Default.ServerUri.Replace("http://", "https://"); ApplicationSettings.Default.Save(); } catch (Exception e) { Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Error swapping to HTTPS. E = " + e.Message.ToString()), LogType.Error.ToString()); } } } } catch (WebException webEx) when(webEx.Response is HttpWebResponse httpWebResponse && (int)httpWebResponse.StatusCode == 429) { // Get the header for how long we ought to wait retryAfterSeconds = webEx.Response.Headers["Retry-After"] != null?int.Parse(webEx.Response.Headers["Retry-After"]) : 120; // Log it. Trace.WriteLine(new LogMessage("LogAgent", "Run: 429 received, waiting for " + retryAfterSeconds + " seconds."), LogType.Info.ToString()); } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RegisterAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Exception in Run: " + ex.Message), LogType.Info.ToString()); } } if (retryAfterSeconds > 0) { // Sleep this thread until we've fulfilled our try after _manualReset.WaitOne(retryAfterSeconds * 1000); } else { // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } } Trace.WriteLine(new LogMessage("RegisterAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }
/// <summary> /// Run Thread /// </summary> public void Run() { Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Started"), LogType.Info.ToString()); int retryAfterSeconds = 0; while (!_forceStop) { // If we are restarting, reset _manualReset.Reset(); // Reset backOff retryAfterSeconds = 0; lock (_locker) { // Run the schedule Agent thread scheduleAgent(); if (ApplicationSettings.Default.InDownloadWindow) { try { int filesToDownload = _requiredFiles.FilesDownloading; // If we are currently downloading something, we have to wait if (filesToDownload > 0) { ClientInfo.Instance.RequiredFilesStatus = string.Format("Waiting: {0} Active Downloads", filesToDownload.ToString()); Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Currently Downloading Files, skipping collect"), LogType.Audit.ToString()); } else if (!ShouldCheckRf()) { ClientInfo.Instance.RequiredFilesStatus = "Sleeping: last check was not required."; } else { ClientInfo.Instance.RequiredFilesStatus = "Running: Requesting connection to Xibo Server"; using (xmds.xmds xmds = new xmds.xmds()) { xmds.Credentials = null; xmds.Url = ApplicationSettings.Default.XiboClient_xmds_xmds + "&method=requiredFiles"; xmds.UseDefaultCredentials = false; // Get required files from XMDS string requiredFilesXml = xmds.RequiredFiles(ApplicationSettings.Default.ServerKey, _hardwareKey); // Set the flag to indicate we have a connection to XMDS ApplicationSettings.Default.XmdsLastConnection = DateTime.Now; ClientInfo.Instance.RequiredFilesStatus = "Running: Data received from Xibo Server"; // Calculate and store a CRC32 _lastCheckRf = Crc32Algorithm.Compute(Encoding.UTF8.GetBytes(requiredFilesXml)).ToString(); // Load the XML file RF call XmlDocument xml = new XmlDocument(); xml.LoadXml(requiredFilesXml); // Create a required files object and set it to contain the RF returned this tick _requiredFiles = new RequiredFiles(); _requiredFiles.RequiredFilesXml = xml; // List of Threads to start // TODO: Track these threads so that we can abort them if the application closes List <Thread> threadsToStart = new List <Thread>(); // Track available disk space. long freeSpace = ClientInfo.Instance.GetDriveFreeSpace(); // Required files now contains a list of files to download (this will be updated by the various worker threads) foreach (RequiredFile fileToDownload in _requiredFiles.RequiredFileList) { // Skip downloaded files if (fileToDownload.Complete) { continue; } // Can we fit the file on the drive? if (freeSpace != -1) { if (fileToDownload.Size > freeSpace) { Trace.WriteLine(new LogMessage("RequiredFilesAgent", "Run: Not enough free space on disk"), LogType.Error.ToString()); continue; } // Decrement this file from the free space freeSpace -= (long)fileToDownload.Size; } // Spawn a thread to download this file. FileAgent fileAgent = new FileAgent(); fileAgent.FileDownloadLimit = _fileDownloadLimit; fileAgent.HardwareKey = _hardwareKey; fileAgent.RequiredFiles = _requiredFiles; fileAgent.RequiredFileId = fileToDownload.Id; fileAgent.RequiredFileType = fileToDownload.FileType; fileAgent.OnComplete += new FileAgent.OnCompleteDelegate(fileAgent_OnComplete); fileAgent.OnPartComplete += new FileAgent.OnPartCompleteDelegate(fileAgent_OnPartComplete); // Create the thread and add it to the list of threads to start Thread thread = new Thread(new ThreadStart(fileAgent.Run)); thread.Name = "FileAgent_" + fileToDownload.FileType + "_Id_" + fileToDownload.Id.ToString(); threadsToStart.Add(thread); } // Start the threads after we have built them all - otherwise they will modify the collection we // are iterating over. foreach (Thread thread in threadsToStart) { thread.Start(); } // Report what we are doing back to MediaInventory _requiredFiles.ReportInventory(); // Write Required Files _requiredFiles.WriteRequiredFiles(); // Write the Cache Manager to Disk CacheManager.Instance.WriteCacheManager(); // Set the status on the client info screen if (threadsToStart.Count == 0) { ClientInfo.Instance.RequiredFilesStatus = "Sleeping (inside download window)"; // Raise an event to say we've completed OnFullyProvisioned?.Invoke(); } else { ClientInfo.Instance.RequiredFilesStatus = string.Format("{0} files to download", threadsToStart.Count.ToString()); } ClientInfo.Instance.UpdateRequiredFiles(RequiredFilesString()); } } } catch (WebException webEx) when(webEx.Response is HttpWebResponse httpWebResponse && (int)httpWebResponse.StatusCode == 429) { // Get the header for how long we ought to wait retryAfterSeconds = webEx.Response.Headers["Retry-After"] != null?int.Parse(webEx.Response.Headers["Retry-After"]) : 120; // Log it. Trace.WriteLine(new LogMessage("RequiredFilesAgent", "Run: 429 received, waiting for " + retryAfterSeconds + " seconds."), LogType.Info.ToString()); } catch (WebException webEx) { // Increment the quantity of XMDS failures and bail out ApplicationSettings.Default.IncrementXmdsErrorCount(); // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "WebException in Run: " + webEx.Message), LogType.Info.ToString()); ClientInfo.Instance.RequiredFilesStatus = "Error: " + webEx.Message; } catch (Exception ex) { // Log this message, but dont abort the thread Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Exception in Run: " + ex.Message), LogType.Error.ToString()); ClientInfo.Instance.RequiredFilesStatus = "Error: " + ex.Message; } } else { ClientInfo.Instance.RequiredFilesStatus = string.Format("Outside Download Window {0} - {1}", ApplicationSettings.Default.DownloadStartWindowTime.ToString(), ApplicationSettings.Default.DownloadEndWindowTime.ToString()); } } if (retryAfterSeconds > 0) { // Sleep this thread until we've fulfilled our try after _manualReset.WaitOne(retryAfterSeconds * 1000); } else { // Sleep this thread until the next collection interval _manualReset.WaitOne((int)(ApplicationSettings.Default.CollectInterval * ApplicationSettings.Default.XmdsCollectionIntervalFactor() * 1000)); } } Trace.WriteLine(new LogMessage("RequiredFilesAgent - Run", "Thread Stopped"), LogType.Info.ToString()); }