using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Http.Headers; using System.Net.Http; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; using System.Xml.Serialization; using System.Xml; using System.Dynamic; using System.IO.Ports; using System.Xml.Linq; namespace AnimeCon.Vlc.Scraper { public partial class Form1 : Form { private string VlcHostName { get; set; } private string VlcPassword { get; set; } private int remainingTime { get;set; } private string timeString { get; set; } static SerialPort _serialPort; public Form1() { InitializeComponent(); _serialPort = new SerialPort(); string[] portNames = SerialPort.GetPortNames(); // Add the port names to the ComboBox cbCom.Items.AddRange(portNames); // Select the first port if available if (cbCom.Items.Count > 0) { cbCom.SelectedIndex = 0; } } private void btnConnect_Click(object sender, EventArgs e) { if(lblStatus.Text != "Disconnected") { lblStatus.Text = "Disconnected"; lblStatus.ForeColor = System.Drawing.Color.Red; btnConnect.Text = "Connect"; lblTime.Text = "00:00:00"; tmrVlc.Stop(); } else { this.VlcHostName = txtHostname.Text; this.VlcPassword = txtPassword.Text; lblTime.Text = "00:00:00"; try { DoWebRequestAsync(); tmrVlc.Start(); btnConnect.Text = "Disconnect"; } catch { tmrVlc.Stop(); } } } private async Task DoWebRequestAsync() { using (HttpClient httpClient = new HttpClient()) { // Convert the credentials to Base64 string base64Credentials = Convert.ToBase64String(System.Text.Encoding.ASCII.GetBytes($":{this.VlcPassword}")); // Add Authorization header with Basic Authentication httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64Credentials); try { // Make a GET request to the remote XML file HttpResponseMessage response = await httpClient.GetAsync($"http://{this.VlcHostName}/requests/status.xml"); // Ensure the request was successful response.EnsureSuccessStatusCode(); lblStatus.Text = "Connected"; lblStatus.ForeColor = System.Drawing.Color.Green; string xmlContent = await response.Content.ReadAsStringAsync(); dynamic parsedObject = ParseXml(xmlContent); int timeValue = GetPropertyValue(parsedObject, "time"); int lengthValue = GetPropertyValue(parsedObject, "length"); remainingTime = lengthValue - timeValue; ConvertSecondsToTimeString(remainingTime); return; } catch (Exception ex) { // Handle exception Console.WriteLine($"Error: {ex.Message}"); lblStatus.Text = "ERROR!"; lblStatus.ForeColor = System.Drawing.Color.Red; btnConnect.Text = "Connect"; throw; } } } private void tmrVlc_Tick(object sender, EventArgs e) { try { DoWebRequestAsync(); } catch { btnConnect.Text = "Connect"; tmrVlc.Stop(); } } private void DoSendDataSerial() { // Allow the user to set the appropriate properties. _serialPort.PortName = cbCom.Items[cbCom.SelectedIndex].ToString(); _serialPort.BaudRate = 9600; _serialPort.Parity = Parity.None; _serialPort.DataBits = 8; _serialPort.StopBits = StopBits.One; _serialPort.Handshake = Handshake.None; // Set the read/write timeouts _serialPort.ReadTimeout = 500; _serialPort.WriteTimeout = 500; _serialPort.Open(); _serialPort.WriteLine(timeString); _serialPort.Close(); } private void btnClock_Click(object sender, EventArgs e) { if (lblRunning.Text != "Off") { lblRunning.Text = "Off"; lblStatus.ForeColor = System.Drawing.Color.Red; btnClock.Text = "Start"; tmrClock.Stop(); } else { try { DoSendDataSerial(); tmrClock.Interval = Convert.ToInt32(txtInterval.Text)*1000; tmrClock.Start(); btnClock.Text = "Stop"; lblStatus.Text = "On"; lblStatus.ForeColor = System.Drawing.Color.Green; } catch { tmrClock.Stop(); } } try { DoSendDataSerial(); tmrVlc.Start(); } catch { lblRunning.Text = "ERROR!"; lblRunning.ForeColor = System.Drawing.Color.Red; btnClock.Text = "Start"; tmrVlc.Stop(); } } private void tmrClock_Tick(object sender, EventArgs e) { try { DoSendDataSerial(); } catch { lblRunning.Text = "ERROR!"; lblRunning.ForeColor = System.Drawing.Color.Red; btnClock.Text = "Start"; tmrVlc.Stop(); } } static dynamic ParseXml(string xmlContent) { try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.LoadXml(xmlContent); return ParseXmlNode(xmlDoc.DocumentElement); } catch (Exception ex) { // Handle parsing exception Console.WriteLine($"Error parsing XML: {ex.Message}"); return null; } } static dynamic ParseXmlNode(XmlNode node) { if (node.NodeType == XmlNodeType.Element) { dynamic dynamicObject = new ExpandoObject(); var dictionary = (IDictionary)dynamicObject; foreach (XmlNode childNode in node.ChildNodes) { dictionary[childNode.Name] = ParseXmlNode(childNode); } return dynamicObject; } else if (node.NodeType == XmlNodeType.Text || node.NodeType == XmlNodeType.CDATA) { return node.InnerText; } else { return null; // Handle other node types as needed } } static int GetPropertyValue(dynamic parsedObject, string propertyName) { if (parsedObject != null) { var dictionary = (IDictionary)parsedObject; if (dictionary.ContainsKey(propertyName)) { dynamic propertyValue = dictionary[propertyName]; // Check if the property value is an array with the format ["#text", value] if (propertyValue is object[] && propertyValue.Length == 2 && propertyValue[0] == "#text") { return Convert.ToInt32(propertyValue[1]); } else if (propertyValue is ExpandoObject) { return GetPropertyValue(propertyValue, "#text"); } else { return Convert.ToInt32(propertyValue); // Fallback if the format is different } } } return 0; // Default value if the property is not found } private void ConvertSecondsToTimeString(int totalSeconds) { // Calculate hours, minutes, and seconds int hours = totalSeconds / 3600; int minutes = (totalSeconds % 3600) / 60; int seconds = totalSeconds % 60; // Format the time string lblTime.Text = $"{hours:D2}:{minutes:D2}:{seconds:D2}"; timeString = $"{hours:D2}{minutes:D2}{seconds:D2}"; } } }