原创 POST数据到微信小程序云开发数据库

2020-4-11 09:27 4090 56 42 分类: 物联网 文集: NodeMcu
上一篇博文中,我介绍了我在实现NodeMcu向云开发数据库发送数据时的思路以及程序代码。
我们已经知道要想发送数据,首先我们要GET到access_token。
那么好,如今我们已经GET到access_token了,接下来如何实现发送数据呢?
我们还是先看一下微信小程序的API文档
通过阅读文档,大家可能发现这篇文章实际上是介绍向数据库插入数据的,确实如此。
不过,原理上插入数据、修改数据以及删除数据等对数据库的操作方式区别在于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就可以这么做! 


    作者: 王土豆, 来源:面包板社区

    链接: https://mbb.eet-china.com/blog/uid-me-3897735.html

    版权声明:本文为博主原创,未经本人允许,禁止转载!

    PARTNER CONTENT

    文章评论1条评论)

    登录后参与讨论

    用户3924592 2020-7-24 08:54

    真的厉害!我的哥哥
    相关推荐阅读
    王土豆 2020-04-09 09:38
    NodeMcu接入微信小程序云开发数据库的实现方法
    首先,我们先来看一下微信小程序的API调用文档:https://developers.weixin.qq.com/miniprogram/dev/api-backend/open-api/access...
    王土豆 2020-03-28 21:43
    1602LCD简介与基于Arduino的使用
    一、1602LCD简介液晶显示器简称LCD。1602液晶也叫1602字符型液晶,是指显示的内容为16X2(即可显示两行,每行16个字符)的液晶模块。使用1602液晶制作的显示器也就叫做1602LCD。...
    我要评论
    1
    56
    关闭 站长推荐上一条 /3 下一条