From 484c3575867f387f444ad65d8be8609a946ba8bf Mon Sep 17 00:00:00 2001 From: zqm Date: Tue, 24 Mar 2026 10:37:54 +0800 Subject: [PATCH] =?UTF-8?q?=E6=91=84=E5=83=8F=E5=A4=B4=E7=BB=84=E4=BB=B6?= =?UTF-8?q?=EF=BC=8C=E6=94=AF=E6=8C=81novif=E5=92=8Chttp=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Windows/CS/Framework4.0/Camera/Camera.sln | 31 +++ .../CS/Framework4.0/Camera/Camera/Camera.cs | 236 ++++++++++++++++++ .../Framework4.0/Camera/Camera/Camera.csproj | 82 ++++++ .../CS/Framework4.0/Camera/Camera/Program.cs | 21 ++ .../Camera/Camera/Properties/AssemblyInfo.cs | 36 +++ .../Camera/Properties/Resources.Designer.cs | 71 ++++++ .../Camera/Camera/Properties/Resources.resx | 117 +++++++++ .../Camera/Properties/Settings.Designer.cs | 30 +++ .../Camera/Properties/Settings.settings | 7 + .../Camera/Camera/Setting.Designer.cs | 153 ++++++++++++ .../CS/Framework4.0/Camera/Camera/Setting.cs | 61 +++++ .../Framework4.0/Camera/Camera/Setting.resx | 120 +++++++++ .../Camera/Test/Form1.Designer.cs | 102 ++++++++ Windows/CS/Framework4.0/Camera/Test/Form1.cs | 72 ++++++ .../CS/Framework4.0/Camera/Test/Form1.resx | 120 +++++++++ .../CS/Framework4.0/Camera/Test/Program.cs | 21 ++ .../Camera/Test/Properties/AssemblyInfo.cs | 36 +++ .../Test/Properties/Resources.Designer.cs | 71 ++++++ .../Camera/Test/Properties/Resources.resx | 117 +++++++++ .../Test/Properties/Settings.Designer.cs | 30 +++ .../Camera/Test/Properties/Settings.settings | 7 + .../CS/Framework4.0/Camera/Test/Test.csproj | 84 +++++++ Windows/CS/Framework4.0/Camera/tplink.md | 109 ++++++++ 23 files changed, 1734 insertions(+) create mode 100644 Windows/CS/Framework4.0/Camera/Camera.sln create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Camera.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Camera.csproj create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Program.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Properties/AssemblyInfo.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.Designer.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.resx create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.Designer.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.settings create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Setting.Designer.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Setting.cs create mode 100644 Windows/CS/Framework4.0/Camera/Camera/Setting.resx create mode 100644 Windows/CS/Framework4.0/Camera/Test/Form1.Designer.cs create mode 100644 Windows/CS/Framework4.0/Camera/Test/Form1.cs create mode 100644 Windows/CS/Framework4.0/Camera/Test/Form1.resx create mode 100644 Windows/CS/Framework4.0/Camera/Test/Program.cs create mode 100644 Windows/CS/Framework4.0/Camera/Test/Properties/AssemblyInfo.cs create mode 100644 Windows/CS/Framework4.0/Camera/Test/Properties/Resources.Designer.cs create mode 100644 Windows/CS/Framework4.0/Camera/Test/Properties/Resources.resx create mode 100644 Windows/CS/Framework4.0/Camera/Test/Properties/Settings.Designer.cs create mode 100644 Windows/CS/Framework4.0/Camera/Test/Properties/Settings.settings create mode 100644 Windows/CS/Framework4.0/Camera/Test/Test.csproj create mode 100644 Windows/CS/Framework4.0/Camera/tplink.md diff --git a/Windows/CS/Framework4.0/Camera/Camera.sln b/Windows/CS/Framework4.0/Camera/Camera.sln new file mode 100644 index 0000000..34b40f4 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.36617.4 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Camera", "Camera\Camera.csproj", "{1376F939-3A40-4406-8987-467450E40573}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Test", "Test\Test.csproj", "{2FAE57C2-275D-449F-967D-04EDC584BDF1}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {1376F939-3A40-4406-8987-467450E40573}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1376F939-3A40-4406-8987-467450E40573}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1376F939-3A40-4406-8987-467450E40573}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1376F939-3A40-4406-8987-467450E40573}.Release|Any CPU.Build.0 = Release|Any CPU + {2FAE57C2-275D-449F-967D-04EDC584BDF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2FAE57C2-275D-449F-967D-04EDC584BDF1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2FAE57C2-275D-449F-967D-04EDC584BDF1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2FAE57C2-275D-449F-967D-04EDC584BDF1}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {729DBE58-6C82-4EA8-8953-F83F08F7223A} + EndGlobalSection +EndGlobal diff --git a/Windows/CS/Framework4.0/Camera/Camera/Camera.cs b/Windows/CS/Framework4.0/Camera/Camera/Camera.cs new file mode 100644 index 0000000..ca6fd53 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Camera.cs @@ -0,0 +1,236 @@ +using System; +using System.Drawing; +using System.Timers; +using System.Net; +using System.IO; +using System.Security.Cryptography; +using System.Text.RegularExpressions; + +namespace Camera +{ + public class Camera + { + // 摄像头配置信息 + private const string IP = "192.168.100.60"; + private const string SNAPSHOT_URI = "/snapshot.jpg"; + private const string USER = "admin"; + private const string PASSWD = "Yexian.net.168"; + + // 定时器 + private System.Timers.Timer _timer; + + // 事件定义 + public event EventHandler ImageCaptured; + + /// + /// 根据区域编号获取颜色 + /// + /// 区域编号 + /// 对应区域的颜色 + public Color GetColor(int AreaNum) + { + // 这里可以根据实际需求实现颜色获取逻辑 + // 暂时返回一个默认颜色 + switch (AreaNum) + { + case 1: + return Color.Red; + case 2: + return Color.Green; + case 3: + return Color.Blue; + default: + return Color.Gray; + } + } + + /// + /// 开始获取图像 + /// + public void Start() + { + // 停止现有的定时器 + Stop(); + + // 创建新的定时器,设置为300ms触发一次,关闭自动重置 + _timer = new System.Timers.Timer(300); + _timer.AutoReset = false; + _timer.Elapsed += Timer_Elapsed; + _timer.Start(); + } + + /// + /// 停止获取图像 + /// + public void Stop() + { + if (_timer != null) + { + _timer.Stop(); + _timer.Dispose(); + _timer = null; + } + } + + /// + /// 定时器触发事件 + /// + private void Timer_Elapsed(object sender, ElapsedEventArgs e) + { + try + { + // 获取图像 + Image image = GetCameraImage(); + if (image != null) + { + // 发布事件 + OnImageCaptured(new ImageEventArgs { Image = image }); + } + } + catch (Exception ex) + { + // 忽略错误,继续下一次获取 + Console.WriteLine("获取图像失败: " + ex.Message); + } + finally + { + // 重新启动定时器 + if (_timer != null && _timer.Enabled == false) + { + _timer.Start(); + } + } + } + + /// + /// 获取摄像头图像 + /// + private Image GetCameraImage() + { + // 构建请求URL + string url = "http://" + IP + SNAPSHOT_URI; + + // 创建Web请求 + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "GET"; + + HttpWebResponse response = null; + try + { + // 发送请求,获取响应 + response = (HttpWebResponse)request.GetResponse(); + } + catch (System.Net.WebException ex) + { + // 检查是否是401未授权错误 + if (ex.Response != null && ((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized) + { + // 获取鉴权信息 + response = (HttpWebResponse)ex.Response; + string authHeader = response.Headers["WWW-Authenticate"]; + response.Close(); + + // 提取realm和nonce + string realm = ExtractAuthParam(authHeader, "realm"); + string nonce = ExtractAuthParam(authHeader, "nonce"); + + // 生成鉴权信息 + string authorization = GenerateDigestAuthorization(USER, PASSWD, realm, nonce, "GET", SNAPSHOT_URI); + + // 重新发送请求,带上鉴权信息 + request = (HttpWebRequest)WebRequest.Create(url); + request.Method = "GET"; + request.Headers.Add("Authorization", authorization); + response = (HttpWebResponse)request.GetResponse(); + } + else + { + // 其他Web异常,抛出 + throw; + } + } + + // 读取响应流中的图片数据 + using (Stream stream = response.GetResponseStream()) + { + // 将流转换为Image对象 + Image image = Image.FromStream(stream); + response.Close(); + return image; + } + } + + /// + /// 从WWW-Authenticate头中提取参数 + /// + private string ExtractAuthParam(string authHeader, string paramName) + { + Regex regex = new Regex(paramName + "=\"([^\"]+)\""); + Match match = regex.Match(authHeader); + if (match.Success) + { + return match.Groups[1].Value; + } + return string.Empty; + } + + /// + /// 生成Digest认证的Authorization头 + /// + private string GenerateDigestAuthorization(string username, string password, string realm, string nonce, string method, string uri) + { + // 计算HA1 = MD5(username:realm:password) + string ha1 = CalculateMD5(username + ":" + realm + ":" + password); + // 计算HA2 = MD5(method:uri) + string ha2 = CalculateMD5(method + ":" + uri); + // 计算response = MD5(ha1:nonce:ha2) + string response = CalculateMD5(ha1 + ":" + nonce + ":" + ha2); + + // 构建Authorization头 + return string.Format("Digest username=\"{0}\", realm=\"{1}\", nonce=\"{2}\", uri=\"{3}\", response=\"{4}\"", + username, realm, nonce, uri, response); + } + + /// + /// 计算MD5哈希值 + /// + private string CalculateMD5(string input) + { + using (MD5 md5 = MD5.Create()) + { + byte[] inputBytes = System.Text.Encoding.UTF8.GetBytes(input); + byte[] hashBytes = md5.ComputeHash(inputBytes); + + // 将字节数组转换为十六进制字符串 + System.Text.StringBuilder sb = new System.Text.StringBuilder(); + for (int i = 0; i < hashBytes.Length; i++) + { + sb.Append(hashBytes[i].ToString("x2")); + } + return sb.ToString(); + } + } + + /// + /// 触发图像捕获事件 + /// + protected virtual void OnImageCaptured(ImageEventArgs e) + { + if (ImageCaptured != null) + { + ImageCaptured(this, e); + } + } + } + + /// + /// 图像事件参数 + /// + public class ImageEventArgs : EventArgs + { + /// + /// 捕获的图像 + /// + public Image Image { get; set; } + } +} \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Camera/Camera.csproj b/Windows/CS/Framework4.0/Camera/Camera/Camera.csproj new file mode 100644 index 0000000..4c4d1df --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Camera.csproj @@ -0,0 +1,82 @@ + + + + + Debug + AnyCPU + {1376F939-3A40-4406-8987-467450E40573} + Library + Camera + Camera + v4.0 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + Form + + + Setting.cs + + + + + Setting.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Camera/Program.cs b/Windows/CS/Framework4.0/Camera/Camera/Program.cs new file mode 100644 index 0000000..d1bf0eb --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace Camera +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Setting()); + } + } +} diff --git a/Windows/CS/Framework4.0/Camera/Camera/Properties/AssemblyInfo.cs b/Windows/CS/Framework4.0/Camera/Camera/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..5711e65 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Camera")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Camera")] +[assembly: AssemblyCopyright("Copyright © 2026")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("1376f939-3a40-4406-8987-467450e40573")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.Designer.cs b/Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.Designer.cs new file mode 100644 index 0000000..4b6f604 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.42000 +// +// 对此文件的更改可能导致不正确的行为,如果 +// 重新生成代码,则所做更改将丢失。 +// +//------------------------------------------------------------------------------ + +namespace Camera.Properties +{ + + + /// + /// 强类型资源类,用于查找本地化字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Camera.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 覆盖当前线程的 CurrentUICulture 属性 + /// 使用此强类型的资源类的资源查找。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.resx b/Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.Designer.cs b/Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.Designer.cs new file mode 100644 index 0000000..556f40f --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Camera.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.settings b/Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Windows/CS/Framework4.0/Camera/Camera/Setting.Designer.cs b/Windows/CS/Framework4.0/Camera/Camera/Setting.Designer.cs new file mode 100644 index 0000000..679e5cc --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Setting.Designer.cs @@ -0,0 +1,153 @@ +namespace Camera +{ + partial class Setting + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.picBoxCamera = new System.Windows.Forms.PictureBox(); + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.toolStripButton1 = new System.Windows.Forms.ToolStripButton(); + this.toolStripButton2 = new System.Windows.Forms.ToolStripButton(); + this.listBox1 = new System.Windows.Forms.ListBox(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.picBoxCamera)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.toolStrip1)).BeginInit(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + // 左侧面板宽度 + this.splitContainer1.Panel1MinSize = 300; + // 右侧面板宽度 + this.splitContainer1.Panel2MinSize = 200; + this.splitContainer1.Size = new System.Drawing.Size(850, 469); + this.splitContainer1.SplitterDistance = 500; + this.splitContainer1.TabIndex = 0; + // + // picBoxCamera + // + this.picBoxCamera = new System.Windows.Forms.PictureBox(); + this.picBoxCamera.Dock = System.Windows.Forms.DockStyle.Fill; + this.picBoxCamera.Location = new System.Drawing.Point(0, 0); + this.picBoxCamera.Name = "picBoxCamera"; + this.picBoxCamera.Size = new System.Drawing.Size(500, 469); + this.picBoxCamera.TabIndex = 0; + this.picBoxCamera.TabStop = false; + this.splitContainer1.Panel1.Controls.Add(this.picBoxCamera); + // + // splitContainer2 + // + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Name = "splitContainer2"; + this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; + // 上方面板高度 + this.splitContainer2.Panel1MinSize = 50; + // 下方面板高度 + this.splitContainer2.Panel2MinSize = 100; + this.splitContainer2.Size = new System.Drawing.Size(346, 469); + this.splitContainer2.SplitterDistance = 100; + this.splitContainer2.TabIndex = 0; + // + // toolStrip1 + // + this.toolStrip1 = new System.Windows.Forms.ToolStrip(); + this.toolStrip1.Dock = System.Windows.Forms.DockStyle.Fill; + this.toolStrip1.Location = new System.Drawing.Point(0, 0); + this.toolStrip1.Name = "toolStrip1"; + this.toolStrip1.Size = new System.Drawing.Size(346, 100); + this.toolStrip1.TabIndex = 0; + this.toolStrip1.Text = "toolStrip1"; + // 添加一些示例按钮 + this.toolStripButton1 = new System.Windows.Forms.ToolStripButton(); + this.toolStripButton2 = new System.Windows.Forms.ToolStripButton(); + this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripButton1, + this.toolStripButton2}); + // + // toolStripButton1 + // + this.toolStripButton1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripButton1.Name = "toolStripButton1"; + this.toolStripButton1.Size = new System.Drawing.Size(52, 97); + this.toolStripButton1.Text = "按钮1"; + // + // toolStripButton2 + // + this.toolStripButton2.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text; + this.toolStripButton2.Name = "toolStripButton2"; + this.toolStripButton2.Size = new System.Drawing.Size(52, 97); + this.toolStripButton2.Text = "按钮2"; + this.splitContainer2.Panel1.Controls.Add(this.toolStrip1); + // + // listBox1 + // + this.listBox1 = new System.Windows.Forms.ListBox(); + this.listBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listBox1.Location = new System.Drawing.Point(0, 0); + this.listBox1.Name = "listBox1"; + this.listBox1.Size = new System.Drawing.Size(346, 365); + this.listBox1.TabIndex = 0; + this.splitContainer2.Panel2.Controls.Add(this.listBox1); + this.splitContainer1.Panel2.Controls.Add(this.splitContainer2); + // + // Setting + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(850, 469); + this.Controls.Add(this.splitContainer1); + this.Name = "Setting"; + this.Text = "设置"; + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.picBoxCamera)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.toolStrip1)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.SplitContainer splitContainer1; + private System.Windows.Forms.SplitContainer splitContainer2; + private System.Windows.Forms.PictureBox picBoxCamera; + private System.Windows.Forms.ToolStrip toolStrip1; + private System.Windows.Forms.ToolStripButton toolStripButton1; + private System.Windows.Forms.ToolStripButton toolStripButton2; + private System.Windows.Forms.ListBox listBox1; + } +} + diff --git a/Windows/CS/Framework4.0/Camera/Camera/Setting.cs b/Windows/CS/Framework4.0/Camera/Camera/Setting.cs new file mode 100644 index 0000000..0845680 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Setting.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; + +namespace Camera +{ + public partial class Setting : Form + { + private Camera _camera; + + public Setting() + { + InitializeComponent(); + InitializeForm(); + } + + private void InitializeForm() + { + // 初始化相机对象 + _camera = new Camera(); + + // 为工具栏按钮添加点击事件 + toolStripButton1.Click += ToolStripButton1_Click; + toolStripButton2.Click += ToolStripButton2_Click; + + // 初始化列表框数据 + InitializeListBox(); + + // 设置图片框的默认背景色 + picBoxCamera.BackColor = Color.Gray; + } + + private void InitializeListBox() + { + // 添加一些示例数据到列表框 + listBox1.Items.Add("区域 1 - 红色"); + listBox1.Items.Add("区域 2 - 绿色"); + listBox1.Items.Add("区域 3 - 蓝色"); + listBox1.Items.Add("区域 4 - 灰色"); + } + + private void ToolStripButton1_Click(object sender, EventArgs e) + { + // 按钮1点击事件处理 + MessageBox.Show("按钮1被点击"); + } + + private void ToolStripButton2_Click(object sender, EventArgs e) + { + // 按钮2点击事件处理 + MessageBox.Show("按钮2被点击"); + } + + // 可以根据需要添加更多事件处理方法 + } +} diff --git a/Windows/CS/Framework4.0/Camera/Camera/Setting.resx b/Windows/CS/Framework4.0/Camera/Camera/Setting.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Camera/Setting.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Test/Form1.Designer.cs b/Windows/CS/Framework4.0/Camera/Test/Form1.Designer.cs new file mode 100644 index 0000000..58216d6 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Form1.Designer.cs @@ -0,0 +1,102 @@ +namespace Test +{ + partial class Form1 + { + /// + /// 必需的设计器变量。 + /// + private System.ComponentModel.IContainer components = null; + + /// + /// 清理所有正在使用的资源。 + /// + /// 如果应释放托管资源,为 true;否则为 false。 + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows 窗体设计器生成的代码 + + /// + /// 设计器支持所需的方法 - 不要修改 + /// 使用代码编辑器修改此方法的内容。 + /// + private void InitializeComponent() + { + if (this.components == null) + { + this.components = new System.ComponentModel.Container(); + } + + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.flowLayoutPanel1 = new System.Windows.Forms.FlowLayoutPanel(); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + ((System.ComponentModel.ISupportInitialize)(this.flowLayoutPanel1)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(804, 443); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // flowLayoutPanel1 + // + this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.flowLayoutPanel1.Location = new System.Drawing.Point(0, 443); + this.flowLayoutPanel1.Name = "flowLayoutPanel1"; + this.flowLayoutPanel1.Size = new System.Drawing.Size(804, 33); + this.flowLayoutPanel1.TabIndex = 1; + this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.LeftToRight; + // + // button1 + // + this.button1 = new System.Windows.Forms.Button(); + this.button1.Name = "button1"; + this.button1.Size = new System.Drawing.Size(400, 33); + this.button1.TabIndex = 0; + this.button1.Text = "获取摄像头图像"; + this.button1.UseVisualStyleBackColor = true; + this.button1.Click += new System.EventHandler(this.button1_Click); + // + // button2 + // + this.button2 = new System.Windows.Forms.Button(); + this.button2.Name = "button2"; + this.button2.Size = new System.Drawing.Size(400, 33); + this.button2.TabIndex = 1; + this.button2.Text = "设置"; + this.button2.UseVisualStyleBackColor = true; + this.button2.Click += new System.EventHandler(this.button2_Click); + // + // Form1 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(804, 476); + this.Controls.Add(this.pictureBox1); + this.Controls.Add(this.flowLayoutPanel1); + this.Name = "Form1"; + this.Text = "摄像头图像获取"; + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + ((System.ComponentModel.ISupportInitialize)(this.flowLayoutPanel1)).EndInit(); + this.ResumeLayout(false); + } + + #endregion + + private System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; + private System.Windows.Forms.Button button1; + private System.Windows.Forms.Button button2; + } +} \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Test/Form1.cs b/Windows/CS/Framework4.0/Camera/Test/Form1.cs new file mode 100644 index 0000000..55d9d5e --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Form1.cs @@ -0,0 +1,72 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Windows.Forms; +using Camera; + +namespace Test +{ + public partial class Form1 : Form + { + private Camera.Camera _camera; + + public Form1() + { + InitializeComponent(); + + _camera = new Camera.Camera(); + _camera.ImageCaptured += Camera_ImageCaptured; + } + + private void Camera_ImageCaptured(object sender, ImageEventArgs e) + { + if (InvokeRequired) + { + Invoke(new Action(UpdatePictureBox), e.Image); + } + else + { + UpdatePictureBox(e.Image); + } + } + + private void UpdatePictureBox(Image image) + { + if (pictureBox1.Image != null) + { + pictureBox1.Image.Dispose(); + } + pictureBox1.Image = image; + } + + private void button1_Click(object sender, EventArgs e) + { + if (button1.Text == "获取摄像头图像") + { + button1.Text = "停止获取"; + _camera.Start(); + } + else + { + button1.Text = "获取摄像头图像"; + _camera.Stop(); + } + } + + private void button2_Click(object sender, EventArgs e) + { + Camera.Setting settingForm = new Camera.Setting(); + settingForm.ShowDialog(); + } + + protected override void OnFormClosing(FormClosingEventArgs e) + { + _camera.Stop(); + base.OnFormClosing(e); + } + } +} \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Test/Form1.resx b/Windows/CS/Framework4.0/Camera/Test/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Test/Program.cs b/Windows/CS/Framework4.0/Camera/Test/Program.cs new file mode 100644 index 0000000..8f48897 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Program.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows.Forms; + +namespace Test +{ + static class Program + { + /// + /// 应用程序的主入口点。 + /// + [STAThread] + static void Main() + { + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + Application.Run(new Form1()); + } + } +} diff --git a/Windows/CS/Framework4.0/Camera/Test/Properties/AssemblyInfo.cs b/Windows/CS/Framework4.0/Camera/Test/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..61eff6d --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// 有关程序集的一般信息由以下 +// 控制。更改这些特性值可修改 +// 与程序集关联的信息。 +[assembly: AssemblyTitle("Test")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Test")] +[assembly: AssemblyCopyright("Copyright © 2026")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// 将 ComVisible 设置为 false 会使此程序集中的类型 +//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型 +//请将此类型的 ComVisible 特性设置为 true。 +[assembly: ComVisible(false)] + +// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID +[assembly: Guid("2fae57c2-275d-449f-967d-04edc584bdf1")] + +// 程序集的版本信息由下列四个值组成: +// +// 主版本 +// 次版本 +// 生成号 +// 修订号 +// +// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 +// 方法是按如下所示使用“*”: : +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Windows/CS/Framework4.0/Camera/Test/Properties/Resources.Designer.cs b/Windows/CS/Framework4.0/Camera/Test/Properties/Resources.Designer.cs new file mode 100644 index 0000000..cfde990 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Properties/Resources.Designer.cs @@ -0,0 +1,71 @@ +//------------------------------------------------------------------------------ +// +// 此代码由工具生成。 +// 运行时版本: 4.0.30319.42000 +// +// 对此文件的更改可能导致不正确的行为,如果 +// 重新生成代码,则所做更改将丢失。 +// +//------------------------------------------------------------------------------ + +namespace Test.Properties +{ + + + /// + /// 强类型资源类,用于查找本地化字符串等。 + /// + // 此类是由 StronglyTypedResourceBuilder + // 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。 + // 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen + // (以 /str 作为命令选项),或重新生成 VS 项目。 + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources + { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() + { + } + + /// + /// 返回此类使用的缓存 ResourceManager 实例。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager + { + get + { + if ((resourceMan == null)) + { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Test.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// 覆盖当前线程的 CurrentUICulture 属性 + /// 使用此强类型的资源类的资源查找。 + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture + { + get + { + return resourceCulture; + } + set + { + resourceCulture = value; + } + } + } +} diff --git a/Windows/CS/Framework4.0/Camera/Test/Properties/Resources.resx b/Windows/CS/Framework4.0/Camera/Test/Properties/Resources.resx new file mode 100644 index 0000000..af7dbeb --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Properties/Resources.resx @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/Test/Properties/Settings.Designer.cs b/Windows/CS/Framework4.0/Camera/Test/Properties/Settings.Designer.cs new file mode 100644 index 0000000..a8cf573 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Properties/Settings.Designer.cs @@ -0,0 +1,30 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Test.Properties +{ + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase + { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default + { + get + { + return defaultInstance; + } + } + } +} diff --git a/Windows/CS/Framework4.0/Camera/Test/Properties/Settings.settings b/Windows/CS/Framework4.0/Camera/Test/Properties/Settings.settings new file mode 100644 index 0000000..3964565 --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Properties/Settings.settings @@ -0,0 +1,7 @@ + + + + + + + diff --git a/Windows/CS/Framework4.0/Camera/Test/Test.csproj b/Windows/CS/Framework4.0/Camera/Test/Test.csproj new file mode 100644 index 0000000..143893d --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/Test/Test.csproj @@ -0,0 +1,84 @@ + + + + + Debug + AnyCPU + {2FAE57C2-275D-449F-967D-04EDC584BDF1} + WinExe + Test + Test + v4.0 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + {1376F939-3A40-4406-8987-467450E40573} + Camera + + + + + Form + + + Form1.cs + + + + + Form1.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + \ No newline at end of file diff --git a/Windows/CS/Framework4.0/Camera/tplink.md b/Windows/CS/Framework4.0/Camera/tplink.md new file mode 100644 index 0000000..946be9b --- /dev/null +++ b/Windows/CS/Framework4.0/Camera/tplink.md @@ -0,0 +1,109 @@ +豆干 HTTP 获取图片 +1. 获取图片的过程 +获取图片的流程如下图所示: + + +各个阶段对应的示例报文(使用 Wireshark 抓取): +总共包含 4 个报文(192.168.1.130 为客户端,192.168.1.60 为设备端): + +1) 客户端发送获取图片请求 + +2) 设备端返回需要鉴权报文(其中 WWW-Authenticate 那一行指定了需要使用什么方式鉴权及鉴权相关信息) + +3) 客户端完成鉴权,并再次发送获取图片请求(其中Authorization 那一行即是客户端完成鉴权后的加密信息) + +4) 设备端返回图片 + +2. Postman 示例 +2.1 发出获取图片请求,返回要求鉴权报文,从中获取鉴权所需信息 + +2.2 根据鉴权所需信息生成鉴权信息,添加到请求头的 Authorization 字段中,鉴权信息使用通用 HTTP 认证中的 Digest 模式生成,具体请参考下方 3.2 备注一节 + + +3. 代码示例 +3.1 Python 代码 +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import requests +from hashlib import md5 +from PIL import Image +from io import BytesIO + +IP = "192.168.1.60" +SNAPSHOT_URI = "/snapshot.jpg" +SNAPSHOT_URL = "http://" + IP + SNAPSHOT_URI +USER = "admin" +PASSWD = "tp123456" + +s = requests.Session() +res = s.get(SNAPSHOT_URL) # 尝试获取图片 +if res.status_code == 401: # 需要鉴权 + # 鉴权方式为 WWW-Authenticate Digest + auth_info = res.headers["WWW-Authenticate"] + token = auth_info.split('"') + realm = token[1] + nonce = token[3] + + user_info = USER + ":" + realm + ":" + PASSWD + method = "GET:" + SNAPSHOT_URI + + response = md5( + ( + md5(user_info.encode(encoding="utf-8")).hexdigest() + + ":" + + nonce + + ":" + + md5(method.encode(encoding="utf-8")).hexdigest() + ).encode(encoding="utf-8") + ).hexdigest() + + authorization = ( + "Digest username=\"" + + USER + + "\",realm=\"" + + realm + + "\",nonce=\"" + + nonce + + "\",uri=\"" + + SNAPSHOT_URI + + "\",response=\"" + + response + + "\"" + ) + s.headers["Authorization"] = authorization # 设置鉴权信息 + +res = s.get(SNAPSHOT_URL) # 再次获取图片 +# 保存图片到本地 +im = Image.open(BytesIO(res.content)) +im.save("snapshot.jpg") + +3.2 备注 +鉴权使用的方法是通用 HTTP 认证中的 Digest 模式,详细信息可参考: +https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/WWW-Authenticate + +针对我们的设备,要完成鉴权,需要从设备端返回的要求鉴权报文中提取 WWW-Authenticate 字段的 realm 和 nonce 的值(对下图而言,就是 TP-LINK IP-Camera 和 d48bbb82dfa9e1e543af852b466d5612): + +然后根据上述两个值以及用户名(应为 admin)和密码来生成鉴权字段 Authorization,该字段由以下几个部分组成(其中绿色部分代表恒定不变的,蓝色部分代表从请求鉴权的报文中获取的,橙色部分代表需要实时计算的(下面将说明计算方法)。例如参考上图, 应为 TP-LINK IP-Camera,而 应为 d48bbb82dfa9e1e543af852b466d5612): +Digest username=”admin”,”realm=””,nonce=””,uri=”/snapshot.jpg”,response=”” + + + +response 的计算方法(MD5 表示 MD5 加密): +response = MD5(MD5(::)::MD5(:)) + +例如,对于上述请求鉴权报文而言,有 +变量 值 +username admin +realm TP-LINK IP-Camera +password tp123456 +nonce d48bbb82dfa9e1e543af852b466d5612 +request-method GET +url /snapshot.jpg +所以最终有 +response += +MD5(MD5(admin:TP-LINK IP-Camera:tp123456):d48bbb82dfa9e1e543af852b466d5612:MD5(GET:/snapshot.jpg)) += +8326b7d2f53557bdde755f9899673b6c +