本节书摘来自华章出版社《用于物联网的Arduino项目开发:实用案例解析》一 书中的第3章,第3.2节,作者[美]安德尔·杰韦德(Adeel Javed),更多章节内容可以访问云栖社区“华章计算机”公众号查看。
3.2 HTTP
网站使用超文本传输协议(Hyper Text Transfer Protocol,HTTP)。HTTP支持多种数据传输的方法,在这个作品中,我们会用其中两种较常用的方法:GET和POST。GET和POST方法要做的事情是一样的,所以代码也很相似,它们的不同在于请求的格式略有变化。与POST相比,GET所能发送的数据量是有限制的。POST还被认为比GET要略为安全一些。根据你的需要,你可以决定哪个方法更适用。图3-1给出了设备和HTTP服务器之间的高层交互。
![e496386b9a7390cc566fbe14d86876aeda8da6f0](https://yqfile.alicdn.com/e496386b9a7390cc566fbe14d86876aeda8da6f0.png?x-oss-process=image/resize,w_1400/format,webp)
所需的硬件、软件和电路,请阅读2.3节。
3.2.1 代码(Arduino)
接下来,我们来写用WiFi连接Arduino和互联网,并通过HTTP协议发送测试数据给服务器的代码。
启动Arduino IDE,输入下面的代码,或者从本书的网站下载代码文件然后打开。所有的文件都在单个源文件(*.ino)中,不过为了便于理解和重用,这个代码被分成四个部分:
- 外部库
- 互联网连接(无线)
- 数据发布(HTTP)
- 标准函数
外部库
代码的第一部分引入了运行代码所需的全部外部库。这一部分的代码和程序2-6是完全一样的。
互联网连接(无线)
代码的第二部分定义了连接互联网要用的变量、常量和函数。在这里使用了程序2-7、程序2-8和程序2-9中的代码。
数据发布
代码的第三部分定义了将来发送给使用HTTP的服务器要用到的变量、常量和函数。
程序3-1首先定义了Arduino要连接和发送数据的服务器的地址和端口。对于这个作品来说,可以把数据发布到www.httpbin.org,这是一个开放可用的测试服务器,只是会把收到的请求数据和一些额外的数据一起回送。在后面的作品中会使用能处理请求的数据的服务器。
![1c27abf04ae50a8a7c2e86791a0a002477f154be](https://yqfile.alicdn.com/1c27abf04ae50a8a7c2e86791a0a002477f154be.png?x-oss-process=image/resize,w_1400/format,webp)
程序3-2里的doHttpGet()函数封装了为GET方法准备请求数据的所有细节,它会连接到服务器然后发送请求。
接下来,在一个if语句中,用client.connect(server, port)来尝试连接服务器。如果连接成功,就准备请求数据。
在使用GET方法的请求中,数据是以名值对格式作为URL的一部分被发送的。
最后,用client.println()方法把HTTP请求发送给服务器。这个方法会通过网络把命令发送给服务器,然后接收服务器的响应。
![ee40c9fb974c701e7c11a201459696e92734b0c3](https://yqfile.alicdn.com/ee40c9fb974c701e7c11a201459696e92734b0c3.png?x-oss-process=image/resize,w_1400/format,webp)
![3e4908b7d0aa58b551937deb018fab9d0d7d4998](https://yqfile.alicdn.com/3e4908b7d0aa58b551937deb018fab9d0d7d4998.png?x-oss-process=image/resize,w_1400/format,webp)
这个代码是用来发送HTTP GET请求的,不过,前面提到过,这种方法有数据长度的限制,如果要突破这个限制,就要使用HTTP POST方法。
程序3-3的doHttpPost()函数把POST方法的所有准备工作封装了起来,它会连接到服务器,然后发送请求。
在一个if语句中,用client.connect(server, port)来尝试连接服务器。到这里,代码和用HTTP GET做请求是相似的。如果连接成功,就准备请求的数据。
用POST方法做请求的时候,数据也是以名值对的格式成对出现的,但是这些数据是请求的一部分(而不是网址的一部分)。从程序3-3可以看出,发送一个HTTP POST请求需要额外的头部数据。
最后,用client.println()方法把HTTP请求发送给服务器。这个方法会通过网络把命令发送给服务器,然后接收服务器响应。
![725acab5c2b52f5b2a52225099633a3df069594b](https://yqfile.alicdn.com/725acab5c2b52f5b2a52225099633a3df069594b.png?x-oss-process=image/resize,w_1400/format,webp)
![d2ade9631c2526095acb6cbea7851b005a094f84](https://yqfile.alicdn.com/d2ade9631c2526095acb6cbea7851b005a094f84.png?x-oss-process=image/resize,w_1400/format,webp)
从Arduino向服务器发布数据的大致过程基本如此。
标准函数
代码的第四部分和第五部分实现了Arduino标准的setup()和loop()函数。
如程序3-4所示,setup()函数初始化串口,然后通过调用doHttpGet()函数来做HTTP GET请求,或是通过调用doHttpPost()函数来做HTTP POST请求。
![bb19b86d5a68a42b6c53d7ed4150e4209a074877](https://yqfile.alicdn.com/bb19b86d5a68a42b6c53d7ed4150e4209a074877.png?x-oss-process=image/resize,w_1400/format,webp)
要在loop()函数里加上代码来读取服务器的响应。这个作品不会对从传感器发送过去的数据做任何服务器端的处理,我们所用的测试服务器只会在响应中把全部的请求数据重复发回来,所以只要读取响应,然后在串口监视器输出即可。
根据程序3-5,首先检查WiFiClient里是否有字节可以读,读取所有的字节,然后在串口监视器打印出来。一旦读取了全部字节并打印出来,就停止这个客户端对象。
![edb3b269e5af4f99870b614a1ba2950b57d1fcd1](https://yqfile.alicdn.com/edb3b269e5af4f99870b614a1ba2950b57d1fcd1.png?x-oss-process=image/resize,w_1400/format,webp)
![f01f6f8f2b669b89cb37b58f458616d5e6f009c9](https://yqfile.alicdn.com/f01f6f8f2b669b89cb37b58f458616d5e6f009c9.png?x-oss-process=image/resize,w_1400/format,webp)
至此,完成了编写Arduino代码。
3.2.2 最终的作品
要测试这个应用,按照第1章所介绍的,校验然后上传代码到Arduino。代码上传后,打开串口监视器会看到如图3-2所示的HTTP GET日志消息,或是图3-3所示的HTTP POST日志消息。
![4babb48655194057ae6dd1e19271ea866cd61433](https://yqfile.alicdn.com/4babb48655194057ae6dd1e19271ea866cd61433.png?x-oss-process=image/resize,w_1400/format,webp)
![285a95633e107bee8f948eeadd4d55c3ca801cfa](https://yqfile.alicdn.com/285a95633e107bee8f948eeadd4d55c3ca801cfa.png?x-oss-process=image/resize,w_1400/format,webp)