程序设计

智能家居控制系统服务端(毕设)

Ⅰ.服务端系统界面设计(Interface design of system)

· Visual studio 2017

设计采用Visual studio 2017进行开发,Visual Studio是微软公司为开发者提供的开发工具包,其中集成了多种编程语言的IDE,还包括UML工具,代码管控工具等,随着其不断的版本迭代,许多新的功能比如跨平台的开发,WEB服务以及云开发等逐渐加入开发工具中,使得Visual studio逐渐成为最受开发者欢迎的开发工具包。

系统设计采用C#语言编写。C#是一款基于C和C++的编程语言。并且为了达到安全,稳定,高效,简单的要求,C#并未保留C和C++中的一些特性,比如指针的使用,但是其依旧为一门面向对象的编程语言,并且还提供了更多的数据类型。与前两者最重要的不同点是C#在微软的支持下可以使用.NET与.ASP进行高效快速的图形界面开发。

在服务端设计开发中,除了与数字图像处理有关的部分采用独立运行的C++语言编写,其余功能(数据库操作,Socket通讯等)均与图形操作界面的设计保持统一,采用C#语言编写。

· 系统界面设计开发

整个服务端系统界面分为三个部分,一是软件系统主界面,二是系统本地服务的界面,包括(视频信号图像实时显示和数据库数据可视化显示),三是与Socket通讯服务有关的界面。

软件系统主界面主要是用于提供各个功能的模块,包括系统登陆(获得系统的使用权),Socket通讯,视频连接和数据库(数据可视化),分别为对应功能的实现。

图 1-1 服务端系统Main界面
Figure 1-1 Main interface of server system

视频连接服务为测试系统与家居视频传输服务的连接属性。为后续基于数字图像处理的服务提供支持,比如人脸识别认证登录和手势指令识别。

图 1-2 视频连接服务界面
Figure 1-2 Video connection service interface

其中系统登录功能为系统本身的安全性验证,旨在获得对整个操作系统的操作和访问权限,只有通过验证的用户才能进入其他操作界面开启相关服务与功能。数据库功能为直接访问数据库进行数据展示的服务。数据库中一共定义了3个表格,数据库访问服务则将这3个表格进行可视化操作,供访问之直接查看数据。数据库的访问亦需要通过登录操作,人脸识别登录无操作界面,独立运行于一个EXE程序,仅账号密码登录具有图形操作界面。在对应输入框输入对应信息即可完成登录。

图 1-3 系统登录界面
Figure 1-3 System login interface
图 1-4 用户数据表界面
Figure 1-4 Data sheet interface for userdata
图 1-5 操作数据表界面
Figure 1-5 Data sheet interface for operation
图 1-6 传感器数据表界面
Figure 1-6 Data sheet interface for sensor data

Socket通讯为整个系统的主要操作界面,整个系统最重要的服务就运行在此操作界面下。其中最基础的包括与客户端进行Socket通讯和与监测端Zigbee网络进行通讯(数据通讯与IP端口绑定等操作)。除此之外还有云端转发程序的连接,ONENET数据上报服务以及手势指令识别操作。其所含服务运行状态数据均在此窗口下显示,类似于一款操作系统的LOG信息输出。使用者可以快色根据状态信息了解当前系统运行状态。

图 1-7 Socket通讯界面
Figure 1-7 Socket communication interface

Ⅱ. 服务端通讯模块设计(communication of system)

· Socket通讯

Socket又称套接字,是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。

socket 的诞生是为了应用程序能够更方便的将数据经由传输层来传输,所以它本质上就是对 TCP/IP 的运用进行了一层封装,然后应用程序直接调用 socket API 即可进行通信。它分为 2 个部分,服务端需要建立 socket 来监听指定的地址,然后等待客户端来连接。而客户端则需要建立 socket 并与服务端的 socket 地址进行连接。

图 2-8 Socket通讯原理
Figure 2-8 Principle of Socket Communication

以服务器端为例。服务器端先初始化Socket,然后与端口绑定(bind),对端口进行监听(listen),调用accept阻塞,等待客户端连接。在这时如果有个客户端初始化一个Socket,然后连接服务器(connect),如果连接成功,这时客户端与服务器端的连接就建立了。客户端发送数据请求,服务器端接收请求并处理请求,然后把回应数据发送给客户端,客户端读取数据,最后关闭连接,一次交互结束。

图 2-9 Socket通讯网络层次
Figure 2-9 Socket communication network layer

整个网络服务必循运行在子线程中,否则会阻塞系统进程,设置如下:

myServer = new Thread(MySocket); //利用线程开启socket服务器
myServer.IsBackground = true; //设置这个线程是后台线程
myServer.Start();//启动线程

其中服务器主函数为:

void MySocket()
        {
            server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
            IPAddress iP = IPAddress.Parse(textBox1.Text);
            IPEndPoint endPoint = new IPEndPoint(iP, int.Parse(textBox2.Text));
            server.Bind(endPoint);
            server.Listen(20);
        }

当有socket客户端进入时,开辟一个新的线程不断接受此客户端发来的数据,实现如下:

Thread threadClient = new Thread(ReciveMsg);
threadClient.IsBackground = true;
threadClient.Start(connectClient);

接受数据函数ReciveMsg如下:

void ReciveMsg(object o)
        {
            Socket client = o as Socket;
            String clientname = client.RemoteEndPoint.ToString();
            while (true)
            {
                try
                {
                    byte[] arrMsg = new byte[1024 * 1024];
                    int length = client.Receive(arrMsg);
                    if (length > 0)
                    {                      
                        string recMsg = Encoding.Default.GetString(arrMsg, 0, length);
                        IPEndPoint endPoint = client.RemoteEndPoint as IPEndPoint;         
                    }
                }
                catch (Exception)
                {
                }
            }
        }

客户端连接直接使用Socket.connect(ip&port)函数实现,连接成功后即可开辟数据接受子线程,使用与客户端一致。数据的发送对于客户端和服务端来说并无差别,都是直接使用Socket.send(),实现,socket为发送对象的socket实例,其中send对象为Byte[]类型数组,如果需要发送字符串需要先转换为字节流。Socket可直接与ESP8266创建的tcp服务器连接,也可与Android端app直接连接,通用性良好,操作方便。

· 百度API通讯

系统设计中使用了基于数字图像处理的智能服务。服务实现需要使用百度AI开放平台提供的识别服务接口。服务端系统需要将采集到的图片发送至百度AI开放平台,调用其提供的云服务完成相应识别任务。

开发采用百度AI开放平台提供的SDK,SDK中封装好了通讯所需要的函数与协议,具体实现代码如下:

var API_KEY = API_KEY;
var SECRET_KEY = SECRET_KEY;
var client = new Baidu.Aip.BodyAnalysis.Body(API_KEY, SECRET_KEY);
client.Timeout = 60000;
var result = client.Gesture(image);

得到的result为一个字符串,字符串内容为Json格式的结果。通过对json格式进行解析即可获取云服务返回的数据。

· ONENET通讯

通过与中国移动ONENET进行连接,可以实时显示传感器数据。ONENET平台提供数据接收,展示与分析一体的服务,通过把数据上传到oennet既可以以直观简洁的界面在外网显示传感器接收的数据,还可以对一段时期内数据进行汇总显示分析,得到数据变化趋势。

与ONENET的连接采用MQTT协议,MQTT协议是当下最成熟的物联网协议之一。ONENET平台提供了一套完整的标准接入规范,服务端系统采用c#开发中常见的M2MQTT.net包进行MQTT通讯,在子线程中按照ONENET约定的报文格式传输数据。其中ONENET要求发送的数据Byte流格式为:

前两个字节固定0x30 0x00;

下一个字节为要发送数据byte流的长度;

后边为要发送的byte流数据;

其余位由ONENET平台自动识别;

整个线程设计为4秒一循环,第一秒分配为终端数据的读取,读取后按照Onenet通讯要求整理数据成对应JSON格式。后3秒为将json字符串转为byte数组,按照前面MQTT上传报文格式进行整理,并以“$dp”为topic上报到onenet平台,平台进行数据绑定并展示。

 具体实现如下:

Thread threadReceive = new Thread(new ThreadStart(onenet));
threadReceive.IsBackground = true;                           
threadReceive.Start();

其中线程内执行的主体为:

mqtt = new MqttClient("183.230.40.39", 6002, false, null, null, MqttSslProtocols.TLSv1_2);
mqtt.Connect("711603057","414848", API_KEY);
Thread.Sleep(1000);
byte[] sendmsg = Encoding.UTF8.GetBytes(msg);
byte[] SendBuf2 = { 0x03, 0x00, Convert.ToByte(sendmsg.Length) };
byte[] bb = new byte[SendBuf2.Length + sendmsg.Length + 1];
Array.Copy(SendBuf2, 0, bb, 0, SendBuf2.Length);
Array.Copy(sendmsg, 0, bb, SendBuf2.Length, sendmsg.Length);
mqtt.Publish("$dp", bb);
Thread.Sleep(3000);

Ⅲ. 服务端功能模块设计(function of system)

· 传感器数据处理

服务端系统基础功能为收集监测端(zigbee网络传感器感知的数据)温湿度,光照,烟雾信息,并将数据展示给客户端。其中客户端设计为两个方向,一个是中国移动ONENET平台,一个是客户端移动设备。ONENET可将数据自动部署在外网,突破局域网访问限制,而客户端移动设备需要服务器进行相应的内网穿透操作才能实现数据随时随地访问。故服务端设计只需要将数据进行格式化处理,方便两个数据展示平台进行获取解析。

服务端设计使用Socket通讯获取Zigbee网关传来的原始数据,按照通讯协议约定的方式反向解析出数据后保存至一个数据类中,类定义为:

class sensordata
    {
        private String location;//存储数据源位置
        private String temperature;//存储温度信息
        private String humidity;//存储湿度信息
        private String smoke;//存储烟雾信息
        private String light;//存储光照信息
        public sensordata(String s)//实例化时的初始化构造函数
        {
            location = s;
            temperature = humidity = smoke = light = "none";//初
        }
}

同时定义类成员的set和get操作以便赋值和读值操作。为了方便其他客户端获取格式化的信息,提高解析效率,在类成员函数中定义JSON格式数据输出功能,在后续舒服转出操作中,直接发送格式化的JSON数据,在此处使用JSON数据优势主要在于两点,一是对于数据展示平台来说,获取JSON数据便于直接解析展示,代码设计方便,数据美观。二是对于数据库的访问使用,JSON格式可以在VS SQL SERVER提供的接口下直接使用,方便数据库操作。其成员函数定义为:

public String data2json()
        {
            String result = "{\"" + location + "\":{"+ "\"tempuate\":\"" + temperature + "\","+                       "\"humidity\":\"" + humidity + "\","+ "\"smoke\":\"" + smoke + "\","+ "\"light\":\"" + light + "\"}}";
            return result;
        }
public String data2jsongroup()
        {
            String result = "\"" + location + "\":" +
                "" +
                "{"+ "\"temperature\":\"" + temperature + "\","+ "\"humidity\":\"" + humidity + "\","+ "\"smoke\":\"" + smoke + "\","+ "\"light\":\"" + light + "\"}";
            return result;
        }

· 云计算用户行为

本项目开发的终端控制系统,将原本人为思考过程转移到以计算机视觉处理为主的过程。原有家居控制系统要求人为思考当前预执行的操作,进而下达控制指令。本系统将思考过程放到云端计算,通过对图像信息的处理,判断出当前用户预执行的操作,并下达控制指令。比如图像亮度感知判断当前光照条件,控制关照明设备;图像手势识别下达控制指令;图像测距技术判断用户移动特征,下达控制指令等等。

与计算服务分存在3个概念:IaaS,PaaS,SaaS。

  1. IaaS

基础设施即服务 (IaaS : Infrastructure as a Service)

把计算基础(服务器、网络技术、存储和数据中心空间)作为一项服务提供给客户。它也包括提供操作系统和虚拟化技术、来管理资源。消费者通过Internet可以从完善的计算机基础设施获得服务。

在本项目系统中,用户可以将所有计算存储服务部署在云端执行。数字图像处理利用云服务提供的算力,摄像头将家庭视频信息通过网络传输至服务器,服务器将控制信息通过网络传回当前家居控制系统。同时用户操作以及系统运行的记录将同步保存在云端数据库中,用户可以访问记录数据。

  • PaaS

平台即服务(PaaS:Platform as a Service)

PaaS实际上是指将软件研发的平台作为一种服务,供应商提供超过基础设施的服务,一个作为软件开发和运行环境的整套解决方案,即以SaaS的模式提交给用户。因此,PaaS也是SaaS模式的一种应用。但是,PaaS的出现可以加快SaaS的发展,尤其是加快SaaS应用的开发速度。

用户可以选择将计算核心以及系统搬到云端执行,例如华为云,阿里云提供云服平台。利用这些平台可以实现后端的图像处理与指令下发等操作,以及前端搭建网页利用数据库供用户直观访问了解当前家居系统运行状况,以及检测对象等其他情况。利用云平台提供的便宜且方便的优势,减小家居系统的冗余程度,使得智能家居简便且更加智能。

  • SaaS

软件即服务 (SaaS:Software as a Service)

是一种交付模式,其中应用作为一项服务托管,通过Internet提供给用户;帮助客户更好地管理它们的IT项目和服务、确保它们IT应用的质量和性能,监控它们的在线业务。通过一些服务商提供的软件等实现数字图像处理,人脸识别等操作。

· 引入数字图像处理

系统设计采用当下热门的数字图像处理为基础,对收集到的视频帧处理,除了直接分析用户指令比如手势控制等能力,还具有自主分析能力,比如利用图像测距技术,自动捕捉用户距离行为信息,通过距离数据与行为特征,计算用户预执行的操作,这类操作需要用户给出明确的指令指示,然后交由系统处理用户行为信息判断出指令信息。因此可以实现意义上的智能。

传统物联网系统依赖于大量传感器,对用户特定行为的感知需要特定的对应传感器,传感器之间存在数据同步,数据组网等大量操作。而本项目采用基于数字图像处理的技术,大大简化家庭的部署复杂度,将大量的分散的冗余传感器替换成简单的家庭摄像头,集中处理数据,系统更高效,更稳定持久。

在人工智能发展火热的当下,华为,百度等公司纷纷成立自己的AI平台,本项目目前用到的人脸识别认证与手势识别均可使用api实现。Api功能速度快,操作简单。对于图像信息的处理服务,系统借助于百度AI开放平台实现。系统主要设计两个方面服务,分别是人脸识别认证与手势指令识别,均利用开放SDK实现。

  • 人脸识别登录

人脸识别登录主要是出于系统安全性考虑,其操作内容为获取登录用户的面部图像信息,按照百度AI开放平台要求进行base64编码,并发送至云服务应用,处理完成后会返回识别结果,结果由JSON数据展示。云服务处理中会对人脸库中的人脸进行对比,返回匹配度最高的人脸数据,其中SCORE为识别匹配分数,score大于80即可认为是同一个人,即认证成功,同时数据库记录当前认证用户登录操作信息。若不符合则判定为非法登录用户。系统将自动将当前信息以“年_月_日 时-分-秒”格式存储在loginhistory文件夹中。同时数据库后台记录当前合法登录与非法登录的信息,方便统一管理。

为了方便客户端设备进行人脸登录,系统抽象出人脸验证函数,只需要接收服务端或者客户端发来的base64编码即可进行人脸识别验证,函数为:

private void baiduapi(String img,Socket c)
    {
        var API_KEY = "GmrSCOB924h4H3pygw97tNEI";
        var SECRET_KEY = "PZ82XrOGGmI7IVwUd6XHZKR4SmsYXBG4";
        var imageType = "BASE64";
        var groupIdList = "1,1";
        Double score;
        var client = new Baidu.Aip.Face.Face(API_KEY, SECRET_KEY);
            client.Timeout = 60000;//百度api client
        var result = client.Search(img, imageType, groupIdList);
        user  = result.ToString().Substring(result.ToString().IndexOf("user_id\": \"") + 11, 3);//解析匹配用户
        score = Convert.ToDouble(result.ToString().Substring(result.ToString().IndexOf("score\":") + 7, 8));//解析匹配分数
        if (score >= 80)//匹配成功
        {
            listBox1.Items.Add("faceid pass");
            SendMsg("confirmed", c);
        }
        Else//匹配失败
        {
            listBox1.Items.Add("faceid error");
        }
    } 
图 3-10 系统人脸认证登录流程
Figure 3-10 System face authentication login process

服务端获取人脸数据时采用C++ + OpenCV实现。OpenCV是一个基于计算机视觉和机器学习的跨平台开源软件库。可以部署运行在Linux,windows,Mac OS和Android平台的操作系统上。其主要由C++语言编写,同时具有主流编程语言例如Python,Java和Matlab的接口,具备轻量级和高效的特点,在图像处理和计算机视觉等方面优势突出。

利用开源OpenCV库提供的人脸检测功能,通过开源的haar特征数据集,利用分类器进行特征对比,实现人脸检测,可以快速对图像中的人脸部分进行定位,利用像素大小可以判断出当前用户距离摄像头的距离,当达到一定距离时即可开始进行人脸信息截取,当人脸处于识别距离外时则忽略此帧图像,通过有选择的处理图像信息,来减轻服务器运行时的负载压力。识别到的人脸信息图像存储至loginhistory文件夹中,并以temp.jpg命名。其C++函数为:

int main(int argc, char** argv) {
	VideoCapture cap;
	if (!cap.open(0)) {	
		return -1;
	}//摄像头检测异常
	face.load("D:/vs2017projects/final/final/bin/Debug/haarcascade_frontalface_default.xml");//人脸检测支持文件XML
	Mat img;
		while (true)
		{
			cap >> img;//读入一帧图像
			face.detectMultiScale(img, faces, 1.3, 3, 0, Size(200, 200));//调用人脸检测,限定检测距离,图像大小
			if (faces.size() > 0)//当人脸检测到时
			{
				img = img(Range(faces[0].y, faces[0].y + faces[0].height+10), Range(faces[0].x, faces[0].x + faces[0].width+10));//裁剪提起人脸图像信息
				imwrite("./loginhistory/temp.jpg", img);//保存
			}
		}
	return 0;}
图 3-11 Haar特征的4种形式
Figure 4-11 4 forms of Haar feature
  • 手势指令识别

用户智能家居系统的控制功能其一就是用户使用手势实现对一些智能家电的控制。当接收到数字图像信息后,同样为了减小计算量,先进行人脸检测,当有人脸特征时捕捉用户手势图像信息,开始对当前用户的特征手势进行识别,利用识别返回的信息,系统下达相应的指令。当不存在人脸特征时判定当前捕捉为误判。其实现函数类似于上述人脸信息提取,不过取消掉距离检测,其余操作与人脸检测保持一致。获取手势图像后发送至百度AI开放平台,进行处理,处理成功后返回结果,结果保存为JSON数据格式。百度AI开放平台提供了24种手势识别,如下所示:

图 3-12 24种特征手势
Figure 3-12 24 kinds of characteristic gestures

其中服务端设计的开关等指令手势为ROCK与ILY,分别控制关灯与开灯。指令下达后,对于当前下达指令用户的操作记录保存至数据库中。当手势识别服务启动后,系统每两秒检测一次,当存在用户信息时上传识别图像,否则不进行操作。具体服务运行于服务端子线程下:

Thread handct = new Thread(handcontrol);
handct.IsBackground = true;
handct.Start();
具体程序如下所示:
public void handcontrol()
      {
          ResM r1 = new ResM();
          var API_KEY = "DlLona46z2Gq3Pmu0YsGgWzS";
          var SECRET_KEY = "KyzO6KYTcmtaMgHkVr17wbGjICssYvv9";
            var client = new Baidu.Aip.BodyAnalysis.Body(API_KEY, SECRET_KEY);//百度api client
          client.Timeout = 60000;//超时判定
          String action;
          p = Process.Start("hand.exe");//活体检测程序
          while (hand)
          {
              try
              {
                    var image = File.ReadAllBytes(filepath + @"loginhistory\temp.jpg");//待识别图像
                  var result = client.Gesture(image);
                  action= result.ToString().Substring(result.ToString().IndexOf("name\": \"") + 8, 3);//返回识别信息
                  if (action == "Fac") //识别成功
action = result.ToString().Substring(result.ToString().LastIndexOf("name\": \"") + 8, 3);//识别手势结果
                  File.Delete(filepath + @"loginhistory\temp.jpg");
                  textBox1.Text = "检测结束";
                if (action == "ILY")//开灯指令
                {
                      String add = "insert into [operate] (name,date,time,type) values('" + user + "','" + Date + "','" + Time + "','" + "Openlight" + "')";//更新数据库sql
                        int re = r1.ExecuteUpdate(add);//更新
                    }
                  else if (action == "Roc")//关灯指令
                    {
                        String add = "insert into [operate] (name,date,time,type) values('" + user + "','" + Date + "','" + Time + "','" + "Closelight" + "')";//更新数据库SQL
                      int re = r1.ExecuteUpdate(add);//更新数据库 
                    }
                    Else//检测失败
                    {
                    }
                }catch(Exception )
                {
                    textBox3.Text = "无数据";//没有检测数据
                }
                Thread.Sleep(2000);//休眠两秒
            }
        }
图 3-13 手势指令识别流程
Figure 3-13 Gesture instruction recognition process

4.3.4 引入安全性验证

作为一款家庭用智能家居系统,自然要承担起安全性的重任。除了通讯协议的安全性以外,系统应当具有一定的认证能力,与当下物联网家居不同,传统家居系统,对智能家电的控制依赖于终端,具有终端唯一性而用户任意性,只要拥有终端就可以操作家电设备。而本项目家居系统采用两种方案即人脸认证登录与账户密码认证登录。

利用图像处理技术引入人脸识别人脸认证,来确定操作用户的唯一。即只有通过系统认证的用户才能实现对家居系统的操作。用户可以自己上传认证用户人脸,只用在人脸库证认证的人才可以操作智能家居系统。对于强制解锁的人,系统可以保留其脸部特征。从而达到家居系统的安全性保障。当客户端应用欲访问家居系统服务时,需向服务端提供带有人面部信息的图像信息。信息以Base64编码的String字符串形式传至服务端。若允许访问则会返回通过信息,以便开启相关服务。

通过数据库里保存login表统计家居系统允许访问的用户账号密码信息。当客户端采用账号密码形式访问时,服务端即对比账户密码信息,若通过账号密码验证,则开启相关服务,在双重验证下即为客户端访问提供便利,又通过安全性验证保护用户家居系统的隐私。

图3 -14 安全性验证要求
Figure 3-14 Safety Verification Requirements

· 引入数据库支持

传统物联网技术支持的智能家居系统,整个控制过程从用户下达到家电指令接受执行便结束,没有连续性,数据不能对后续操作产生影响。加入数据库后,用户可以自主或者交由系统自主的对以往数据进行分析,以便后续执行更高级的更智能的操作,同时方便用户对整个系统的运行进行了解与管理。

在家居系统运行过程中要产生许多数据,安全性验证也需要存储许多数据。因此本系统在传统的用完即释放的操作模式下新增数据存储。为了让计算机更好的预测数据,以及用户直观的访问与了解系统运行的情况,系统对用户行为特征,收集数据,以及用户操作,系统下达的指令等都利用数据库记录。不仅可以使系统成为一个长期运行的整体,而且提供个人用户分析记录能力。

同时,数据库提供标准JSON格式数据输入输出,在整个系统数据流传输中均采用JSON格式,JSON格式的使用使得整个系统数据传输更加灵活。包括各大开放平台,例如使用的中国移动ONENET,百度AI开放平台,都以JSON格式传输数据。这样在开发中无需多余操作可直接实现数据库中数据与各大开放平台的流通。

系统开发使用的数据库为SQL Server 2017,SQL Server是由Microsoft开发和推广的关系数据库管理系统(DBMS),最初是由Microsoft、Sybase和Ashton-Tate三家公司共同开发。由于其丰富的编程接口工具,为用户进行程序设计提供了更大的选择余地,SQL Server已成为当下主流的数据库开发与管理软件。同为微软旗下产品SQL Server与Windows NT完全集成,利用了NT的许多功能,如发送和接受消息,管理登录安全性等。SQL Server也可以很好地与Microsoft BackOffice产品集成。通过DBMS为系统提前创建3个数据表分别为:

Dbo.login:存储授权用户信息,用于验证访问权限
Dbo.operate:存储用户服务器对指令的响应或状态信息
Dbo.data:存储各个传感器的感知数据

图 3-15 数据库列表
Figure 4-15 Database list

在使用Visual Studio 2017开发时,其可以方便的连接数据库,进行开发操作,在服务端这边,可以直接通过DataGridView窗体控件直接绑定数据表,进行窗体内数据库数据展示。对于外部客户端数据请求,仅需要建立一个访问类即可利用SQL语句实现增删查改。类定义如下:

class ResM      //数据库访问类命名为ResM;
  {
      private string MySqlCon = "Data Source=DESKTOP-JC51D9S\\SQLEXPRESS;Initial Catalog = bishe; Persist Security Info=True;User ID = bishe; Password=a123456";//数据库访问允许字符串
    public DataTable ExecuteQuery(string sqlStr)//sql用于查询
        {
            SqlConnection con = new SqlConnection(@MySqlCon);
            con.Open();
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sqlStr;
            DataTable dt = new DataTable();
            SqlDataAdapter msda;
            msda = new SqlDataAdapter(cmd);
            msda.Fill(dt);
            con.Close();
            return dt;
        }
        public int ExecuteUpdate(string sqlStr)//sql用于增删改;
        {
            SqlConnection con = new SqlConnection(@MySqlCon);
            con.Open();
            SqlCommand cmd = new SqlCommand();
            cmd.Connection = con;
            cmd.CommandType = CommandType.Text;
            cmd.CommandText = sqlStr;
            int iud = 0;
            iud = cmd.ExecuteNonQuery();
            con.Close();
            return iud;
        }
    }
}

当要实现数据库增删查改操作时只需要先对类实例化,输入对应正确的SQL语句即可,示例如下:

ResM r1 = new ResM();//实例化
DataTable d1 = new DataTable();//定义数据表访问
d1 = r1.ExecuteQuery(SQL);//输入SQL进行访问操作

4.3.6 内网穿透服务

当客户端设备并不处于局域网内部时,要实现对服务端访问需进行内网穿透,打通内网与外网的访问限制。此处实现内网穿透为广义内网穿透,主要目的为实现外网用户能访问局域网内服务端系统程序。

系统设计采用主动和被动的数据穿透服务。主动方式采用中国移动ONENET平台展示数据,数据4秒自动上传一次,用户可以随时利用浏览器访问数据页面,查看传感器上报数据,了解家里温湿度,光照与烟雾状况。但是不能实现用户数据接收,因此为主动式的数据穿透服务。被动式的服务即为在阿里云服务器搭建一个Socket转发程序,本地服务端连接至云服务器的转发程序并持续侦听云服务器转发程序转发过来的用户数据。

被动式数据穿透需要服务端长时间连接至云服务器转发程序,接收客户端下发的数据,,数据穿透为收一发一模式,主要用于响应客户端请求,故为被动式的数据穿透。此服务需要在阿里云服务器部署Socket转发程序,程序一次完整工作流程为:转发接收到用户端数据->转发给服务端系统程序->系统响应用户指令,将响应的数据回发给转发程序->转发程序将回应数据传给请求客户端。具体实现为搭建Socket服务端,监听客户端应用和服务端系统的访问请求并在子线程中转发数据。数据转发代码为:

static void pubReciveMsg(object o)//接收客户端请求,转发给服务端
        {
            Socket client ,sendto;
            client = o as Socket;//接收数据的Socket client
            sendto = prisocket;//要转发给的Socket client
            while (true)
            {
                try
                {
                    byte[] arrMsg = new byte[1024 * 1024];
                    int length = client.Receive(arrMsg);
                    if (length > 0)
                    {
                        latest = client;//存储请求客户端实例
                        string recMsg =Encoding.UTF8.GetString(arrMsg, 0, length);  //接收数据                   
               sendto.Send(Encoding.UTF8.GetBytes(recMsg));//转发数据
                        issend = true;
                    }
                    }
                catch (Exception)
                {
                }
            }
        }
static void priReciveMsg(object o)//接收服务端回应,转发给客户端
        {
            Socket client, sendto;
            client = prisocket;//接收数据的Socket client
            sendto = o as Socket;//要转发的Socket client
            while (true)
            {              
                try
                {
                    if (latest == sendto)//当找到请求的客户端时
                    {
                        byte[] arrMsg = new byte[1024 * 1024];
                        int length = client.Receive(arrMsg);
                        if (length > 0)
                        {
                            issend = false;
                            string recMsg = Encoding.UTF8.GetString(arrMsg, 0, length);//接收响应数据
           latest.Send(Encoding.UTF8.GetBytes(recMsg));//回传给客户端
                            issend = true;
                        }     
                }
                catch (Exception)
                {
                }
            }
        }
图 3-16 转发程序工作流程
Figure 3-16 forwarding program workflow

留言

您的邮箱地址不会被公开。 必填项已用 * 标注