数码之家

 找回密码
 立即注册
搜索
查看: 1348|回复: 7

[Arduino] esp8266_arduino直连postgresql

[复制链接]
发表于 2020-3-30 14:43:45 | 显示全部楼层 |阅读模式

爱科技、爱创意、爱折腾、爱极致,我们都是技术控

您需要 登录 才可以下载或查看,没有账号?立即注册

x
传感器直接连接数据库,不是物联网的正确打开方式。物联网还是mqtt之类的比较正常。
但是,很多时候都想简单了再简单,于是直连数据库就成了必须的功能。。。。 :lol:

postgresql这个arduino默认库里没有,去这里 下来之后放到 libraries 里

  1. https://github.com/ethanak/SimplePgSQL
复制代码

以下是代码,只保证可用
  1. /*
  2. * SimplePgSQL.c - Lightweight PostgreSQL connector for Arduino
  3. * Copyright (C) Bohdan R. Rau 2016 <ethanak@polip.com>
  4. *
  5. * SimplePgSQL is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU Lesser General Public
  7. * License as published by the Free Software Foundation; either
  8. * version 2.1 of the License, or (at your option) any later version.
  9. *
  10. * SimplePgSQL is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13. * Lesser General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Lesser General Public
  16. * License along with SimplePgSQL.  If not, write to:
  17. *         The Free Software Foundation, Inc.,
  18. *         51 Franklin Street, Fifth Floor
  19. *         Boston, MA  02110-1301, USA.
  20. */

  21. /*
  22. * Demo program for SimplePgSQL library
  23. * Simple PostgreSQL console
  24. * Accepts:
  25. * - PostgreSQL simple queries
  26. * - \d - displays table list
  27. * - \d tablename - list table columns
  28. * - exit - closes connection
  29. */

  30. #include <stdlib.h>
  31. #ifdef ESP8266
  32. #include <ESP8266WiFi.h>
  33. #include <DNSServer.h>
  34. #include <ESP8266WebServer.h>
  35. #include <WiFiManager.h>
  36. #else

  37. // Uncomment line below if you use WiFi shield instead of Ethernet
  38. // #define USE_ARDUINO WIFI 1

  39. #ifdef USE_ARDUINO_WIFI
  40. #include <WIFI.h>
  41. #else
  42. #include <Ethernet.h>
  43. #endif

  44. #endif
  45. #include <SimplePgSQL.h>

  46. IPAddress PGIP(192, 168, 1, 5);        // your PostgreSQL server IP

  47. //const char ssid[] = "network_ssid";      //  your network SSID (name)
  48. //const char pass[] = "network_pass";      // your network password

  49. const char user[] = "esp";       // your database user
  50. const char password[] = "Espsdsdsdsd";   // your database password
  51. const char dbname[] = "esp";         // your database name

  52. #if defined(ESP8266) || defined(USE_ARDUINO_WIFI)
  53. int WiFiStatus;
  54. WiFiClient client;
  55. #else
  56. #define USE_ARDUINO_ETHERNET 1
  57. EthernetClient client;
  58. byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // your mac address
  59. byte ip[] = {192, 168, 1, 177};                    // your IP address
  60. #endif

  61. char buffer[1024];
  62. PGconnection conn(&client, 0, 1024, buffer);

  63. void setup(void) {
  64.         Serial.begin(
  65. #ifdef ESP8266
  66.                         115200
  67. #else
  68.     9600
  69. #endif
  70.                         );
  71. #ifdef USE_ARDUINO_ETHERNET
  72.     Ethernet.begin(mac, ip);
  73. #else
  74.         //WiFi.begin((char*) ssid, pass);
  75.         WiFiManager wifiManager;
  76. #endif

  77. //        WiFiManager wifiManager;
  78.         //reset saved settings
  79.         //wifiManager.resetSettings();

  80.         //set custom ip for portal
  81.         //wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));

  82.         //fetches ssid and pass from eeprom and tries to connect
  83.         //if it does not connect it starts an access point with the specified name
  84.         //here  "AutoConnectAP"
  85.         //and goes into a blocking loop awaiting configuration
  86.         //  wifiManager.autoConnect("AutoConnectAP");
  87.         //or use this for auto generated name ESP + ChipID
  88.         //wifiManager.autoConnect();

  89.         //将到期超时设置为240秒:

  90.         wifiManager.setConfigPortalTimeout(240);
  91.         if (!wifiManager.autoConnect("ESP_AP", "changeit")) {
  92.                 Serial.println(F("Failed to connect. Reset and try again. . ."));
  93.                 delay(3000);
  94.                 //重置并重试
  95.                 ESP.reset();
  96.                 delay(5000);
  97.         }

  98.         //在我们从网络浏览器中选择Wi-Fi网络和密码后,我们现在连接到Wi-Fi网络:

  99.         //如果你到这里,你已经连接到WiFi
  100.         Serial.println(F("Connected to Wifi."));
  101.         Serial.print(F("My IP:"));
  102.         Serial.println(WiFi.localIP());
  103.         String hostname = "esp8266_";
  104.         hostname += ESP.getChipId();
  105.         WiFi.hostname(hostname);

  106.         //  ADD_STARTUP_OPTION_P(PSTR("application_name"), PSTR("arduino"));

  107. }

  108. #ifndef USE_ARDUINO_ETHERNET
  109. void checkConnection() {
  110.         int status = WiFi.status();
  111.         if (status != WL_CONNECTED) {
  112.                 if (WiFiStatus == WL_CONNECTED) {
  113.                         Serial.println("Connection lost");
  114.                         WiFiStatus = status;
  115.                 }
  116.         } else {
  117.                 if (WiFiStatus != WL_CONNECTED) {
  118.                         Serial.println("Connected");
  119.                         WiFiStatus = status;
  120.                 }
  121.         }
  122. }

  123. #endif

  124. /*
  125. static PROGMEM const char query_rel[] = "\
  126. SELECT a.attname "Column",\
  127.   pg_catalog.format_type(a.atttypid, a.atttypmod) "Type",\
  128.   case when a.attnotnull then 'not null ' else 'null' end as "null",\
  129.   (SELECT substring(pg_catalog.pg_get_expr(d.adbin, d.adrelid) for 128)\
  130.    FROM pg_catalog.pg_attrdef d\
  131.    WHERE d.adrelid = a.attrelid AND d.adnum = a.attnum AND a.atthasdef) "Extras"\
  132. FROM pg_catalog.pg_attribute a, pg_catalog.pg_class c\
  133. WHERE a.attrelid = c.oid AND c.relkind = 'r' AND\
  134. c.relname = %s AND\
  135. pg_catalog.pg_table_is_visible(c.oid)\
  136. AND a.attnum > 0 AND NOT a.attisdropped\
  137.     ORDER BY a.attnum";


  138. static PROGMEM const char query_tables[] = "\
  139. select * from esp_insert limit 10;";
  140. */

  141. int pg_status = 0;

  142. void doPg(void) {

  143.         /*
  144.          *
  145.          setDbLogin

  146.          int setDbLogin(IPAddress server,
  147.          const char *user,
  148.          const char *passwd = NULL,
  149.          const char *db = NULL,
  150.          const char *charset = NULL,
  151.          int port = 5432);

  152.          Initialize connection.
  153.          */
  154.         char *msg;
  155.         int rc;
  156.         if (!pg_status) {
  157.                 conn.setDbLogin(PGIP, user, password, dbname, "utf8", 9988);
  158.                 pg_status = 1;
  159.                 Serial.println("conn.setDbLogin");
  160.                 return;
  161.         }

  162.         if (pg_status == 1) {
  163.                 rc = conn.status();
  164.                 if (rc == CONNECTION_BAD || rc == CONNECTION_NEEDED) {
  165.                         char *c = conn.getMessage();
  166.                         if (c)
  167.                                 Serial.println(c);

  168.                         pg_status = -1;
  169.                 } else if (rc == CONNECTION_OK) {
  170.                         pg_status = 2;
  171.                         Serial.println("Enter query");
  172.                 }
  173.                 return;
  174.         }

  175.         /*
  176.          if (pg_status == 2) {
  177.          if (!Serial.available())
  178.          return;
  179.          char inbuf[64];
  180.          int n = Serial.readBytesUntil('\n', inbuf, 63);
  181.          while (n > 0) {
  182.          if (isspace(inbuf[n - 1]))
  183.          n--;
  184.          else
  185.          break;
  186.          }
  187.          inbuf[n] = 0;

  188.          if (!strcmp(inbuf, "\\d")) {
  189.          if (conn.execute(query_tables, true))
  190.          goto error;
  191.          Serial.println("Working...");
  192.          pg_status = 3;
  193.          return;
  194.          }
  195.          if (!strncmp(inbuf, "\\d", 2) && isspace(inbuf[2])) {
  196.          char *c = inbuf + 3;
  197.          while (*c && isspace(*c))
  198.          c++;
  199.          if (!*c) {
  200.          if (conn.execute(query_tables, true))
  201.          goto error;
  202.          Serial.println("Working...");
  203.          pg_status = 3;
  204.          return;
  205.          }
  206.          if (conn.executeFormat(true, query_rel, c))
  207.          goto error;
  208.          Serial.println("Working...");
  209.          pg_status = 3;
  210.          return;
  211.          }
  212.          */if (pg_status == 2) {

  213.                 // int random(int num);
  214.                 //         random函数返回一个0~num-1之间的随机数. random(num)是在stdlib.h中的一个宏定义. num和函数返回值都是整型数.

  215.                 String sql_query =
  216.                                 " insert  \
  217.                    into esp_insert ( datenow, vaules, s_id, k_id ,up_addr,client_addr )\
  218.                    select \
  219.                    now() dateNow,  ";
  220.                 sql_query += random(1000);
  221.                 sql_query += " vaules, '001' s_iD, '";
  222.                 sql_query += ESP.getChipId();
  223.                 sql_query += "',inet_client_addr(),'";
  224.                 sql_query += WiFi.localIP().toString();
  225.                 sql_query += "';";

  226.                 /*
  227.                  String str1 = String(along);
  228.                  str1 += "mimi";
  229.                  char cArr[str1.length() + 1];
  230.                  char cArr2[str1.length() + 3];
  231.                  str1.toCharArray(cArr,str1.length() + 1);
  232.                  str1.toCharArray(cArr2,str1.length() + 3);
  233.                  */

  234.                 char query_rel[sql_query.length() + 1];
  235.                 sql_query.toCharArray(query_rel, sql_query.length() + 1);
  236.                 /*
  237.                  static PROGMEM const char query_rel[] =
  238.                  " insert  \
  239.                                                                      into esp_insert ( datenow, vaules, s_id, k_id )\
  240.                                                                      select \
  241.                                                                      now() dateNow, 12 vaules, '001' s_iD, '\ ESP.getChipId();";
  242.                  */

  243.                 //if (conn.execute(query_tables, true))
  244.                 if (conn.execute(query_rel, true))
  245.                         goto error;
  246.                 Serial.println("Working...");
  247.                 pg_status = 3;
  248.                 /*
  249.                  if (!strncmp(inbuf, "exit", 4)) {
  250.                  conn.close();
  251.                  Serial.println("Thank you");
  252.                  pg_status = -1;
  253.                  return;
  254.                  }
  255.                  if (conn.execute(inbuf))
  256.                  goto error;
  257.                  Serial.println("Working...");
  258.                  pg_status = 3;
  259.                  */
  260.         }
  261.         if (pg_status == 3) {
  262.                 rc = conn.getData();
  263.                 int i;
  264.                 if (rc < 0)
  265.                         goto error;
  266.                 if (!rc)
  267.                         return;
  268.                 if (rc & PG_RSTAT_HAVE_COLUMNS) {
  269.                         for (i = 0; i < conn.nfields(); i++) {
  270.                                 if (i)
  271.                                         Serial.print(" | ");
  272.                                 Serial.print(conn.getColumn(i));
  273.                         }
  274.                         Serial.println("\n==========");
  275.                 } else if (rc & PG_RSTAT_HAVE_ROW) {
  276.                         for (i = 0; i < conn.nfields(); i++) {
  277.                                 if (i)
  278.                                         Serial.print(" | ");
  279.                                 msg = conn.getValue(i);
  280.                                 if (!msg)
  281.                                         msg = (char*) "NULL";
  282.                                 Serial.print(msg);
  283.                         }
  284.                         Serial.println();
  285.                 } else if (rc & PG_RSTAT_HAVE_SUMMARY) {
  286.                         Serial.print("Rows affected: ");
  287.                         Serial.println(conn.ntuples());
  288.                 } else if (rc & PG_RSTAT_HAVE_MESSAGE) {
  289.                         msg = conn.getMessage();
  290.                         if (msg)
  291.                                 Serial.println(msg);
  292.                 }
  293.                 if (rc & PG_RSTAT_READY) {
  294.                         pg_status = 2;
  295.                         Serial.println("Enter query");
  296.                 }
  297.         }
  298.         return;
  299.         error: msg = conn.getMessage();
  300.         if (msg)
  301.                 Serial.println(msg);
  302.         else
  303.                 Serial.println("UNKNOWN ERROR");
  304.         if (conn.status() == CONNECTION_BAD) {
  305.                 Serial.println("Connection is bad");
  306.                 pg_status = -1;
  307.         }
  308.         conn.close();
  309. }

  310. void loop() {
  311. #ifndef USE_ARDUINO_ETHERNET
  312.         checkConnection();
  313.         if (WiFiStatus == WL_CONNECTED) {
  314. #endif
  315.                 doPg();
  316. #ifndef USE_ARDUINO_ETHERNET
  317.         }
  318. #endif
  319.         delay(1000);
  320. }

复制代码



打赏

参与人数 1家元 +10 收起 理由
人艰不拆了 + 10

查看全部打赏

发表于 2020-3-30 17:07:50 | 显示全部楼层
哈哈,好长的代码,看了二行,看不懂了:titter:
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-3-30 17:15:50 | 显示全部楼层
人艰不拆了 发表于 2020-3-30 17:07
哈哈,好长的代码,看了二行,看不懂了

代码挺简单了。。。毕竟资源有限,实现不了太复杂的操作。

ESP8266还是要上网啊,上网就要存数据啊
物联网么,就是在网上 存数 取数 存数 取数 :biggrin:

这东西已经和传统的控制用单片机的应用不太一样了。多数应用追求啥功耗,效率都不是第一位的了。毕竟网络的速度就够慢的,而发射功率都不小
回复 支持 反对

使用道具 举报

发表于 2020-3-31 22:19:41 | 显示全部楼层
本帖最后由 fryefryefrye 于 2020-3-31 22:22 编辑

我都懒得用MQTT,我家里几十个ESP8266和我的树莓派主机,直接互发UDP包。

定义一个数据结构,用一个UDP包整体发送。接收方用同一个数据结构,指针指以下,所有的变量就解析好了。

服务端也懒得搞数据库,所有的日志文件直接存文本文件,每天新建一个文件。平时也不会查看这些文件的,主要是在网页端画曲线图,我所记录的文本文件的格式可以直接喂给网页端把曲线图显示出来。

坏处就是每页最多显示一天的数据。


打赏

参与人数 1家元 +20 收起 理由
qingkong + 20 厉害了

查看全部打赏

回复 支持 1 反对 0

使用道具 举报

 楼主| 发表于 2020-3-31 23:46:13 来自手机浏览器 | 显示全部楼层
fryefryefrye 发表于 2020-3-31 22:19
我都懒得用MQTT,我家里几十个ESP8266和我的树莓派主机,直接互发UDP包。

定义一个数据结构,用一个UDP包 ...

你家里那么多esp8266 都干啥用啊……

数据还是入库各种都方便  ,如果有数据生成第一考虑还是入库

而postgresql 一样有arm版本
我是跑香橙派的……树莓派太贵 买不起………

mqtt不仅仅是上传下达 第三方接收也能干点别的
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-1 00:00:02 来自手机浏览器 | 显示全部楼层
postgresql 可以直接接收或者返回json
对于表 还可以连http也不写 直接上 PostgREST 直接提供http的json结果

要偷懒 这玩意是个好选择:lol:
回复 支持 反对

使用道具 举报

发表于 2020-4-1 22:04:07 | 显示全部楼层
qingkong 发表于 2020-3-31 23:46
你家里那么多esp8266 都干啥用啊……

数据还是入库各种都方便  ,如果有数据生成第一考虑还是入库

比如4台空调,每台一个。每个房间的灯光控制。家里各个自动门的控制。315mhz设备的控制。门禁系统等等,都是8266.

数据库当年学的很熟的,最近工作也偶尔用Access数据库,但是自己DIY,我是用树莓派直接把Log文件写到了NAS服务器上了,直接代码printf就行。清理老数据,删删旧文件就行了。

Linux这种安装上的轻型数据库,存储出来是一个文件吗?文件放哪儿?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2020-4-2 08:19:14 | 显示全部楼层
fryefryefrye 发表于 2020-4-1 22:04
比如4台空调,每台一个。每个房间的灯光控制。家里各个自动门的控制。315mhz设备的控制。门禁系统等等, ...

postgresql可不是access那种简单数据库。。。与它比 pg就是核弹级别的

pg 与 sql server 是同类型的 但是跨平台和扩展性更好

单文件数据库的话,我现在更倾向于选择sqlit

不能跨平台的 win 专用的软件 我现在基本上不考虑
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

APP|手机版|小黑屋|关于我们|联系我们|法律条款|技术知识分享平台

闽公网安备35020502000485号

闽ICP备2021002735号-2

GMT+8, 2024-5-14 10:18 , Processed in 0.124801 second(s), 11 queries , Redis On.

Powered by Discuz!

© 2006-2023 smzj.net

快速回复 返回顶部 返回列表