上一篇博文中,我介绍了我在实现NodeMcu向云开发数据库发送数据时的思路以及程序代码。
我们已经知道要想发送数据,首先我们要GET到access_token。
那么好,如今我们已经GET到access_token了,接下来如何实现发送数据呢?
通过阅读文档,大家可能发现这篇文章实际上是介绍向数据库插入数据的,确实如此。
不过,原理上插入数据、修改数据以及删除数据等对数据库的操作方式区别在于POST的地址不同,以及POST的数据参数query有所差别,其他的实现步骤与我们本博文的介绍内容完全类似。
但事实上我并未全部实验过,所以若遇到问题还是根据errcode判断我们的问题所在并解决问题。
POST数据整体的流程实际上与GET到access_token完全类似。
首先,我们还是要获得POST请求地址:
我们注意到,每种对数据库的操作对应一个地址区别在于“?”前的操作方式不同,但无论何种操作方式,都需要我们的参数access_token。我们前一阶段的工作终于起作用了。
除此之外,我们还要POST数据,数据包括:env、query。在这里,我要介绍一下:
由于我此次使用的方法是NodeMcu在ArduinoIDE编程环境下实现。原理上我调用了一个库,使用其中的POST方法实现就好了。但事实上,这个方法中POST的数据格式只能是字符串,而我却把它当作使用高级语言编程时POST数据应处理的json格式,所以一直返回:47001,这就是数据格式错误时返回的错误码。
然后我就去阅读ESP8266HTTPClient.h和ESP8266HTTPClient.cpp的底层代码,才发现这一漏洞。在这一点上浪费了我许多时间,一方面是经验不足,另一方面没有根据返回的errcode进行Debug,盲目的修改程序,甚至我一度以为是开发板坏掉了。在此记录,为自己提个醒,也为以后阅读本博文的读者们在遇到问题时提醒一下:Debug应该做到有理有据,不能盲目,否则只会白白浪费时间,事倍功半。
好,我们根据文档中提供的query语句,将其字符串化。(当初学习C语言以及其他语言时,对字符串的操作认识并不深入,当我真正用到时只能回去翻书,采取了一种最低效但却是最有效的方法)
阅读文档我们还发现,POST请求返回的数据还是json数据,那么好,之前的操作拿来继续用就好了。
有了以上的工作,我们的程序实现思路就很清晰了:根据access_token,得到POST请求地址,然后调用POST方法POST文档中要求的字符串化后的参数,获取返回的json数据并解析,看看到底POST成功没有。
当返回码是0,出现了ok时,就证明POST成功了!!!
不再说废话,直接上代码:
- #include <Arduino.h>
- #include <Arduino_JSON.h>
- #include <ESP8266WiFi.h>
- #include <ESP8266WiFiMulti.h>
- #include <ESP8266HTTPClient.h>
- #include <WiFiClientSecureBearSSL.h>
- ESP8266WiFiMulti WiFiMulti;
- const char wifiSSID[] = "XXXXXX";
- const char wifiPassword[] = "XXXXX";
- const char httpsUrl[] PROGMEM = "https://api.weixin.qq.com/tcb/databaseadd?access_token=XXXXXX";
- const char httpsFingerprint[] PROGMEM = "f9 aa 18 e0 bf 74 7d 52 f4 f6 a5 f4 9d 66 be af 72 54 13 8f";
- String PostData =String("{")
- +String(""env"") +String(":") + String(""sdu-jnjp-uomj9",")
- +String(""query"") + String(": ") + ""db.collection(\\"data\\")" + ".add({"
- +"data: [{"
- +"description:\\"item1\\","
- +"due: new Date(\\"2020-04-07\\"),"
- +"tags: ["
- +"\\"cloud\\","
- +"\\"database\\""
- +"],"
- +"location: new db.Geo.Point(33,23),"
- +"done: false"
- +"}"
- +"]"
- +"})""
- +String("}")
- ;//这就是我最低效的方法,但不可否认,它的确很有效,只要仔细一下绝对不出差错
- String errMsg;
- String idList;
- int errCode;
- void setup() {
- Serial.begin(115200);
- //Serial.setDebugOutput(true);
- Serial.println();
- Serial.println();
- Serial.println();
- for (uint8_t t = 4; t > 0; t--) {
- Serial.printf("[SETUP] WAIT %d...\n", t);
- Serial.flush();
- delay(1000);
- }
- wifiSetup();
-
- }
- void loop() {
-
- PostDataLoop();
- Serial.println("Wait 10s before next round...");
- delay(10000);
- }
- void wifiSetup() {
- WiFi.mode(WIFI_STA);
- WiFiMulti.addAP(wifiSSID, wifiPassword);
- }
- bool PostDataLoop() {
- Serial.printf("[HTTPS] Connect wifi(%s)...\n", wifiSSID);
-
- if ((WiFiMulti.run() != WL_CONNECTED)) {
- Serial.println("[HTTPS] WiFi connect failed");
- return false;
- }
- Serial.printf("[HTTPS] Set fingerprint(%s)...\n", httpsFingerprint);
-
- BearSSL::WiFiClientSecure client;
- bool ret = client.setFingerprint(httpsFingerprint);
- if (!ret) {
- Serial.println("[HTTPS] Set fingerprint failed");
- return false;
- }
- Serial.printf("[HTTPS] Connect remote(%s)...\n", httpsUrl);
-
- HTTPClient https;
- ret = https.begin(client, httpsUrl);
- if (!ret) {
- Serial.println("[HTTPS] Begin connec failed");
- return false;
- }
-
- Serial.println("[HTTPS] post data...");
- https.addHeader("Content-Type","application/json");
- int httpCode = https.POST(PostData);
- Serial.printf("[HTTPS] Rsp code: %d %s\n", httpCode, https.errorToString(httpCode).c_str());
-
- if (httpCode > 0) {
- if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
- String payload = https.getString();
- Serial.printf("[HTTPS] Rsp payload: %s\n", payload.c_str());
- JSONVar jsonObject = JSON.parse(payload.c_str());
- JSONVar keys = jsonObject.keys();
- for (int i = 0; i < keys.length(); i++) {
- JSONVar value = jsonObject[keys[i]];
- Serial.printf("[HTTPS] Rsp data: %s %s\n", (const char*)keys[i], JSONVar::stringify(value).c_str());
- }
- if (jsonObject.hasOwnProperty("errcode")) {
- errCode = jsonObject["errcode"];
- }
- if (jsonObject.hasOwnProperty("errmsg")) {
- errMsg = jsonObject["errmsg"];
- }
-
- if (jsonObject.hasOwnProperty("id_list")) {
- idList = jsonObject["id_list"];
- }
- Serial.printf("[HTTPS] Got data: errCode(%d) errMsg(%s) idList(%s)\n",errCode, errMsg.c_str(), idList.c_str());
- }
- }
- https.end();
- return true;
- }
不可否认,我写的代码实在是垃圾代码。并且此次代码,我也没注释。因为我觉得大部分内容与上次的代码一样(当然上次的代码也并未完整注释)。
我真是一个Green Hand!
但我还要总结一下下:就是实现POST请求POST数据,原理上只要是POST就可以这么做!
用户3924592 2020-7-24 08:54