[译]完整的自制防盗监控系统
By robot-v1.0
本文链接 https://www.kyfws.com/applications/a-complete-anti-theft-homemade-surveillance-system-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 20 分钟阅读 - 9632 个词 阅读量 0[译]完整的自制防盗监控系统
原文地址:https://www.codeproject.com/Articles/1175057/A-Complete-Anti-Theft-Homemade-Surveillance-System
原文作者:Miguel Diaz Kusztrich
译文由本站 robot-v1.0 翻译
前言
Be notified in your mobile phone of intruders in your home, and take photos of them
在您的手机中收到有关入侵者的通知,并为他们拍照
How to mount a surveillance system that detects intruders in your home, takes their photos and notifies you on your cell phone, using which you can call the police if necessary and provide them the photos to quickly identify the robbers and increase your chances to recover all the stolen items.
如何安装监视系统,以检测您家里的入侵者,拍摄他们的照片并在您的手机上通知您,使用该系统,您可以在必要时给警察报警,并向他们提供照片,以快速识别强盗并增加恢复所有劫匪的机会被盗的物品.
- 下载ThiefWatcher服务器的可执行文件-2.8 MB(Download the executables of ThiefWatcher server - 2.8 MB)
- 下载完整的ThiefWatcher解决方案的源代码-6.1 MB(Download the source code of the complete ThiefWatcher solution - 6.1 MB)
介绍(Introduction)
在本文中,我将展示一些DIY物品,以安装监视系统,该监视系统可检测到您家里的入侵者,为他们拍照并在手机上通知您,您可以在必要时从那儿报警并按顺序提供照片.快速识别强盗,并增加找回所有被盗物品的机会.(In this article, I will show some DIY stuff to mount a surveillance system that detects intruders in your home, takes photos of them and notifies you on your cell phone, from which you can call the police if necessary and provide them the photos in order to quickly identify the robbers and raise your opportunities to recover all the stolen things.)
当然,除了此软件之外,您还必须提供一些硬件,但是我在家里用相对便宜的材料(不是摄像机,而是摄像机中最昂贵的部分)建造了该系统.但是您可以使用相机来做很多事情,因此这是一项很好而有趣的投资.(Of course, besides this software, you have to provide some hardware, but I have built this system at my home using relatively cheap materials, other than the cameras, which arethe most expensive part of the mounting. But you can do a lot of things with a camera, so it can be a good and funny investment.)
基本上,这是系统架构,包含所有参与元素:(Basically, this is the system schema, with all the participating elements:)
尽管在模式中我代表了一些具体的子系统,但实际上我已经设计了解决方案,以便可以通过实现一个公共接口并使用依赖注入将它们与应用程序链接来独立开发所有这些元素.不同的子系统或协议如下:(Although in the schema I have represented some concrete subsystems, really I have designed the solution so that all those elements can be developed independently, by implementing a common interface and using dependency injection to link them with the application. The different subsystems or protocols are the following:)
- 相机协议(Camera protocol):定义与摄像机的通信(: defines the communication with the video cameras)
- 存储协议(Storage protocol):定义文件传输,图像和控制命令/响应(: defines the file transfer, images and control command / responses)
- 触发协议(Trigger protocol):启动监视系统(: fires-up the surveillance system)
- 报警协议(Alarm protocol):将事件远程传达给用户(: communicates the incidents remotely to the user) 该解决方案使用Visual Studio 2015和4.5版本的.NETFramework实施.(The solution is implemented using Visual Studio 2015 and the 4.5 version of the .NETFramework.)
您可以找到本文的更长版本(You can find a longer version of this article) 这里(here) 在西班牙语中(in Spanish) .由于该站点的文件大小限制为10MB,因此我不得不删除源代码中的许多文件,包括所有NuGet包,(. Due to the file size limits of this site, of 10MB, I have had to delete a lot of files in the source code, all the NuGet packages, the)**对象(obj)**目录和所有二进制文件.尽管可以从Visual Studio还原程序包,但是可能无法重新编译代码.在这种情况下,您可以在上一个链接中从我的网站下载该项目的完整文件集.(directories and all the binaries. Although you can restore the packages from Visual Studio, it is possible that you cannot recompile the code. In that case, you can download the complete set of files of the project from my website, in the previous link.)
硬体(The Hardware)
让我们回顾一下我用来构建系统的硬件.由于应用程序可以通过多种方式扩展,因此您可以使用自己的不同硬件选择进行安装.(Let’s review the hardware I used to build the system in my case. As the application is extensible in many ways, you can use your own different hardware selection to mount it.)
首先,相机.我有两个IP摄像机,每个IP摄像机具有不同的协议.更便宜的是一个conceptornic wifi相机,价格约50€和协议(First, the cameras. I have two IP cameras, each one with a different protocol. The cheaper is a conceptornic wifi camera, with a price about 50€ and protocol) NetWave
cgi.另一个是专业的,具有高性能,但价格也很高.这是一个Axis相机,(cgi. The other is a professional one, with high-performance, but also a very high price. It’s an Axis camera, with) VAPIX
cgi协议.(cgi protocol.)
为了拨打电话,我购买了一个简单的USB AT调制解调器,价格约为17欧元:(In order to make a call to the mobile phone, I have bought a simple USB AT modem, for about 17€:)
当然,作为触发,我使用了(As a trigger I used, of course, an)Arduino的(Arduino)板(约20欧元),存在检测器开关(约10欧元)和一个继电器.由于状态显示开关可在220V电压下工作,因此将其直接连接到Arduino板是个坏主意.因此,我将检测器连接到12V电源,并将电源连接到继电器,继电器充当另一个开关,该继电器闭合5V Arduino电源和输入引脚之间的电路.这样可以完全隔离220V主电源的Arduino板(以及计算机).(board (about 20€), a presence detector switch (about 10€) and a relay. As the presence switch works with 220V, it is a bad idea to connect it directly to the Arduino board. So, I have connected the detector to a12V power source, and the power source to the relay, which acts as another switch, that closes a circuit between the 5V Arduino power and an input pin. This isolates completely the Arduino board (and thus the computer) of the 220V main power source.)
您可以轻松构建这样的继电器电路.只需将12个电源连接到中继线轴,将一根二极管从地线连接到12V线,然后从Arduino端,使用一个输入引脚(PI)作为触发引脚,一个输出引脚(PO)强制电路断开时,输入引脚为0V,并通过5V电源信号激活输入引脚:(You can easily build a relay circuit like this. Simply connect the 12 power source to the relay reel, put a diode from the ground wire to the 12V wire, and, from the Arduino side, use an input pin (PI) as the trigger pin, an output pin (PO) to force the input pin to 0V when the circuit is open, and the 5V power signal to activate the input pin:)
这是Arduino代码,我将引脚28用作输入,将24用作输出,因为在Arduino Mega板上它们靠近5V引脚,但是您可以随意使用.(This is the Arduino code, I used the pin 28 as input and 24 as output, cause in the Arduino Mega board they are near the 5V pin, but you can use which you want to, of course.)
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);
}
最后,尽管这并不是真正的硬件,但我会提到我使用的存储协议.我已经选择(Finally, although this is not really hardware, I will mention the storage protocol I have used. I have chosen) Dropbox
是将照片上传到云端的最简单,最便宜的方法,我还使用这种媒体通过文本文件和数据将通讯客户端与控制中心进行通信.(as the easiest and cheaper way to upload the photos to the cloud, and I use also this media to communicate the mobile clients with the control center, using text files with data in)JSON格式(JSON)格式.(format.)
控制中心(The Control Center)
在里面(In the) ThiefWatcher
在项目中,中央控制应用程序得以实施.它是一个桌面MDI Windows应用程序,基本上具有两种不同的窗口类型.其中之一是控制面板,您可以在其中设置除摄像机的协议以外的所有协议:(project, the central control application is implemented. It is a desktop MDI Windows application, and basically has two different window types. One of them is the control panel, where you can set up all the protocols except those of the cameras:)
顶部窗格用于(The top pane is for the)触发协议(trigger protocol).在这里,您可以选择要使用的协议,并提供具有相应设置的连接字符串(该设置可能因一个协议而异),以及系统必须启动监视模式的开始日期/时间(如果未提供)系统立即启动),终止监视的结束日期/时间,您可以配置检测到入侵者时要拍摄的照片数量以及照片之间的秒数(整数).(. Here, you can select which protocol to use, provide a connection string with the corresponding settings (which can vary from one protocol to another), a start date / time in which the system must start the surveillance mode (if you don’t provide it, the system starts inmediatelly), an end date / time to stop the surveillance, and you can configure the number of photos to be taken when an intruder is detected and the number of seconds between photos (an integer number).)
该窗格下面是(Below this pane is that for the)通知(警报)协议(notifications (alarm) protocol).在下拉列表的右侧以选择协议,您有一个(. At right of the dropdown list to select the protocol, you have a) Test
按钮,您无需进行任何模拟就可以测试此协议.如果协议允许数据传输,还必须提供带有参数设置的字符串连接和可选消息.(button, which allows you to test this protocol without the need to make any simmulation. You must provide also a string connection with the parameter settings, and an optional message in case the protocol allows data transfer.)
底部窗格用于(The bottom pane is for the)存储协议(storage protocol).您具有用于设置参数的连接字符串(如果有)以及用于存储数据的容器名称,该容器名称可以是本地文件夹,FTP文件夹,Azure Blob容器名称等.(. You have a connection string to set up the parameters, if any, and a container name to store the data, which can be a local folder, an FTP folder, an Azure blob container name, etc.)
命令按钮从左到右分别是(The command buttons are, from left to right,)启动Simulacrum(Start Simulacrum),它可以像检测到入侵者一样启动或停止系统,因此您可以测试摄像头和存储协议以及与客户端的通信.在此模式下,不考虑开始日期和结束日期.接下来,(, which starts or stops the system as if an intruder has been detected, so you can test the cameras and storage protocol, and the communications with the clients. In this mode, the start and end date are not taken into account. Next, the) Start
按钮启动或停止实际监视模式.照相机表格中未显示图像(假设没有图像).最后,(button starts or stops the real surveillance mode. No image is shown in the camera forms (is supposed that no one is present). Finally, the) Save
按钮将更改写入配置文件.(button writes the changes in the configuration file.)
在代码使用部分中,我将注释已实现的所有协议的连接字符串参数.(In the code usage section, I will comment the parameters for the connection strings of all the protocols I have implemented.)
关于摄像机协议,每个摄像机的配置都在摄像机窗口中进行,您可以使用(Regarding the camera protocol, the configuration of each camera is performed in the camera window, which you can show using the)文件/新相机…(File / New Camera…)菜单选项.首先,您必须为要添加的摄像机选择正确的摄像机协议,然后,必须提供连接数据,摄像机URL,用户名和密码.然后,您会看到一个这样的窗口:(menu option. First, you have to select the correct camera protocol for the camera you want to add, then, you have to provide the connection data, camera URL, user name and password. Then, you can see a window like this:)
工具栏左侧的第一个按钮是更改访问设置,第二个按钮显示摄像机设置对话框,该对话框以相应的协议实现.然后,您有一个按钮可以启动,其他按钮则可以停止相机,因此您可以在配置相机时观看图像.摄像机ID必须是唯一的并且是强制性的,因为您将使用此ID从客户端中选择摄像机.最后两个按钮用于将摄像机保存在配置文件中或将其删除.(The first button, from the left, of the toolbar, is to change the access settings, the second shows the camera set up dialog box, which is implemented in the corresponding protocol. Then, you have a button to start and other to stop the camera, so you can watch the image while configuring the camera. The camera ID must be unique and is mandatory, as you will use this ID to select the camera from the clients. The last two buttons are to save the camera in the configuration file or to remove it.)
所有这些设置都存储在应用程序中(All those settings are stored in the application)**App.config(App.config)**文件.中的连接字符串(file. The connection strings in the) connectionStrings
`` 部分中的其他协议设置(section, the other protocol settings in the) appSettings
部分.还有两个自定义部分,用于存储协议列表以及不同的摄像机及其设置.(section. There are also two custom sections to store the protocol list and the different cameras and their settings.)
的(The) cameraSection
就像这样:(is like this:)
<camerasSection>
<cameras>
<cameraData id="CAMNW"
protocolName="NetWave IP camera"
connectionStringName="CAMNW" />
<cameraData id="VAPIX"
protocolName="VAPIX IP Camera"
connectionStringName="VAPIX" />
</cameras>
</camerasSection>
每个相机是一个(Each camera is a) cameraData
元素,带有(element, with an) id
属性,一个(attribute, a) protocolName
属性以及相应协议的名称,以及一个(attribute with the name of the corresponding protocol, and a) connectionStringName
连接数据的属性:(attribute for the connection data:) url
,(,) userName
和(and) password
,存储在连接字符串中(, stored in a connection string in the) connectionStrings
部分.(section.)
还有一个(There is also a) protocolsSection
,其中包含已安装协议的列表:(, containing the list of installed protocols:)
<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>
每个协议都有一个(Each protocol has a) name
, 一种(, a) class
识别其用法((to identify their usage () trigger
,(,) alarm
,(,) storage
要么(or) camera
)和一个() and a) type
具有实现协议的类的完整类型.(with the complete type of the class which implements the protocol.)
您可以使用(You can add new protocols to this section using the)文件/安装协议(File / Install Protocol/s…)菜单选项,选择带有协议或协议实现的类库.(menu option, selecting the class library with the protocol or protocols implementation.)
客户(The Clients)
无论您身在何处,该应用程序都必须通知您可能的入侵,因此我已将客户端实现为移动应用程序.快速为几乎所有平台提供应用程序版本的最简单方法是使用(The application has to notify you a possible intrusion wherever you are, so I have implemented the clients as mobile Apps. The easiest way to quickly have versions of an App for almost all platforms is to use) Xamarin
为此,这是我选择的方法.(to do it, so this is the approach I have selected.)
的(The) TWClientApp
PCL(便携式类库)项目包含客户端中几乎所有的代码.在针对不同平台的特定项目中,只有用于保存文件,将相机拍摄的照片保存在手机存储器中的代码,以便您可以将其尽快提供给警察.(PCL (portable class library) project contains almost all the code in the client side. In the specific projects for the different platforms, there is only the code to save files, to save the pictures taken by the cameras in the mobile phone memory, so that you can provide them to the police as soon as possible.)
这是我的第一个移动App项目,因此它不是非常复杂.在这里,我没有使用依赖注入.相反,我只实现了(This is my first mobile App project, so it isn’t very sophisticated. Here, I haven’t used dependency injection. Instead I have implemented only the) Dropbox
存储协议,因此,如果要使用其他协议,则必须更改PCL库中的代码.该协议的优势在于您可以使用(storage protocol, so, if you want to use another one, you have to change the code in the PCL library. This protocol has the advantage that you can use the) Dropbox
实际客户无需使用(actual client to obtain the photos, without using the) ThiefWatcher
客户端(尽管您失去了应用程序控制功能).(client (although you lose the application control capability).)
启动客户端应用程序时,必须按(When you start the client App, you have to press the) Connect
按钮以将标识消息发送到主应用程序:(button in order to send an identification message to the main application:)
然后,将摄像机列表发送到客户端.您可以按相应的按钮选择其中之一:(Then, a list of cameras is sent to the client. You can select one of them pressing the corresponding button:)
您可以观看相机的当前图像.通常,您不能等待真正的视频流,因为上传每个图像可能非常慢.中央控件实时获取帧,但Dropbox最多花费两秒钟来上传每一帧.(You can watch the current image of the camera. Normally, you can’t wait a really video stream, as uploading each image can be very slow. The central control takes the frames in real time, but the Dropbox spends up to two seconds to upload each one.)
您可以使用按钮来启动/停止相机,拍照或结束闹铃模式(在结束闹铃模式之前无需停止摄像机).(You can use the buttons to Start /Stop the camera, take a photo, or end the alarm mode (there is no need to stop the cameras before end the alarm mode).)
这些照片显示在底部的列表中,您可以将其保存到手机或删除它们.(The photos appear in a list at the bottom, and you can save it to the phone or delete them.)
由于没有MAC,因此无法测试iOS版本,但Windows Phone和Android Apps可以正常工作.(I couldn’t test the iOS version, as I don’t have a MAC, but the Windows Phone and Android Apps work fine.)
使用代码(Using the Code)
协议中定义了不同的协议接口(The different protocol interfaces are defined in the) WatcherCommons
项目,在(project, in the) Interfaces
命名空间.相机协议是(namespace. The camera protocol is) IWatcherCamera
,定义如下:(, defined as follows:)
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
:准备好将图像发送到应用程序时是否触发事件处理程序?图像作为位图传递到(: Is the event handler fired when an image is ready to be sent to the application. The image is passed as a Bitmap in the)Image
的属性(property of the)FrameEventArgs
参数.(parameter.)FrameSize
:摄像机图像的当前宽度和高度.(: The current width and height of the camera image.)ConnectionString
:用分号分隔的字符串,用于定义摄像机访问参数.在我实现的协议中,参数为(: a semicolon separated string to define the camera access parameters. In the protocols I have implemented, the parameters are)url
,(,)userName
和(and)password
, 像这样:(, like this:)url =http://192.168.1.20; userName =root; password =root(url=http://192.168.1.20;userName=root;password=root).(.)UserName
,(,)Password
和(and)Uri
:与连接字符串相同.(: Same as in the connection string.)MaxFps
:设置捕获率.(: To set the capture rate.)Status
:如果摄像机正在运行,则为true.(: true if the camera is running.)SetupManager
:与摄像机设置对话框对接.当用户更改摄像机图像大小时,用于在应用程序中触发事件,以便可以正确调整摄像机窗体的大小.(: Interface with the camera settings dialog box. Used to fire an event inthe application when the user changes the camera image size, so that the camera form can be resized properly.)Initialize
:根据需要重置内部状态.(: to reset the internal state as needed.)ShowCameraConfiguration
:显示摄像机配置对话框.它必须不是模态的,以便在相机一次显示图像时可以观看更改.(: shows the camera configuration dialog box. It must be not modal, so that you can watch the changes if the camera is showing images at time.)Start
:开始图像拍摄.这是在单独的线程中执行的,在新帧事件中与相机进行交互时,必须考虑到这一点.(: starts the image capturing. This is carried-out in a separate thread, you have to take this into account when interacting with the camera in the new frame event.)Stop
:停止捕获.(: stop capturing.) 的(The)NetWave
协议是在(protocol is implemented in the)NetWaveProtocol
项目,以及(project, and the)VAPIX
中的协议(protocol in the)VAPIXProtocol
项目.(project.)
触发协议(The trigger protocol,) ITrigger
,如下:(,is as follows:)
public interface ITrigger
{
event EventHandler OnTriggerFired;
string ConnectionString { get; set; }
void Initialize();
void Start();
void Stop();
}
OnTriggerFired
:在检测到触发条件时触发.(: fired when the trigger condition is detected.)ConnectionString
:带有配置参数的字符串.在我实施的协议中(: string with the configuration parameters. In the protocol I have implemented, in the)ArduinoSimpleTriggerProtocol
项目,他们是(project, they are)port
和(and)baudrate
, 像这样:(, like this:)端口=COM4;波特率=9600(port=COM4;baudrate=9600).切记在(. Remember to set the same baud rate in the)Arduino
码.(code.)Initialize
:根据需要重置Intarnal状态.(: to reset the intarnal state as needed.)Start
:开始监听触发条件.这是在单独的线程中完成的.(: start listen for a trigger condition. This is done in a separate thread.)Stop
:停止听.(: stop listening.) 通知协议,(The notification protocol,)IAlarmChannel
,也很简单:(, is simple too:)
public interface IAlarmChannel
{
string ConnectionString { get; set; }
string MessageText { get; set; }
void Initialice();
void SendAlarm();
}
-
ConnectionString
:带有配置参数的字符串.(: string with the configuration parameters.) -
MessageText:
如果协议允许,则发送消息.(message to send, if the protocol allows it.) -
Initialize:
重置内部状态.(to reset the internal state.) -
SendAlarm
:向客户发送通知.(: sends a notificatrion to the clients.) 我已经实现的协议是(The protocols I have implemented are the)ATModemProtocol
项目,该项目使用AT调制解调器拨打一个或多个电话号码,并具有以下配置参数:(project, which dials one or more phone numbers using an AT modem, and has the following configuration parameters:) -
port
:连接调制解调器的COM端口(: the COM port where the modem is connected) -
baudrate
:设置端口波特率(: to set the port baud rate) -
initdelay
:延迟等待拨号之前的毫秒数(: delay in milliseconds to wait before dial) -
number:
以逗号分隔的电话号码列表(comma separated list of phone numbers) -
ringduration
:挂断之前的时间(以毫秒为单位)(: time in milliseconds before hang up) 其他协议使用(The other protocol uses)Skype
要么(or)Lync
通知用户.它在(to notify the user. It is implemented in the)LyncProtocol
项目.连接字符串是用分号分隔的列表(project. The connection string is a semicolon separated list of)Skype
要么(or)Lync
用户地址.你必须有(user addresses. You must have the)Lync
客户端安装在主计算机和客户端上.(client installed on the main computer and on the clients.)
后者是存储协议,该协议使用的数据在(The latter is the storage protocol, the data used by this protocol is defined in the) Data
的命名空间(namespace of the) WatcherCommons
类库.有两个不同的类别,(class library. There are two different classes,) ControlCommand
适用于相机命令:(is for the camera commands:)
[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格式发送和接收.有两个不同的命令,在(The commands are sent and received in JSON format. There are two differentcommnands, passed in the) Command
成员,一个用于向应用程序注册并获取摄像机列表,另一个用于停止警报并将应用程序重置为监视模式.(member, one to register with the application and get the list of cameras and another one to stop the alarm and reset the application to the surveillance mode.)
的(The) ClientID
成员唯一标识每个客户.(member uniquely identifies each client.)
CameraInfo
也将以JSON格式交换有关摄像机的请求和响应:(is to interchange requests and responses regarding the cameras, in JSON format too:)
[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
:相机标识符(: the camera identifier)Active
:相机状态(: the camera state)Photo
:用于请求相机拍照(: used to request to the camera to take a photo)Width
和(and)Height
:相机图像尺寸(: camera image size)ClientID
:客户端唯一标识符(: client unique identifier) 当您请求摄像机列表时,您会收到包含以下内容的响应:(When you request a list of cameras, you receive a response with an array of)CameraInfo
对象,每个摄像机一个.(objects, one for each camera.)
实现协议的接口是(The interface to implement the protocol is) 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
:带有配置参数的字符串(: string with the configuration parameters)ContainerPath
:用于标识文件夹,blob容器名称等.(: to identify a folder, blob container name, etc.)UploadFile
:发送文件(在(: send a file, provided in a)Stream
目的(object)DownloadFile
:在提供的文件中获取文件(: get a file in the provided)Stream
目的(object)DeleteFile
: 删除文件(: deletea file)ExistsFile
:测试文件是否存在(: test if a file exists)ListFiles
:枚举文件夹中的文件,其文件名的开头必须与(: enumerate the files in the folder, the begining of their names must match the)model
参数(parameter)GetCommands
:枚举客户端发送的命令(: enumerate the commands sent by the clients)GetRequests
:枚举客户端发送的摄像头请求(: enumerate the camera requests sent by the clients)SendResponse
:发送命令或摄像机请求的响应(: send a responsefor a command or camera request) 我已经实现了两个存储协议.的(I have implemented two storage protocols. The)DropBoxProtocol
项目实施与之配合使用的协议(project implements the protocol to use with)Dropbox
.在服务器端,这无非是读取和写入文件.(. In the server side, this is nothing more than read and write files to the)Dropbox
夹.由于该文件夹是单独配置的,因此无需连接字符串.(folder. There is no need to connection string, as the folder is configured separately.)
在客户端中,这是实现的协议.稍有不同,该接口在(In the clients, this is the protocol implemented. It is slightly different, the interface is defined in the) TWClientApp
项目:(project:)
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);
}
它是一个异步接口,成员数少于服务器端.实现并不像在服务器中那样容易.我们必须使用(It is an asynchronous interface, and there are less members than that in the server side. The implementation is not as easy as in the server; we have to use the) Dropbox
与之交互的API.实现在类中(API to interact with it. The implementation is in the class) DropBoxStorage
并且,在(and, in the) _accessKey
常量,则必须设置安全密钥以成功建立连接(不要忘记在第一次编译代码之前这样做,因为没有默认值).(constant, you mustset the security key to stablish succesfully the connection (Don’t forget to do so before compile the code the first time, as thereis no default value).)
private const string _accessKey = "";
客户端应用的几乎所有代码都位于(Almost all the code of the client App is in the) TWClientApp
项目,在课堂上(project, in the class) CameraPage
.数据交换协议是通过文件的方式进行的,每个文件都有一个特殊的名称来标识它.这些是不同的文件名模式:(. The interchange protocol of data is by means of files, each with a special name to identify it. These are the different file name patterns:)
- 摄像机仅写入一个帧文件,当客户端读取帧时,它将删除该文件,而服务器可以写入另一帧文件.该文件是jpg图片,名称为(The camera only write one frame file, when the client read the frame, it deletes the file and the server can write another one. The file is a jpg picture, with the name)<摄像机ID> FRAME <客户ID> .jpg(FRAME.jpg).(.)
- 照片的名称相似,可能有不止一张照片.名称模式为:(The name of the photos is similar and there may have more than one photo. The name pattern is:)<摄像机ID> _PHOTO_yyyyMMddHHmmss.jpg(_PHOTO_yyyyMMddHHmmss.jpg).(.)
- 客户端可以一次以JSON文本格式和名称将命令发送到服务器(The clientcan send commands to the server, one at time, in JSON text format and with the name)**cmd_ <客户ID> .json(*cmd_.json*)**.(*.*)
- 服务器获得命令文件后,它将删除该文件,因此客户端可以发送另一个命令,并执行该命令.然后,它写一个响应文件,名称为(When the server get a command file, it deletes the file, so the client can send another command, and it executes the command. Then, it write a response file with the name)**resp_ <客户ID> .json(*resp_.json*)**.(*.*)
- 最终,客户端可以发送JSON格式的相机请求,例如拍照,启动或停止相机,其名称为(Finally, the clientcan send camera requests, by example to take a photo, or to start or stop a camera, in JSON format in a file with the name)**req_ <客户ID> .json(*req_.json*)**.服务器读取文件,将其删除,然后将请求传递给摄像机以对其进行处理,然后,服务器将响应状态写入命令文件中,就像在命令的情况下一样.(*. The server read the file, deletes it, and passes the request to the camera to process it, then, the server write a response file, like in the case of commands, with the camera state.*)
的(*The*)
NetWave
摄像头协议配置对话框非常简单,您可以在(*camera protocol configuration dialog box is very simple, you can read more about this protocol in*) 我的博客(my blog) .(*.*)
至于(As to the) VAPIX
协议,因此更为复杂,因为它是专业相机的协议.我用一个带有所有配置参数(它们很多)的树视图代替了一个带有许多控件的复杂对话框,您可以在其中选择每个参数并更改其值.(protocol, it is more complicated, as it is a protocol for professional cameras. Instead of a complicate dialog box with lots of controls, I have implemented a tree view with all the configuration parameters (they are a lot of them), where you can select every one of them and changethe value.)
就这样,享受解决方案,并感谢您的阅读!!!(And that’s all, enjoy the solution, and thanks for reading!!!)
历史(History)
- 10(10)日(th)2017年3月:初始版本(March, 2017: Initial version)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# .NET Mobile Android cloud Windows Dev surveillance camera sensors 新闻 翻译