热度 42
2020-4-11 09:27
4056 次阅读|
1 个评论
上一篇博文中,我介绍了我在实现NodeMcu向云开发数据库发送数据时的思路以及程序代码。 我们已经知道要想发送数据,首先我们要GET到access_token。 那么好,如今我们已经GET到access_token了,接下来如何实现发送数据呢? 我们还是先看一下 微信小程序的API文档 : https://developers.weixin.qq.com/miniprogram/dev/wxcloud/reference-http-api/database/databaseAdd.html 通过阅读文档,大家可能发现这篇文章实际上是介绍向数据库插入数据的,确实如此。 不过,原理上插入数据、修改数据以及删除数据等对数据库的操作方式区别在于POST的地址不同,以及POST的数据参数query有所差别,其他的实现步骤与我们本博文的介绍内容完全类似。 但事实上我并未全部实验过,所以若遇到问题还是根据errcode判断我们的问题所在并解决问题。 POST数据整体的流程实际上与GET到access_token完全类似。 首先,我们还是要获得POST请求地址: https://api.weixin.qq.com/tcb/databaseadd?access_token=ACCESS_TOKEN 我们注意到,每种对数据库的操作对应一个地址区别在于“?”前的操作方式不同,但无论何种操作方式,都需要我们的参数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 #include #include #include #include #include ESP8266WiFiMulti WiFiMulti; const char wifiSSID = "XXXXX"; const char httpsUrl 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: ," +"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(); 0; t--) { Serial.printf(" 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(" Connect wifi(%s)...\n", wifiSSID); if ((WiFiMulti.run() != WL_CONNECTED)) { Serial.println(" WiFi connect failed"); return false; } Serial.printf(" Set fingerprint(%s)...\n", httpsFingerprint); BearSSL::WiFiClientSecure client; bool ret = client.setFingerprint(httpsFingerprint); if (!ret) { Serial.println(" Set fingerprint failed"); return false; } Serial.printf(" Connect remote(%s)...\n", httpsUrl); HTTPClient https; ret = https.begin(client, httpsUrl); if (!ret) { Serial.println(" Begin connec failed"); return false; } Serial.println(" post data..."); https.addHeader("Content-Type","application/json"); int httpCode = https.POST(PostData); Serial.printf(" Rsp code: %d %s\n", httpCode, https.errorToString(httpCode).c_str()); 0) { if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) { String payload = https.getString(); Serial.printf(" 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 ]; Serial.printf(" Rsp data: %s %s\n", (const char*)keys , JSONVar::stringify(value).c_str()); } if (jsonObject.hasOwnProperty("errcode")) { errCode = jsonObject ; } if (jsonObject.hasOwnProperty("errmsg")) { errMsg = jsonObject ; } if (jsonObject.hasOwnProperty("id_list")) { idList = jsonObject ; } Serial.printf(" 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就可以这么做!