• <code id="58gs9"></code>

      <mark id="58gs9"></mark>
      1. 您好£¬欢迎来到源码搜藏网£¡分享精神£¬快乐你我£¡
        [加入VIP] 设为首页 | 收藏本站 | 网站地图 | Sitemap | TAG标签
      2. 首 页
      3. 在线工具
      4. jquery手册
      5. 当前位置£º首页 > 开发教程 > IT博文 > .NET技术 >

        C#实现完整的防盗自制监控系统

        时间£º2018-12-23 13:01 来源£º互联网 作者£º源码搜藏 浏览£º收藏 挑错 推荐 打印

        在您的手机中通知您家中的入侵者£¬并拍摄他们的照片

         

        介绍

        在本文中£¬我将展示一些DIY东西​​£¬用于安装监控系统£¬检测家中的入侵者£¬拍摄照片并通过手机通知您£¬必要时可?#28304;?#30005;?#26696;?#35686;察并提供照片以便快速识别劫匪£¬并提高你恢复所有被盗事物的机会¡£

        当然£¬除了这个软件£¬你必须提供一些硬件£¬但我已经在我家使用相对便宜的材料建造了这个系统£¬如果我们除了相机£¬这是安装中最昂贵的部分¡£但你可以用相机做很多事情£¬所以它可以是一个好的和有趣的投资¡£

        基本上£¬这是系统架构£¬包含所有参与元素£º

        C#实现完整的防盗自制监控系统

        虽然在模式中我已经代表了一些具体的子系统£¬但实际上我已经设?#23631;?#35299;决方案£¬以便通过实现公共接口并使用?#35272;?#27880;入将它们与应用程序链接£¬可以独立开发所有这些元素¡£不同的子系统或协议如下£º

        • 摄像机协议£º定义与摄像机的通信¡£
        • 存储协议£º定义文件传输£¬图像和控制命令/响应¡£
        • 触发协议£º启动监控系统¡£
        • 警报协议£º将?#24405;?#36828;程传达给用户¡£

        该解决方案使用Visual Studio 2015和4.5版的.Net Framework实现¡£

        你可以在我的博客中找到这篇文章的更长版本£¬这里?#24418;?#29677;牙文版本¡£由于此站点的文件大小限制为10MB£¬我不得不删除源代码中的大量文件£¬所有NuGet包£¬obj目录和所有二进制文件¡£虽然您可?#28304;ÓVisual Studio还原包£¬但您可能无法重新编译代码¡£在这种情况下£¬您可?#28304;?#25105;的网站£¬在上一个链接中下载项目的完整文件集¡£

        硬件

        让我们回顾一下我用来构建系统的硬件¡£由于应用程序可以通过多种方式进行扩展£¬因此您可以使用自己的不同硬件选择来安装它¡£

        首先是相机¡£我有两个IP摄像头£¬每个?#21152;?#19981;同的协议¡£更便宜的是一个?#25293;?#24615;的wifi摄像头£¬价格约50€和协议NetWave cgi¡£另一种是专业的£¬具有高性能£¬但也是非常高的价格¡£这是一款采用VAPIX cgi协议的Axis相机¡£

        C#实现完整的防盗自制监控系统

        为了拨打移动电话£¬我买了一个简单的USB AT调制解调器£¬价格约为17欧元£º

        C#实现完整的防盗自制监控系统

        当然£¬作为触发器£¬我使用的是Arduino板£¨约20欧元£©£¬存在探测器开关£¨约10欧元£©和继电器¡£由于存在开关适用于220V£¬因此将其直接连接到Arduino板是一个坏主意¡£因此£¬我已将探测器连接到12V电源£¬并将继电器的电源连接到另一个开关£¬该电源关闭5V Arduino电源和输入引脚之间的电路¡£这完全隔离了220V主电源的Arduino板£¨以及计算机£©¡£

        C#实现完整的防盗自制监控系统

        C#实现完整的防盗自制监控系统

        你可以轻松地建立一个继电器电路¡£只需将12个电源连接到继电器卷轴£¬将二极管从地线连接到12V电线£¬然后从Arduino侧使用输入引脚£¨PI£©作为触发引脚£¬输出引脚£¨PO£©用力电路开路时输入引脚为0V£¬5V电源信号激活输入引脚£º

        C#实现完整的防盗自制监控系统

        这是Arduino代码£¬我使用引脚28作为输入£¬24使用输出£¬因为在Arduino Mega板中它们靠近5V引脚£¬但是你可以使用你想要的£¬当然¡£

        int pin1 = 28;
        int pin0 = 24;
        void setup() {
        // Initialize pins
            pinMode(pin0, OUTPUT); 
            digitalWrite(pin0, LOW);
            pinMode(pin1, INPUT);
            digitalWrite(pin1, LOW);
            Serial.begin(9600);
        }
        void loop() {
            int val = digitalRead(pin1);
            if (val == HIGH) {
                Serial.write(1);
            }
            delay(1000);
        }

        最后£¬虽然这不是真正的硬件£¬但我会提到我使用过的存储协议¡£我选择Dropbox作为将照片上传到云端的最简单£¬最便宜的方式£¬我还使用此?#25945;?#23558;移动客户端与控制中心进行通信£¬使用带有JSON格式数据的文本文件¡£

        控制中心

        在ThiefWatcher项目中£¬实现了中央控制应用程序¡£它是一个桌面MDI Windows应用程序£¬基本上有两种不同的窗口类型¡£其中一个是控制面板£¬您可以在其中设置所?#34892;?#35758;£¬而不是摄像机£º

        C#实现完整的防盗自制监控系统

        顶部窗格用于触发器协议¡£在这里£¬您可以选择要使用的协议£¬提供具有相应设置的连接字符串£¨可?#28304;有?#35758;到另一个不同£©£¬系统必须启动监视模式的开始日期/时间£¨如果您不提供£¬系统启动£¨中间£©£¬停止监视的结束日期/时间£¬您可以配置检测到入侵者时拍摄的照片数量和照片之间的秒数£¨整数£©¡£

        此窗格下方是通知£¨警报£©协议¡£在下拉列表?#20063;?#36873;择协议£¬您有一个测试按钮£¬允许您测?#28304;?#21327;议£¬而无需进行任?#25991;?#25311;¡£您还必须提供带参数设置的字符串连接£¬并在协议允许数据传输的情况下提供可选消息¡£

        底部窗格用于存储协议¡£您有一个连接字符串来设置参数£¨如果有£©和一个用于存储数据的容器名称£¬可以是本地文件夹£¬FTP文件夹£¬Azure blob容器名?#39057;取?/p>

        命令按钮从左到右?#26469;?#20026;Start Simulacrum£¬它启动或停止系统£¬就像检测到入侵者一样£¬因此您可以测试摄像机和存储协议以及与客户端的通信¡£在此模式下£¬不考虑开始和结束日期¡£接下来£¬“ 开始”按钮启动或停止实际监控模式¡£相机形式中没有显示图像£¨假设没有人在场£©¡£最后£¬“ 保存”按钮会在配置文件中写入更改¡£

        在代码使用部分£¬我将评论我已实现的所?#34892;?#35758;的连接字符串的参数¡£

        关于摄像机协议£¬每个摄像机的配置都在摄像机窗口中执行£¬您可以使用File / New Camera ...菜单选项显示摄像机窗口¡£首先£¬您必须为要添加的摄像机选择正确的摄像机协议£¬然后£¬您必须提供连接数据£¬摄像机URL£¬用户名和密码¡£然后£¬你可以看到这样一个窗口£º

        C#实现完整的防盗自制监控系统

        工具栏左侧的第一个按钮用于更改访问设置£¬第二个按钮用于显示相机设置对话框£¬该对话框在相应的协议中实现¡£然后£¬您有一个启动按钮和其他停止相机的按钮£¬因此您可以在配置相机时观看图像¡£摄像机ID必须是唯一的并且是必需的£¬因为您将使用此ID从客户?#25628;?#25321;摄像机¡£最后两个按钮用于将摄像机保存在配置文件中或将其删除¡£

        所有这些设置都存储在应用程序  App.config文件中¡£connectionStrings部分中的连接字符串£¬appSettings部分中的其他协议设置¡£还有两个自定义部分用于存储协议列表以?#23433;?#21516;的摄像机及其设置¡£

        该cameraSection islike这样的£º

        <camerasSection>
            <cameras>
                <cameraData id="CAMNW"
                    protocolName="NetWave IP camera"
                    connectionStringName="CAMNW" />
                <cameraData id="VAPIX"
                    protocolName="VAPIX IP Camera"
                    connectionStringName="VAPIX" />
            </cameras>
        </camerasSection>

        每个照相机是一个cameraData元件£¬具有一个ID属性£¬protocolName与相应协议的名称属性£¬和一个的connectionStringName用于连接数据属性£ºURL£¬userName的和密码£¬存储在一个连接字符串中的ConnectionStrings部分¡£

        还有一个protocolsSection£¬包含已安装协议的列表£º

        <protocolsSection>
            <protocols>
                <protocolData name="Arduino Simple Trigger"
                    class="trigger"
                    type="ArduinoSimpleTriggerProtocol.ArduinoTrigger, ArduinoSimpleTriggerProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <protocolData name="Lync Notifications"
                    class="alarm"
                    type="LyncProtocol.LyncAlarmChannel, LyncProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <protocolData name="AT Modem Notifications"
                    class="alarm"
                    type="ATModemProtocol.ATModemAlarmChannel, ATModemProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <protocolData name="Azure Blob Storage"
                    class="storage"
                    type="AzureBlobProtocol.AzureBlobManager, AzureBlobProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <protocolData name="NetWave IP camera"
                    class="camera"
                    type="NetWaveProtocol.NetWaveCamera, NetWaveProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <protocolData name="VAPIX IP Camera"
                    class="camera"
                    type="VAPIXProtocol.VAPIXCamera, VAPIXProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
                <protocolData name="DropBox Storage"
                    class="storage"
                    type="DropBoxProtocol.DropBoxStorage, DropBoxProtocol, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
            </protocols>
        </protocolsSection>

        每个协议有一个名字£¬一类£¬以确定它们的用法£¨触发£¬报警£¬存储或相机£©和类型与所述完整的类型£¬其实现协议的类¡£

        您可以使用File / Install Protocol / s ...菜单选项向此部分添加新协议£¬选择具?#34892;?#35758;或协议实现的类库¡£

        客户

        无论您身在何处£¬应用程序都必须通知您可能的入侵£¬因此我将客户端实现为移动应用程序¡£几乎所有平台快速拥有应用程序版本的最简单方法是使用Xamarin来执行此操作£¬因此这是我选择的方法¡£

        该TWClientApp PCL£¨便携式类库£©项目包含在客户端几乎所有的代码¡£在不同平台的具体项目中£¬只有代码保存文件£¬将摄像头拍摄的照片保存在手机内存中£¬以便您尽快将其提供给警方¡£

        这是我的第一个移动App项目£¬所以它不是很复?#21360;?#36825;里我没有使用?#35272;?#27880;入¡£相反£¬我只实现了Dropbox存储协议£¬因此£¬如果要使用另一个协议£¬则必须更改PCL库中的代码¡£此协议的优点是您可以使用Dropbox实际客户端获取照片£¬而无需使用ThiefWatcher客户端£¨尽管您失去了应用程序控制功能£©¡£

        启动客户端应用程序时£¬必须按“ 连接”按钮?#25293;?#21521;主应用程序发送标识消息£º

        C#实现完整的防盗自制监控系统

        然后£¬将相机列表发送到客户端¡£您可以按相应的按钮选择其中一个£º

        C#实现完整的防盗自制监控系统

        您可以观看相机的当前图像¡£通常£¬您不能等待真正的视?#30423;ö?#22240;为上传每个图像可能会非常慢¡£中央控制实时获取帧£¬但Dropbox?#21487;?#20256;花费最多两秒?#21360;?/p>

        C#实现完整的防盗自制监控系统

        您可以使用按钮启动/停止相机£¬拍照或结束?#31181;?#27169;式£¨在结束?#31181;?#27169;式之前无需停止相机£©¡£

        照片显示在底部的列表中£¬您可以将其保存到手机或删除它们¡£

        C#实现完整的防盗自制监控系统

        我无法测试iOS版本£¬因为我没有MAC£¬但Windows Phone和Android Apps工作正常¡£

        使用代码

        不同的协议接口在WatcherCommons项目的Interfaces名称空间中定义¡£摄像机协议是IWatcherCamera£¬定义如下£º

        public class FrameEventArgs : EventArgs
        {
            public FrameEventArgs(Bitmap bmp)
            {
                Image = bmp;
            }
            public Bitmap Image { get; private set; }
        }
        public delegate void NewFrameEventHandler(object sender, FrameEventArgs e);
        public interface IWatcherCamera
        {
            event NewFrameEventHandler OnNewFrame;
            Size FrameSize { get; }
            string ConnectionString { get; set; }
            string UserName { get; set; }
            string Password { get; set; }
            string Uri { get; set; }
            int MaxFPS { get; set; }
            bool Status { get; }
            ICameraSetupManager SetupManager { get; }
            void Initialize();
            void ShowCameraConfiguration(Form parent);
            void Start();
            void Close();
        }
        • OnNewFrame£º当图像准备好发送到应用程序时触发?#24405;?#22788;理程序¡£图像在FrameEventArgs参数的Image属性中作为Bitmap传递¡£
        • FrameSize£º摄像机图像的当前宽度和高?#21462;?/li>
        • ConnectionString£º用分号分隔的字符串£¬用于定义摄像机访问参数¡£在我实现的协议中£¬参数是url£¬userName和password£¬如下所示£ºurl = http£º//192.168.1.20; userName = root; password = root¡£
        • UserName£¬Password和Uri£º与连接字符串中的相同¡£
        • MaxFps£º设置捕获率¡£
        • 状态£º如果摄像机正在运行£¬则为true¡£
        • SetupManager£º与摄像机设置对话框的界面¡£用于在用户更改摄像机图像大小时在应用程序中触发?#24405;þ£?#20197;便可以正?#36820;?#25972;摄像机表单的大小¡£
        • 初始化£º根据需要重置内部状态¡£
        • ShowCameraConfiguration£º显示摄像机配置对话框¡£它必须不是模态的£¬因此如果相机正在显示图像£¬您可以观察更改¡£
        • 开始£º开始图像捕获¡£这是在一个单独的线程中执行的£¬您必须在新帧?#24405;?#20013;与相机?#25442;?#26102;将其考虑在内¡£
        • 停止?#21644;£Ö共?#33719;¡£

        该NetWave协议在实施NetWaveProtocol项目和VAPIX在协议VAPIXProtocol项目¡£

        触发器协议ITrigger如下£º

         public interface ITrigger
        {
            event EventHandler OnTriggerFired;
            string ConnectionString { get; set; }
            void Initialize();
            void Start();
            void Stop();
        }
        • OnTriggerFired£º在检测到触发条件时触发¡£
        • ConnectionString£º带?#20449;?#32622;参数的字符串¡£在我已经实现的协议中£¬在ArduinoSimpleTriggerProtocol项目中£¬它们是端口和波特率£¬如下所示£ºport = COM4; baudrate = 9600¡£请记住在Arduino代码中设置相同的波特率¡£
        • 初始化£º根据需要重置intarnal状态¡£
        • 开始£º开始侦听触发条件¡£这是在一个单独的线程中完成的¡£
        • 停止?#21644;?#27490;听¡£

        通知协议IAlarmChannel也很简单£º

        public interface IAlarmChannel
        {
            string ConnectionString { get; set; }
            string MessageText { get; set; }
            void Initialice();
            void SendAlarm();
        } 
        • ConnectionString£º带?#20449;?#32622;参数的字符串¡£
        • MessageText£º如果协议允许£¬则发送消息¡£
        • 初始化£º重置内部状态¡£
        • SendAlarm£º向客户端发送通知¡£

        我实现的协议是ATModemProtocol项目£¬它使用AT调制解调器拨打一个或多个电话号码£¬并具有以下配置参数£º

        • port£º连接调制解调器的COM端口¡£
        • 波特率£º设置端口波特率¡£
        • initdelay£º拨号前等待的延迟时间£¨以毫秒为单位£©¡£
        • number£º逗号分隔的电话号码列表¡£
        • ringduration£º?#19968;?#21069;的时间£¬以毫秒为单位¡£

        另一个协议使用Skype或Lync通知用户¡£它在LyncProtocol项目中实现¡£连接字符串是以分号分隔的Skype或Lync用户地址列表¡£您必须在主计算机和客户端上安装Lync客户端¡£

        后者是存储协议£¬此协议使用的数据在WatcherCommons类库的Data命名空间中定义¡£有两个不同的类£¬ControlCommand用于摄像头命令£º

        [DataContract]
        public class ControlCommand
        {
            public const int cmdGetCameraList = 1;
            public const int cmdStopAlarm = 2;
            public ControlCommand()
            {
            }
            public static ControlCommand FromJSON(Stream s)
            {
                s.Position = 0;
                StreamReader rdr = new StreamReader(s);
                string str = rdr.ReadToEnd();
                return JsonConvert.DeserializeObject<ControlCommand>(str);
            }
            public static void ToJSON(Stream s, ControlCommand cc)
            {
                s.Position = 0;
                string js = JsonConvert.SerializeObject(cc);
                StreamWriter wr = new StreamWriter(s);
                wr.Write(js);
                wr.Flush();
            }
            [DataMember]
            public int Command { get; set; }
            [DataMember]
            public string ClientID { get; set; }
        }

        命令以JSON格式发送和接收¡£在Command成员中传递了两个不同的commnand£¬一个用于向应用程序注册并获取摄像机列表£¬另一个用于停止警报并将应用程序重置为监视模式¡£

        该客户端ID构件唯一地标识每个客户端¡£

        CameraInfo也是以JSON格式?#25442;?#26377;关摄像机的请求和响应£º

        [DataContract]
        public class CameraInfo
        {
            public CameraInfo()
            {
            }
            public static List<CameraInfo> FromJSON(Stream s)
            {
                s.Position = 0;
                StreamReader rdr = new StreamReader(s);
                return JsonConvert.DeserializeObject<List<CameraInfo>>(rdr.ReadToEnd());
            }
            public static void ToJSON(Stream s, List<CameraInfo> ci)
            {
                s.Position = 0;
                string js = JsonConvert.SerializeObject(ci);
                StreamWriter wr = new StreamWriter(s);
                wr.Write(js);
                wr.Flush();
            }
            [DataMember]
            public string ID { get; set; }
            [DataMember]
            public bool Active { get; set; }
            [DataMember]
            public bool Photo { get; set; }
            [DataMember]
            public int Width { get; set; }
            [DataMember]
            public int Height { get; set; }
            [DataMember]
            public string ClientID { get; set; }
        } 
        • ID£º摄像机标识符¡£
        • 活动£º相机状态¡£
        • 照片£º用于要求相机拍照¡£
        • 宽度和高度£º相机图像尺寸¡£
        • ClientID£º客户端唯一标识符¡£

        当您请求摄像机列表时£¬您会收到一个带有一?#30423;ÐCameraInfo对象的响应£¬每个摄像机对应一个¡£

        实现协议的接口是IStorageManager£º

        public interface IStorageManager
        {
            string ConnsecionString { get; set; }
            string ContainerPath { get; set; }
            void UploadFile(string filename, Stream s);
            void DownloadFile(string filename, Stream s);
            void DeleteFile(string filename);
            bool ExistsFile(string filename);
            IEnumerable<string> ListFiles(string model);
            IEnumerable<ControlCommand> GetCommands();
            IEnumerable<List<CameraInfo>> GetRequests();
            void SendResponse(List<CameraInfo> resp);
        } 
        • ConnectionString£º带?#20449;?#32622;参数的字符串¡£
        • ContainerPath£º标识文件夹£¬blob容器名?#39057;取?/li>
        • UploadFile£º发送Stream对象中提供的文件¡£
        • DownloadFile£º在提供的Stream对象中获取文件¡£
        • DeleteFile£º删除文件¡£
        • ExistsFile£º测试文件是否存在¡£
        • ListFiles?#22909;?#20030;文件夹中的文件£¬其名称的开头必须与模型参数匹配  ¡£
        • GetCommands?#22909;?#20030;客户端发送的命令¡£
        • GetRequests?#22909;?#20030;客户端发送的摄像头请求¡£
        • SendResponse£º发送命令或摄像机请求的响应¡£

        我已经实现了两个存储协议¡£该DropBoxProtocol项目实施与使用的协议的Dropbox¡£在服务器端£¬这只是读取和写入Dropbox文件夹的文件¡£不需要连接字符串£¬因为文件夹是单独配置的¡£

        在客户端中£¬这是实现的协议¡£它略有不同£¬界面在TWClientApp项目中定义£º

        public interface IStorageManager
        {
            Task DownloadFile(string filename, Stream s);
            Task DeleteFile(string filename);
            Task<bool> ExistsFile(string filename);
            Task<List<string>> ListFiles(string model);
            Task SendCommand(ControlCommand cmd);
            Task SendRequest(List<CameraInfo> req);
            Task<List<CameraInfo>> GetResponse(string id);
        } 

        它是一个异步接口£¬成员数少于服务器端¡£实现并不像服务器那么容易; 我们必须使用Dropbox API与之?#25442;¥¡?#23454;现在DropBoxStorage类中£¬并且在_accessKey常量中£¬您必须将安全密钥设置为成功建立连接£¨在第一次编译代码之?#23433;?#35201;忘记这样做£¬因为没有默?#29616;“ú©¡?/p>

        private const string _accessKey = ""; 

        客户端App的几乎所有代码都在TWClientApp项目中£¬在CameraPage类中¡£数据的?#25442;?#21327;议是通过文件£¬每个文件?#21152;?#19968;个特殊的名称来识别它¡£这些是不同的文件名模式£º

        • 摄像机只写一个帧文件£¬当客户端读取帧时£¬它删除文件£¬服务器可以写另一个¡£该文件是jpg图片£¬名称为<CAMERA ID> _FRAME_ <CLIENT ID> .jpg¡£
        • 照片的名称相似£¬可能有多张照片¡£名称模式为£º<CAMERA ID> _PHOTO_yyyyMMddHHmmss.jpg¡£
        • 客户端可以以JSON文本格式和名称cmd_ <CLIENT ID> .json将命令一次发送到服务器¡£
        • 当服务器获取命令文件时£¬它会删除该文件£¬因此客户端可以发送另一个命令£¬并执行该命令¡£然后£¬它编写一个名为resp_ <CLIENT ID> .json的响应文件¡£
        • 最后£¬客户端可以发送相机请求£¬例如拍摄照片£¬或以JSON格式在名为req_ <CLIENT ID> .json的文件中启动或停止相机¡£服务器读取文件£¬删除它£¬并将请求传递给摄像机进行处理£¬然后£¬服务器写入响应文件£¬就像命令一样£¬具有摄像机状态¡£

        该NetWave相机协议配置对话框非常简单£¬你可以阅读更多关于此协议中我的博客¡£

        至于VAPIX协议£¬它更复杂£¬因为它是专业相机的协议¡£我没有使用包含大量控件的复杂对话框£¬而是实现了一个包含所?#20449;?#32622;参数的树视图£¨它们是很多配置参数£©£¬您可以在其中选择每个参数并更改值¡£您?#37096;?#20197;在我的博客中阅读更多相关信息¡£

        这就是全部£¬享受解决方案£¬并?#34892;?#38405;读£¡

        C#实现完整的防盗自制监控系统转载
        标签£º网站源码
        ´ó¸»ÎÌÆåÅÆÓéÀÖ¹ÙÍø

      6. <code id="58gs9"></code>

          <mark id="58gs9"></mark>

          1. <code id="58gs9"></code>

              <mark id="58gs9"></mark>