Mobile API Refactoring

• Introduced new Mobile API.cs module
• Encapsulates firmware checks, day/night mode switching, and snapshot operations
• Methods: CheckFirmwareAsync(), SetDayModeAsync(), SetNightModeAsync()
• Improves code maintainability and separates API logic from test execution

UI Components
• DayImgPcbx PictureBox: Displays day snapshot
• NightImgPcbx PictureBox: Displays night snapshot
• DayImage Label: Shows day luminance percentage
• NightImage Label: Shows night luminance percentage

Features Implemented
• Luminance-based validation: Uses ImageProcessing.GetMeanLuminance() to quantitatively analyze day and night snapshots
• Validation logic: Day luminance must exceed night luminance to pass the test
• Real-time luminance display: Appends calculated luminance percentages (0-100%) to day and night image labels
• Enhanced error reporting: Logs detailed luminance values when test fails for debugging purposes

• Captures day mode snapshot → Analyzes luminance
• Captures night mode snapshot → Analyzes luminance
• Compares values and updates UI labels with percentages
• Result: "Day/Night Mode = Passed" (green) or "Day/Night Mode = Failed" (red) with error details
This commit is contained in:
2026-01-13 15:31:50 +00:00
parent 4a2e874b9d
commit d1d90f17fc
7 changed files with 308 additions and 162 deletions

119
AiQ_GUI.Designer.cs generated
View File

@@ -132,10 +132,10 @@ namespace AiQ_GUI
TabImages = new TabPage(); TabImages = new TabPage();
Video = new TabPage(); Video = new TabPage();
VLCVideo = new Label(); VLCVideo = new Label();
pictureBox2 = new PictureBox(); NightImgPcbx = new PictureBox();
label7 = new Label(); NightImage = new Label();
OVImage = new Label(); DayImage = new Label();
pictureBox1 = new PictureBox(); DayImgPcbx = new PictureBox();
TabSoak = new TabPage(); TabSoak = new TabPage();
BtnFactoryDefault = new Button(); BtnFactoryDefault = new Button();
SetGodModeAll = new Button(); SetGodModeAll = new Button();
@@ -170,8 +170,8 @@ namespace AiQ_GUI
TabSettings.SuspendLayout(); TabSettings.SuspendLayout();
TabImages.SuspendLayout(); TabImages.SuspendLayout();
Video.SuspendLayout(); Video.SuspendLayout();
((System.ComponentModel.ISupportInitialize)pictureBox2).BeginInit(); ((System.ComponentModel.ISupportInitialize)NightImgPcbx).BeginInit();
((System.ComponentModel.ISupportInitialize)pictureBox1).BeginInit(); ((System.ComponentModel.ISupportInitialize)DayImgPcbx).BeginInit();
TabSoak.SuspendLayout(); TabSoak.SuspendLayout();
Mobile.SuspendLayout(); Mobile.SuspendLayout();
SuspendLayout(); SuspendLayout();
@@ -1664,10 +1664,10 @@ namespace AiQ_GUI
Video.BackColor = Color.FromArgb(39, 37, 55); Video.BackColor = Color.FromArgb(39, 37, 55);
Video.Controls.Add(VidView); Video.Controls.Add(VidView);
Video.Controls.Add(VLCVideo); Video.Controls.Add(VLCVideo);
Video.Controls.Add(pictureBox2); Video.Controls.Add(NightImgPcbx);
Video.Controls.Add(label7); Video.Controls.Add(NightImage);
Video.Controls.Add(OVImage); Video.Controls.Add(DayImage);
Video.Controls.Add(pictureBox1); Video.Controls.Add(DayImgPcbx);
Video.Location = new Point(4, 24); Video.Location = new Point(4, 24);
Video.Name = "Video"; Video.Name = "Video";
Video.Padding = new Padding(3); Video.Padding = new Padding(3);
@@ -1688,55 +1688,55 @@ namespace AiQ_GUI
VLCVideo.TabIndex = 238; VLCVideo.TabIndex = 238;
VLCVideo.Text = "Live Video"; VLCVideo.Text = "Live Video";
// //
// pictureBox2 // NightImgPcbx
// //
pictureBox2.BackColor = Color.Transparent; NightImgPcbx.BackColor = Color.Transparent;
pictureBox2.BorderStyle = BorderStyle.FixedSingle; NightImgPcbx.BorderStyle = BorderStyle.FixedSingle;
pictureBox2.Location = new Point(7, 303); NightImgPcbx.Location = new Point(7, 303);
pictureBox2.Margin = new Padding(4, 3, 4, 3); NightImgPcbx.Margin = new Padding(4, 3, 4, 3);
pictureBox2.Name = "pictureBox2"; NightImgPcbx.Name = "NightImgPcbx";
pictureBox2.Size = new Size(392, 221); NightImgPcbx.Size = new Size(392, 221);
pictureBox2.SizeMode = PictureBoxSizeMode.StretchImage; NightImgPcbx.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox2.TabIndex = 237; NightImgPcbx.TabIndex = 237;
pictureBox2.TabStop = false; NightImgPcbx.TabStop = false;
// //
// label7 // NightImage
// //
label7.AutoSize = true; NightImage.AutoSize = true;
label7.BackColor = Color.Transparent; NightImage.BackColor = Color.Transparent;
label7.Font = new Font("Segoe UI Semibold", 12F, FontStyle.Bold); NightImage.Font = new Font("Segoe UI Semibold", 12F, FontStyle.Bold);
label7.ForeColor = SystemColors.Control; NightImage.ForeColor = SystemColors.Control;
label7.Location = new Point(12, 279); NightImage.Location = new Point(12, 279);
label7.Margin = new Padding(4, 0, 4, 0); NightImage.Margin = new Padding(4, 0, 4, 0);
label7.Name = "label7"; NightImage.Name = "NightImage";
label7.Size = new Size(101, 21); NightImage.Size = new Size(101, 21);
label7.TabIndex = 236; NightImage.TabIndex = 236;
label7.Text = "Night Image"; NightImage.Text = "Night Image";
// //
// OVImage // DayImage
// //
OVImage.AutoSize = true; DayImage.AutoSize = true;
OVImage.BackColor = Color.Transparent; DayImage.BackColor = Color.Transparent;
OVImage.Font = new Font("Segoe UI Semibold", 12F, FontStyle.Bold); DayImage.Font = new Font("Segoe UI Semibold", 12F, FontStyle.Bold);
OVImage.ForeColor = SystemColors.Control; DayImage.ForeColor = SystemColors.Control;
OVImage.Location = new Point(12, 14); DayImage.Location = new Point(12, 14);
OVImage.Margin = new Padding(4, 0, 4, 0); DayImage.Margin = new Padding(4, 0, 4, 0);
OVImage.Name = "OVImage"; DayImage.Name = "DayImage";
OVImage.Size = new Size(87, 21); DayImage.Size = new Size(87, 21);
OVImage.TabIndex = 235; DayImage.TabIndex = 235;
OVImage.Text = "Day Image"; DayImage.Text = "Day Image";
// //
// pictureBox1 // DayImgPcbx
// //
pictureBox1.BackColor = Color.Transparent; DayImgPcbx.BackColor = Color.Transparent;
pictureBox1.BorderStyle = BorderStyle.FixedSingle; DayImgPcbx.BorderStyle = BorderStyle.FixedSingle;
pictureBox1.Location = new Point(7, 46); DayImgPcbx.Location = new Point(7, 46);
pictureBox1.Margin = new Padding(4, 3, 4, 3); DayImgPcbx.Margin = new Padding(4, 3, 4, 3);
pictureBox1.Name = "pictureBox1"; DayImgPcbx.Name = "DayImgPcbx";
pictureBox1.Size = new Size(392, 221); DayImgPcbx.Size = new Size(392, 221);
pictureBox1.SizeMode = PictureBoxSizeMode.StretchImage; DayImgPcbx.SizeMode = PictureBoxSizeMode.StretchImage;
pictureBox1.TabIndex = 234; DayImgPcbx.TabIndex = 234;
pictureBox1.TabStop = false; DayImgPcbx.TabStop = false;
// //
// TabSoak // TabSoak
// //
@@ -1979,8 +1979,8 @@ namespace AiQ_GUI
TabImages.PerformLayout(); TabImages.PerformLayout();
Video.ResumeLayout(false); Video.ResumeLayout(false);
Video.PerformLayout(); Video.PerformLayout();
((System.ComponentModel.ISupportInitialize)pictureBox2).EndInit(); ((System.ComponentModel.ISupportInitialize)NightImgPcbx).EndInit();
((System.ComponentModel.ISupportInitialize)pictureBox1).EndInit(); ((System.ComponentModel.ISupportInitialize)DayImgPcbx).EndInit();
TabSoak.ResumeLayout(false); TabSoak.ResumeLayout(false);
TabSoak.PerformLayout(); TabSoak.PerformLayout();
Mobile.ResumeLayout(false); Mobile.ResumeLayout(false);
@@ -1992,7 +1992,7 @@ namespace AiQ_GUI
#endregion #endregion
public System.Windows.Forms.Button BtnStartTest; public System.Windows.Forms.Button BtnStartTest;
private System.Windows.Forms.Button BtnFindCams; private System.Windows.Forms.Button BtnFindCams;
private System.Windows.Forms.ComboBox CbBxFoundCams; public System.Windows.Forms.ComboBox CbBxFoundCams;
private System.Windows.Forms.Button BtnRestart; private System.Windows.Forms.Button BtnRestart;
private System.Windows.Forms.Button BtnMin; private System.Windows.Forms.Button BtnMin;
private System.Windows.Forms.Button BtnClose; private System.Windows.Forms.Button BtnClose;
@@ -2121,12 +2121,13 @@ namespace AiQ_GUI
public ComboBox CbBxCamType; public ComboBox CbBxCamType;
public TabPage Mobile; public TabPage Mobile;
private Button BtnUpFirm; private Button BtnUpFirm;
private LibVLCSharp.WinForms.VideoView VidView; public LibVLCSharp.WinForms.VideoView VidView;
private TabPage Video; private TabPage Video;
public Label label7; public Label NightImage;
public Label OVImage; public Label DayImage;
public PictureBox pictureBox1; public PictureBox pictureBox1;
public Label VLCVideo; public Label VLCVideo;
public PictureBox pictureBox2; public PictureBox NightImgPcbx;
public PictureBox DayImgPcbx;
} }
} }

View File

@@ -1,4 +1,5 @@
using AiQ_GUI.AiQ_Tests; using AiQ_GUI.AiQ_Tests;
using AiQ_GUI.Mobile_Tests;
using LibVLCSharp.Shared; using LibVLCSharp.Shared;
using LibVLCSharp.WinForms; using LibVLCSharp.WinForms;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -1449,10 +1450,12 @@ namespace AiQ_GUI
//StatsExcel excelExporter = new(); //StatsExcel excelExporter = new();
//excelExporter.ExportDatabaseToExcel(); //excelExporter.ExportDatabaseToExcel();
//await MobilePreTest.CheckFirmwareAsync(); //await MobilePreTest.CheckFirmwareAsync();
VLC.Play(VidView); VLC.Play(VidView);
await Task.Delay(5000); await Task.Delay(5000);
VLC.TakeSnapshot(VidView); //VLC.TakeSnapshot(VidView);
await MobileAPI.SetDayModeAsync();
AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff"), Level.LOG); AddToActionsList("RunTime " + stopWatchTest.Elapsed.ToString(@"hh\:mm\:ss\.ff"), Level.LOG);
} }

View File

@@ -123,6 +123,9 @@
<metadata name="ToolTipClipboard.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="ToolTipClipboard.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>159, 17</value> <value>159, 17</value>
</metadata> </metadata>
<metadata name="ToolTipAvailable.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>17, 17</value>
</metadata>
<metadata name="TimerDDC.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"> <metadata name="TimerDDC.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>531, 18</value> <value>531, 18</value>
</metadata> </metadata>

164
Mobile Tests/Mobile API.cs Normal file
View File

@@ -0,0 +1,164 @@
using AiQ_GUI;
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
namespace AiQ_GUI.Mobile_Tests
{
public static class MobileAPI
{
public static async Task CheckFirmwareAsync()
{
using HttpClient client = new HttpClient
{
BaseAddress = new Uri($"http://{MainForm.Instance.CamOnTest.IP}")
};
try
{
// Login and get JWT token
string token = await LoginAsync(client, "ADMIN", "1234");
// Attach JWT to all requests
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
// Request firmware information
HttpResponseMessage response = await client.GetAsync("/app/v1/system/firmware");
string body = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
JsonElement json = JsonSerializer.Deserialize<JsonElement>(body);
string version = json.GetProperty("version").GetString()?.Trim();
// Compare against expected SRZFirmware from UniversalData
if (string.IsNullOrEmpty(UniversalData.SRZFirmware))
{
MainForm.Instance.AddToActionsList($"Firmware check failed: Expected SRZFirmware not loaded in UniversalData", Level.ERROR);
MainForm.Instance.AddLabelToPanel($"Firmware = {version}", true);
}
else if (version == UniversalData.SRZFirmware)
{
MainForm.Instance.AddLabelToPanel($"Firmware = {version}", false);
}
else
{
MainForm.Instance.AddLabelToPanel($"Firmware = {version}", true);
}
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Firmware check failed: {ex.Message}", Level.ERROR);
MainForm.Instance.AddLabelToPanel("Firmware = Unknown", true);
}
}
public static async Task ChangeDayNightModeAsync(uint mode)
{
// mode: 0 = Auto, 1 = Day, 2 = Night
string modeName = mode switch
{
0 => "Auto",
1 => "Day",
2 => "Night",
_ => "Unknown"
};
// operatingMode required by firmware (!)
// day -> 1, night -> 0
int operatingMode = mode switch
{
1 => 1, // Day
2 => 0, // Night
_ => 1 // Auto: keep day as safe default
};
using HttpClient client = new HttpClient
{
BaseAddress = new Uri($"http://{MainForm.Instance.CamOnTest.IP}")
};
try
{
// Login
string token = await LoginAsync(client, "ADMIN", "1234");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
var payload = new
{
dayNightMode = new
{
mode = mode,
dayToNightSens = 4,
nightToDaySens = 24,
transitionDelay = 20,
operatingMode = operatingMode
}
};
HttpResponseMessage response = await client.PostAsJsonAsync("/app/v1/camera/image", payload);
if (response.IsSuccessStatusCode)
{
MainForm.Instance.AddToActionsList($"Camera set to {modeName} mode successfully",Level.Success);
}
else
{
string error = await response.Content.ReadAsStringAsync();
MainForm.Instance.AddToActionsList($"Failed to set {modeName} mode: {response.StatusCode} - {error}",Level.ERROR);
}
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Error changing to {modeName} mode: {ex.Message}",Level.ERROR);
}
}
public static async Task SetDayModeAsync()
{
await ChangeDayNightModeAsync(1);
}
public static async Task SetNightModeAsync()
{
await ChangeDayNightModeAsync(2);
}
public static async Task SetAutoModeAsync()
{
await ChangeDayNightModeAsync(0);
}
private static async Task<string> LoginAsync(HttpClient client, string user, string password)
{
var payload = new
{
userId = user,
userPassword = Sha256(password)
};
HttpResponseMessage response = await client.PostAsJsonAsync("/app/v1/login", payload);
response.EnsureSuccessStatusCode();
JsonElement json = await response.Content.ReadFromJsonAsync<JsonElement>();
return json.GetProperty("token").GetString();
}
private static string Sha256(string input)
{
using SHA256 sha = SHA256.Create();
byte[] bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
}
}

View File

@@ -0,0 +1,68 @@
using LibVLCSharp.WinForms;
using System;
using System.Threading.Tasks;
namespace AiQ_GUI.Mobile_Tests
{
public static class MobilePreTest
{
public static async Task RunPreTestAsync()
{
await MobileAPI.CheckFirmwareAsync();// Check firmware version
VLC.Play(MainForm.Instance.VidView);// Test Live Video streaming
await Task.Delay(5000);
VLC.TakeSnapshot(MainForm.Instance.VidView);
if (!VLC.IsPLaying(MainForm.Instance.VidView))// Check Live Video streaming
{
MainForm.Instance.AddToActionsList("Live Video streaming test failed: Video is not playing.", Level.ERROR);
MainForm.Instance.AddLabelToPanel("Live Video = Not Playing", true);
}
else
{
MainForm.Instance.AddLabelToPanel("Live Video = Playing", false);
}
await TestDayNightMode();// Test day/night mode cycling
double dayLuminance = ImageProcessing.GetMeanLuminance(MainForm.Instance.DayImgPcbx.Image); // Calculates the Luminance
double nightLuminance = ImageProcessing.GetMeanLuminance(MainForm.Instance.NightImgPcbx.Image);
MainForm.Instance.DayImage.Text += $" - Luminance: {dayLuminance}%";
MainForm.Instance.NightImage.Text += $" - Luminance: {nightLuminance}%";
if (dayLuminance > nightLuminance)
{
MainForm.Instance.AddLabelToPanel("Day/Night Mode = Passed", false);
}
else
{
MainForm.Instance.AddToActionsList($"Day/Night mode test failed: Day luminance ({dayLuminance}%) is not greater than night luminance ({nightLuminance}%).", Level.ERROR);
MainForm.Instance.AddLabelToPanel("Day/Night Mode = Failed", true);
}
}
private static async Task TestDayNightMode()
{
await MobileAPI.SetDayModeAsync();// Set to Day mode
await Task.Delay(5000);
VLC.TakeSnapshot(MainForm.Instance.VidView, "Mobile_day_snapshot.png");// Take Day Image Snapshot
MainForm.Instance.DayImgPcbx.Image = System.Drawing.Image.FromFile(Path.Combine(LDS.MAVPath, "Mobile_day_snapshot.png"));// Display Day mode snapshot
await MobileAPI.SetNightModeAsync();// Set to Night mode
await Task.Delay(5000);
VLC.TakeSnapshot(MainForm.Instance.VidView, "Mobile_night_snapshot.png");// Take Night Image Snapshot
MainForm.Instance.NightImgPcbx.Image = System.Drawing.Image.FromFile(Path.Combine(LDS.MAVPath, "Mobile_night_snapshot.png"));// Display Night mode snapshot
}
}
}

View File

@@ -1,95 +0,0 @@
using AiQ_GUI;
using System;
using System.IO;
using System.Net.Http;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing;
public static class MobilePreTest
{
public static async Task CheckFirmwareAsync()
{
using HttpClient client = new HttpClient
{
BaseAddress = new Uri($"http://{MainForm.Instance.CamOnTest.IP}")
};
try
{
// Login and get JWT token
string token = await LoginAsync(client, "ADMIN", "1234");
// Attach JWT to all requests
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
// Request firmware information
HttpResponseMessage response = await client.GetAsync("/app/v1/system/firmware");
string body = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
JsonElement json = JsonSerializer.Deserialize<JsonElement>(body);
string version = json.GetProperty("version").GetString()?.Trim();
// Compare against expected SRZFirmware from UniversalData
if (string.IsNullOrEmpty(UniversalData.SRZFirmware))
{
MainForm.Instance.AddToActionsList($"Firmware check failed: Expected SRZFirmware not loaded in UniversalData",Level.ERROR);
MainForm.Instance.AddLabelToPanel($"Firmware = {version}", true);
}
else if (version == UniversalData.SRZFirmware)
{
MainForm.Instance.AddLabelToPanel($"Firmware = {version}", false);
}
else
{
MainForm.Instance.AddLabelToPanel($"Firmware = {version}", true);
}
}
catch (Exception ex)
{
MainForm.Instance.AddToActionsList($"Firmware check failed: {ex.Message}",Level.ERROR);
MainForm.Instance.AddLabelToPanel("Firmware = Unknown", true);
}
}
private static async Task<string> LoginAsync(HttpClient client, string user, string password)
{
var payload = new
{
userId = user,
userPassword = Sha256(password)
};
HttpResponseMessage response = await client.PostAsJsonAsync("/app/v1/login", payload);
response.EnsureSuccessStatusCode();
JsonElement json = await response.Content.ReadFromJsonAsync<JsonElement>();
return json.GetProperty("token").GetString();
}
private static string Sha256(string input)
{
using SHA256 sha = SHA256.Create();
byte[] bytes = sha.ComputeHash(Encoding.UTF8.GetBytes(input));
return BitConverter.ToString(bytes).Replace("-", "").ToLower();
}
public static async Task RunPreTestAsync()
{
await CheckFirmwareAsync();
}
}

View File

@@ -1,7 +1,9 @@
using AiQ_GUI; using AiQ_GUI;
using Emgu.CV.Dai;
using LibVLCSharp.Shared; using LibVLCSharp.Shared;
using LibVLCSharp.WinForms; using LibVLCSharp.WinForms;
using System.IO; using System.IO;
using System.Security.Policy;
internal class VLC internal class VLC
{ {
@@ -14,12 +16,12 @@ internal class VLC
libVLC = new LibVLC(); libVLC = new LibVLC();
} }
public static string RtspUrl = $"rtsp://ADMIN:1234@192.168.0.85:554/live/main";
public static string SnapshotPath = Path.Combine(LDS.MAVPath, "Mobile_ov_snapshot.png"); public static string SnapshotPath = Path.Combine(LDS.MAVPath, "Mobile_ov_snapshot.png");
public static void Play(VideoView VLCVV) public static void Play(VideoView VLCVV)
{ {
var media = new Media(libVLC, RtspUrl, FromType.FromLocation); var media = new Media(libVLC, $"rtsp://ADMIN:1234@{MainForm.Instance.CamOnTest.IP}:554/live/main", FromType.FromLocation);
VLCVV.MediaPlayer.Play(media); VLCVV.MediaPlayer.Play(media);
} }
@@ -28,10 +30,10 @@ internal class VLC
return VLCVV.MediaPlayer.IsPlaying; return VLCVV.MediaPlayer.IsPlaying;
} }
public static void TakeSnapshot(VideoView VLCVV) public static void TakeSnapshot(VideoView VLCVV, string filename = "Mobile_ov_snapshot.png")
{ {
VLCVV.MediaPlayer.TakeSnapshot(0, SnapshotPath, 1280, 720); string path = Path.Combine(LDS.MAVPath, filename);
VLCVV.MediaPlayer.TakeSnapshot(0, path, 1280, 720);
} }
public static void Stop(VideoView VLCVV) public static void Stop(VideoView VLCVV)
@@ -41,7 +43,7 @@ internal class VLC
public static void Capture(VideoView VLCVV) public static void Capture(VideoView VLCVV)
{ {
var media = new Media(libVLC, RtspUrl, FromType.FromLocation); var media = new Media(libVLC, $"rtsp://ADMIN:1234@{MainForm.Instance.CamOnTest.IP}:554/live/main", FromType.FromLocation);
media.AddOption(":rtsp-tcp"); media.AddOption(":rtsp-tcp");
VLCVV.MediaPlayer.Play(media); VLCVV.MediaPlayer.Play(media);
} }