开源倾情奉献:基于.NET打造IP智能网络视频监控系统 ---- 系列文章
基于.NET打造IP智能网络视频监控系统
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
OptimalVision网络视频监控系统
OptimalVision(OV)网络视频监控系统(Video Surveillance System),是一套基于.NET、C#、WCF、WPF等技术构建的IP网络视频监控系统。设计与实现该系统的初衷是希望在家用电脑中部署该系统,连接本地或局域网设备,通过浏览器或手机客户端浏览宝宝实时视频,也就是俗称的“宝宝在线”或“家庭看护”。
但由于业余时间总是有限,完成系统中的服务、配置、采集、传输和桌面GUI部分后,继续完成后续移动客户端的动力与兴趣明显减弱,尤其是宝宝出生后的很长一段时间内基本没有进展,逐渐地演变为演练和测试所关注技术和模式的实验性项目。
开源倾情奉献系列链接
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
目录
OV系统的设计要求
- 系统平台要求部署在Windows操作系统,适宜家庭用户安装使用。
- 系统服务需要支持自启动、自发现、自组网功能,方便用户使用。
- 系统桌面客户端需简单易用,配置与浏览多路视频方便。
- 系统支持连接USB摄像头、WebCam、JPEG摄像机、MJPEG摄像机等。
- 摄像机可部署和接入在不同的主机电脑上,由桌面客户端进行配置管理。
- 系统提供基于HTTP发布的视频和图片,支持浏览器、移动客户端访问。
OV系统的技术选择
- 系统平台基于.NET/C#构建
- 系统服务间采用WCF技术通信
- 系统桌面客户端采用WPF技术构建
- 系统直接采用裸图对帧率要求极低
- 系统采用RTP封装视频数据包UDP传输
- 系统提供HTTP REST API服务
- 系统采用文件数据库存储数据
- 系统支持浏览器和移动客户端访问
OV系统架构设计
OV系统已实现的服务
OV系统主要业务流程
OV桌面客户端架构
OV桌面客户端截图
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
================================================================================================
开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
开源倾情奉献系列链接
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
这是什么系统?
OptimalVision(OV)网络视频监控系统(Video Surveillance System),是一套基于.NET、C#、WCF、WPF等技术构建的IP网络视频监控系统。设计与实现该系统的初衷是希望在家用电脑中部署该系统,连接本地或局域网设备,通过浏览器或手机客户端浏览宝宝实时视频,也就是俗称的“宝宝在线”或“家庭看护”。
详情参考博文《基于.NET打造IP智能网络视频监控系统》。
更多系统截图请参考博文《基于.NET打造IP智能网络视频监控系统》。
为什么开源?
由于业余时间总是有限,完成系统中的服务、配置、采集、传输和桌面GUI部分后,继续完成后续移动客户端的动力与兴趣明显减弱,尤其是宝宝出生后的很长一段时间内基本没有进展,逐渐地演变为演练和测试所关注技术和模式的实验性项目。
总结了几点开放源代码的原因:
- 社区分享。独乐乐不如众乐乐,孤独腐朽的代码没有意义,与社区分享和探讨也是一种乐趣。
- 精力有限。利用业余时间构建,挤占的是陪家人和孩子的时间,要不也不会积累了三年。
- 知识积累。据说自己查看六个月前写的代码,如果感觉需要改进,则就成长了。
- 拓展视野。个人的视角总是短视,接受更多人的批评与指正,可以促进学习和拓展视野。
代码在哪里?
代码托管在 GitHub 网站,所有代码基于 Microsoft .NET Framework 4.0 编译。
代码目录结构
下面是源代码目录结构:
- assets - 系统使用到的资源,例如图片等
- bin - 系统编译输出目录
- Debug - Debug模式输出目录
- build - 编译系统脚本
- docs - 系统设计和文档
- lib - 系统引用的类库
- src - 系统代码
- Crust - MVVM模式框架(改编自 MVVM Light Toolkit)
- Foundation - 系统基础类库(参考《开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍》)
- Knifer - 命令行工具集(参考《开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集》)
- Rukbat - 视频监控系统代码
- Common - 前端和后端通用代码
- Service - WCF服务代码(参考《开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍》)
- GUI - WPF客户端代码(参考《开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍》)
- tests- 各种测试
- tools - 各种工具,例如清理编译目录脚本等
参考了哪些类库?
下面罗列了系统所学习、引用、参考、改编、摘抄的开源类库的不完全列表。
- AForge.NET
- Accord.NET
- NAudio
- nVLC
- Speex
- C# WebServer
- FFmpeg
- FFmpeg.NET
- Flowplayer
- iSpy
- ZoneMinder
- ONVIF Device Manager
- Google GData
- GMap.NET
- Json.NET
- Dynamic Json
- Hammock
- AutoMapper
- SocialKit / LightRest
- Microsoft Enterprise Library
- Microsoft Unity
- System.Data.SQLite
- RavenDB
- RaptorDB
- MongoDB
- MongoDB C# Driver
- Windows Presentation Foundation (WPF)
- MVVM Light Toolkit
- Caliburn.Micro
- MEFedMVVM
- MVVM Foundation
- Phoenix MVVM
- WPF MediaKit
- WPF Multiple Document Interface (MDI)
- MDI Container for WPF
- AvalonDock
- WPF Google Map Control
- WPFSpark
- WPF 3DTools
- Odyssey WPF Controls
- Extended WPF Toolkit™ Community Edition
- Calendar Control in WPF
- patterns & practices: Prism
- Facebook Developer Toolkit
- Microsoft Health Common User Interface (CUI)
- Mahapps.Metroa UI Toolkit for WPF
- Spark View Engine
- ReactiveUI
- CommonServiceLocator
- Ninject
- StructureMap
- NetMQ
- FunnelWeb
- Quartz.NET
- Task Scheduler Engine
- SuperSocket
- CommonLibrary.NET
- NSubstitute
GitHub 本周上榜,感谢各位朋友的支持。
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
=========================================================================================================
开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
开源倾情奉献系列链接
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
基础类库介绍
基础类库目录结构及名空间内容描述
- Foundation
- Common
- Gimela.Common.Configuration - 配置文件处理
- Gimela.Common.Consts - 系统常用恒量
- Gimela.Common.Cultures - 系统 Culture 封装
- Gimela.Common.ExceptionHandling - 通用 Excepton 处理封装
- Gimela.Common.Logging - 通用 Logging 封装
- Data
- Gimela.Data.DataStructures - 二叉树,B+数实现,参考《你曾实现过二叉树吗》,参考 RaptorDB
- Gimela.Data.Json - Json 序列化实现,参考 RaptorDB
- Gimela.Data.JsonExtension - Dynamic Json 移植
- Gimela.Data.MagpieDatabase - NoSQL 文档数据库,参考 RaptorDB
- Gimela.Data.Mapping - AutoMapper 移植
- Gimela.Data.Repository - Repository 模式,参考《EntityFramework用法探索(四)Repository和UnitOfWork》
- Gimela.Data.SparrowDatabase - 文件数据库,参考《C#实现文件数据库》
- Infrastructure
- Gimela.Infrastructure.AsyncModel - 异步模型实现
- Gimela.Infrastructure.Messaging - MVVM 消息通信机制
- Gimela.Infrastructure.Patterns - 模式实现,包括 Flyweight,SmartQueue,WeakAction, Singleton 等
- Gimela.Infrastructure.ResourceLocation - Service Locator 模式实现,参考《Service Locator 模式》
- Gimela.Infrastructure.Serialization - 常用序列化实现
- Management
- Gimela.Management - WMI 实现
- Media
- Gimela.Media.Imaging - AForge.NET 移植
- Gimela.Media.Utilities - AForge.NET 移植
- Gimela.Media.Video - AForge.NET 移植
- Gimela.Media.Video.DirectShow - AForge.NET 移植
- Gimela.Media.Video.VFW - AForge.NET 移植
- Gimela.Media.Vision.Motion - AForge.NET 移植
- Net
- Gimela.Net.Http - Http Server 实现,C# WebServer 移植
- Gimela.Net.Rtp - RTP(RFC3550)实现
- Gimela.Net.Sockets - TCP/UDP 通信实现
- Presentation
- Gimela.Presentation.Controls - WPF 通用控件实现
- Gimela.Presentation.Shapes - 常用 WPF XMAL 形状
- Gimela.Presentation.Skins - WPF 皮肤实现
- Gimela.Presentation.Transitions - WPF View 转换实现
- Gimela.Presentation.Windows - WPF Window 窗体的实现
- Security
- Gimela.Security - 加密及随机数
- ServiceModel
- Gimela.ServiceModel.ChannelManagement - WCF 通道管理
- Gimela.ServiceModel.ManagedDiscovery - WCF 服务自发现(WCF Discovery)
- Gimela.ServiceModel.ManagedHosting - WCF 服务宿主
- Gimela.ServiceModel.ManagedService - WCF 托管服务
- Streaming
- Gimela.Streaming.MJpegStreamingServer - MJPEG流化处理,参考《C#开源实现MJPEG流传输》
- Tasks
- Gimela.Tasks - 任务调度,包括基于 Linux CronTab 模式的实现,参考 Quartz.NET
- Text
- Gimela.Text - 基于文本的处理
- Gimela.Text.Validation - 文本验证规则
- Common
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
=========================================================================================================
开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
开源倾情奉献系列链接
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
命令行工具
为便于平时代码管理和一些特殊需求,伴随系统开发了一系列命令行工具,主要参考 Linux 系统 shell 命令实现。
- addtext - 在文件的初始位置添加文本
- base64 - 将字符串转换为 Base64 编码
- cat - 显示文件内容
- checksum - 检查文本或文件的校验和
- count - 检索目录中指定类型文件的数量
- encode - 将文件编码或更改编码
- env - 显示系统环境变量信息
- extract - 在所有文件中抽取符合模式匹配规则的文本
- find - 在目录中查找文件
- grep - 在文件中查找符合模式匹配规则的行
- head - 显示文件内容的前几行
- join - 将多个文件合并成一个文件
- kill - 杀掉进程
- ls - 显示目录中的内容
- ps - 显示进程状态
- rm - 删除文件
- rmdir - 删除目录
- rename - 重命名指定文件
- replace - 在文件中替换文本
- select - 在目录中查找指定类型的文件
- sort - 将文件中的文本排序
- split - 将一个文件分割成多个文件
- tail - 显示文件的尾部内容
- uniq - 移除文件中的重复行
扩展参考《C#开源文件实时监控工具Tail&TailUI》
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
=====================================================================================================
开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
开源倾情奉献系列链接
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
服务端介绍
目前在服务端实现了 4 个 WCF 服务:
- ServiceDiscovery(简称 SVD)
- DeviceConnector(简称 DVC)
- DeviceProfile(简称 DPS)
- MediaPublisher(简称 MPS)
服务建议启动顺序
- SVD - 服务发现目前有时后启动不太稳定,暂时没有调试这个问题。
- DVC
- DPS
- MPS
Service Discovery Service
SVD 服务实现 WCF Discovery ,当有服务上线时接收注册,并通过服务接口实现向外提供检索指定类型服务的功能。
1 [ServiceContract(SessionMode = SessionMode.Allowed)] 2 [ManagedServiceContract] 3 public interface IServiceDiscoveryService 4 { 5 [FaultContract(typeof(ServiceDiscoveryServiceFault))] 6 [OperationContract] 7 GetServicesResponse GetServices(GetServicesRequest request); 8 }
Device Connector Service
DVC 服务负责提供接口创建、连接、保活摄像机设备。
- 使用 Gimela.Data.MagpieDatabase 文档数据库进行本地数据存取。
- 使用 Gimela.Media.Video 进行媒体流数据的建立。
- 使用 Gimela.Net.Rtp 进行媒体流的封装。
- 使用 Gimela.Net.Sockets 进行媒体流的传输。
1 [ManagedServiceContractAttribute] 2 [ServiceContract(SessionMode = SessionMode.Allowed, CallbackContract = typeof(IDeviceConnectorCallbackService))] 3 public interface IDeviceConnectorService 4 { 5 /// <summary> 6 /// 获取摄像机源列表 7 /// </summary> 8 /// <param name="request"></param> 9 /// <returns></returns> 10 [OperationContract] 11 [FaultContract(typeof(DeviceConnectorServiceFault))] 12 GetCameraFiltersResponse GetCameraFilters(GetCameraFiltersRequest request); 13 14 /// <summary> 15 /// 获取桌面源列表 16 /// </summary> 17 /// <param name="request"></param> 18 /// <returns></returns> 19 [OperationContract] 20 [FaultContract(typeof(DeviceConnectorServiceFault))] 21 GetDesktopFiltersResponse GetDesktopFilters(GetDesktopFiltersRequest request); 22 23 /// <summary> 24 /// 获取指定的摄像机 25 /// </summary> 26 /// <param name="request"></param> 27 /// <returns></returns> 28 [OperationContract] 29 [FaultContract(typeof(DeviceConnectorServiceFault))] 30 GetCameraResponse GetCamera(GetCameraRequest request); 31 32 /// <summary> 33 /// 获取全部的摄像机 34 /// </summary> 35 /// <param name="request"></param> 36 /// <returns></returns> 37 [OperationContract] 38 [FaultContract(typeof(DeviceConnectorServiceFault))] 39 GetCamerasResponse GetCameras(GetCamerasRequest request); 40 41 /// <summary> 42 /// 创建摄像机 43 /// </summary> 44 /// <param name="request"></param> 45 /// <returns></returns> 46 [OperationContract] 47 [FaultContract(typeof(DeviceConnectorServiceFault))] 48 CreateCameraResponse CreateCamera(CreateCameraRequest request); 49 50 /// <summary> 51 /// 修改摄像机 52 /// </summary> 53 /// <param name="request"></param> 54 /// <returns></returns> 55 [OperationContract] 56 [FaultContract(typeof(DeviceConnectorServiceFault))] 57 UpdateCameraResponse UpdateCamera(UpdateCameraRequest request); 58 59 /// <summary> 60 /// 删除摄像机 61 /// </summary> 62 /// <param name="request"></param> 63 /// <returns></returns> 64 [OperationContract] 65 [FaultContract(typeof(DeviceConnectorServiceFault))] 66 DeleteCameraResponse DeleteCamera(DeleteCameraRequest request); 67 68 /// <summary> 69 /// 检测摄像机 70 /// </summary> 71 /// <param name="request"></param> 72 /// <returns></returns> 73 [OperationContract] 74 [FaultContract(typeof(DeviceConnectorServiceFault))] 75 PingCameraResponse PingCamera(PingCameraRequest request); 76 77 /// <summary> 78 /// 获取摄像机最新的快照图像 79 /// </summary> 80 /// <param name="request"></param> 81 /// <returns></returns> 82 [OperationContract] 83 [FaultContract(typeof(DeviceConnectorServiceFault))] 84 GetCameraSnapshotResponse GetCameraSnapshot(GetCameraSnapshotRequest request); 85 86 /// <summary> 87 /// 获取已发布摄像机的信息 88 /// </summary> 89 /// <param name="request"></param> 90 /// <returns></returns> 91 [OperationContract] 92 [FaultContract(typeof(DeviceConnectorServiceFault))] 93 GetPublishedCamerasResponse GetPublishedCameras(GetPublishedCamerasRequest request); 94 95 /// <summary> 96 /// 发布摄像机视频流至指定接收器 97 /// </summary> 98 /// <param name="request"></param> 99 /// <returns></returns> 100 [OperationContract] 101 [FaultContract(typeof(DeviceConnectorServiceFault))] 102 PublishCameraResponse PublishCamera(PublishCameraRequest request); 103 104 /// <summary> 105 /// 取消发布摄像机视频流 106 /// </summary> 107 /// <param name="request"></param> 108 /// <returns></returns> 109 [OperationContract] 110 [FaultContract(typeof(DeviceConnectorServiceFault))] 111 UnpublishCameraResponse UnpublishCamera(UnpublishCameraRequest request); 112 113 /// <summary> 114 /// 发布的摄像机保活机制 115 /// </summary> 116 /// <param name="request">摄像机保活机制请求消息</param> 117 /// <returns>摄像机保活机制响应消息</returns> 118 [OperationContract] 119 [FaultContract(typeof(DeviceConnectorServiceFault))] 120 KeepPublishedCameraAliveResponse KeepPublishedCameraAlive(KeepPublishedCameraAliveRequest request); 121 }
Device Profile Service
DPS 服务暴露简洁的接口,对外提供摄像机的基本信息,主要用以屏蔽或代理 DVC 服务。
1 /// <summary> 2 /// 设备信息服务接口 3 /// </summary> 4 [ManagedServiceContractAttribute] 5 [ServiceContract(SessionMode = SessionMode.Allowed)] 6 public interface IDeviceProfileService 7 { 8 /// <summary> 9 /// 获取全部摄像机的信息 10 /// </summary> 11 /// <param name="request">获取全部摄像机的请求信息</param> 12 /// <returns>全部摄像机的响应信息</returns> 13 [OperationContract] 14 [FaultContract(typeof(DeviceProfileServiceFault))] 15 GetCamerasResponse GetCameras(GetCamerasRequest request); 16 17 /// <summary> 18 /// 获取摄像机的信息 19 /// </summary> 20 /// <param name="request">获取摄像机的请求信息</param> 21 /// <returns>摄像机的响应信息</returns> 22 [OperationContract] 23 [FaultContract(typeof(DeviceProfileServiceFault))] 24 GetCameraResponse GetCamera(GetCameraRequest request); 25 }
Media Publisher Service
MPS 服务负责配置摄像机的媒体流的发布。
1 [ManagedServiceContractAttribute] 2 [ServiceContract(SessionMode = SessionMode.Allowed)] 3 public interface IMediaPublisherService 4 { 5 /// <summary> 6 /// 获取已发布摄像机的信息 7 /// </summary> 8 /// <param name="request"></param> 9 /// <returns></returns> 10 [OperationContract] 11 [FaultContract(typeof(MediaPublisherServiceFault))] 12 GetPublishedCamerasResponse GetPublishedCameras(GetPublishedCamerasRequest request); 13 14 /// <summary> 15 /// 发布摄像机视频流至指定接收器 16 /// </summary> 17 /// <param name="request"></param> 18 /// <returns></returns> 19 [OperationContract] 20 [FaultContract(typeof(MediaPublisherServiceFault))] 21 PublishCameraResponse PublishCamera(PublishCameraRequest request); 22 23 /// <summary> 24 /// 取消发布摄像机视频流 25 /// </summary> 26 /// <param name="request"></param> 27 /// <returns></returns> 28 [OperationContract] 29 [FaultContract(typeof(MediaPublisherServiceFault))] 30 UnpublishCameraResponse UnpublishCamera(UnpublishCameraRequest request); 31 }
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
=============================================================================================
开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
开源倾情奉献系列链接
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(一)开放源代码
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(二)基础类库介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(三)命令行工具集
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(四)服务端介绍
- 开源倾情奉献:基于.NET打造IP智能网络视频监控系统(五)客户端介绍
客户端介绍
系统 C/S 架构客户端采用 WPF 技术并基于 MVVM 模式实现。
主要分为 3 部分:
- Common - 通用控件、验证规则等
- Modules - 业务功能模块
- Applications - 最终呈现应用
业务功能模块
- UIMessage - MVVM 模式中的消息传递
- Navigation - 系统导航菜单
- SkinConfiguration - UI 皮肤设置
- UserManagement - 系统登录和用户管理
- DeviceConfiguration - 设备管理
- LiveVideo - 实时视频
- PublishMedia - 媒体流发布
- Widgets - 小部件,例如 About 页面
服务连接
GUI 通过调用服务发现接口来获取需要的服务连接。
1 namespace Gimela.Rukbat.ServiceDiscovery.Contracts.ServiceContracts 2 { 3 [ManagedServiceContractAttribute] 4 [ServiceContract(SessionMode = SessionMode.Allowed)] 5 public interface IServiceDiscoveryService 6 { 7 [OperationContract] 8 [FaultContract(typeof(ServiceDiscoveryServiceFault))] 9 GetServicesResponse GetServices(GetServicesRequest request); 10 } 11 }
例如连接调用 DVC 服务:
1 GetCamerasResponse response = 2 ServiceProvider.GetService<IDeviceConnectorService, IDeviceConnectorCallbackService>( 3 ViewModelLocator.ServiceClient, 4 ViewModelLocator.SelectedService.HostName, 5 ViewModelLocator.SelectedService.Uri.ToString() 6 ).GetCameras(request);
本文为 Dennis Gao 原创技术文章,发表于博客园博客,未经作者本人允许禁止任何形式的转载。
出处:https://www.cnblogs.com/gaochundong/tag/Video%20Surveillance/
关注我】。(●'◡'●)
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/13260247.html
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!
posted on 2020-07-07 13:30 jack_Meng 阅读(1899) 评论(0) 编辑 收藏 举报