ESP8266填坑记录(一)连接百度云天工

1 篇文章 0 订阅
0 篇文章 0 订阅

版权声明:本文为原创文章,允许转载,转载时请务必标明文章原始出处 。
https://blog.csdn.net/siaszhangjie/article/details/84104382

刚开始使用Arduino和ESP8266及NodeMcu板子,一个坑接着一个坑,一些群或者百度是无法理解和回答简单的白痴问题的,只能自己慢慢摸索,在此慢慢记录填坑过程。

百度云天工配置

通过百度账号,登录百度云天宫,创建项目,目前物管理是免费的,提供的每月100万条的数据额度,测试学习是够用的。

有时候会有活动,赠送时序数据库,用来学习测试是很好的平台,-.- 广告了一波

注意的是:设备项目只能创建一个,而且不能够删除和编辑!,虽然影响不大,但是起个好听的名字吧

当时为了测试,随便起的一个名字,后来发现不能修改和删除,真闹心 -_- !

完成项目创建后,跟着说明开始创建物模型和物影子,这个都比较简单,略过,最终建好之后是这个样子:
物模型列表
图一
物模型详细
图二

这里说明一下,数据类型能够使用数字的尽量不用字符串
创建好的物影子
图三
完成以上后,在任意MQTT测试工具中根据<物详情>给的连接配置进行连接测试
连接配置
图四

MQTT在线测试

很多测试工具但都需要配置环境,比较麻烦,推荐大家可以使用“通信猫”这个在线工具进行测试,但是目前的问题是,通信猫只能连接8884端口,而且需要勾选TLS,哪位知道原因,请留言
通信猫在线测试
图五
测试通过之后,就可以选择一种ESP8266固件进行连接了;

固件选择

这里也不多过于介绍,根据自己购买的硬件进行选择,网上很多教程了,可以选择Arduino直接烧录,也可以选择NodeMcu板相应固件,也可以选择Mongoose OS,亦可以百度云天工的SDK自己编译,也可以选择乐鑫官方固件进行烧录等等。

Arduino

这个东西比较方便,语法也相对容易理解,入门很合适;
MQTT采用PubSubClient库,给Arduino添加上PubSubClient后(通过项目->加载库->管理库 添加),在“文件”->“示例”中会多出如下示例
增加PubSubClient
图六

说这个东西的目的是记录一下,自己爬的一个坑,具体问题如下:
订阅百度云天工物影子的属性变化

$baidu/iot/shadow/smartlamp001/update/documents

代码如下:

#include <ESP8266WiFi.h>
#include <PubSubClient.h>

const char *ssid = "xxxxxxx"; //wifi账号
const char *password = "xxxxxxx";//wifi密码
const char *mqtt_server = "112.34.115.12";                                // 使用的信息中转服务
const char *subTopic = "$baidu/iot/shadow/xxx/update/documents"; // 订阅信息主题
const char *pubTopic = "$baidu/iot/shadow/xxx/update";
const char *client_id = "xxxxxx"; // 标识当前设备的客户端编号
const char *mqtt_username = "xxxxxxxx";
const char *mqtt_password = "xxxxxxx";

WiFiClient espClient;           // 定义wifiClient实例
PubSubClient mqttclient(espClient); // 定义PubSubClient的实例
long lastMsg = 0;               // 记录上一次发送信息的时长

void callback(char *topic, byte *payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  Serial.println();
  Serial.println(String(length));
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}

void setup()
{
  pinMode(0, OUTPUT); // 定义板载LED灯为输出方式
  Serial.begin(115200);
  setup_wifi();                        //执行Wifi初始化,下文有具体描述
  mqttclient.setServer(mqtt_server, 1883); //设定MQTT服务器与使用的端口,1883是默认的MQTT端口
  mqttclient.setCallback(callback);        //设定回调方式,当ESP8266收到订阅消息时会调用此方法
  delay(1500);
}

void setup_wifi()
{
  delay(10);
  // 板子通电后要启动,稍微等待一下让板子点亮
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED)
  {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect()
{
  while (!mqttclient.connected())
  {
    Serial.print("Attempting MQTT connection...");
    // Attempt to connect
    if (mqttclient.connect(client_id, mqtt_username, mqtt_password))
    {
      Serial.println("connected");
    
      if (mqttclient.subscribe(subTopic, 1))
      {
        Serial.println("subscribe success");
      }
      else
      {
        Serial.println("subscribe fail");
      }
    }
    else
    {
      Serial.print("failed, rc=");
      Serial.print(mqttclient.state());
      Serial.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void loop()
{
  if (!mqttclient.connected())
  {
    reconnect();
  }
  mqttclient.loop();
  
  digitalWrite(0, HIGH);
  delay(1000);
  digitalWrite(0, LOW);
  delay(1000);
  //  long now = millis();
  //  if (now - lastMsg > 2000) {
  //    lastMsg = now;
  //    client.subscribe(TOPIC);
  //  }
}

上面的代码很简单,就是连接wifi,连接MQTT服务器,然后订阅一下属性值变化Topic,当收到信息时,执行callback函数;

 mqttclient.setCallback(callback); 
void callback(char *topic, byte *payload, unsigned int length)
{
 Serial.print("Message arrived [");
 Serial.print(topic);
 Serial.print("] ");
 Serial.println();
 Serial.println(String(length));
 for (int i = 0; i < length; i++)
 {
   Serial.print((char)payload[i]);
 }
 Serial.println();
}

通过MQTT测试工具发布物影子属性变化,死活callback没有反应,通过物影子中“模型数据的编辑”也会自动发布物影子属性变化的Topic,可以用来测试,但问题是还是没有反应,提示订阅成功,但就是收不到订阅的数据,callback中输出length,一直为0 ,经过一天的试来试去,放弃------

睡了一个好觉后,接着找问题,猜测是不是PubSubClient这个库的问题,查看了一下这个库的源码,看到一个可疑的字段:

uint16_t PubSubClient::readPacket(uint8_t* lengthLength) {
    uint16_t len = 0;
    if(!readByte(buffer, &len)) return 0;
    bool isPublish = (buffer[0]&0xF0) == MQTTPUBLISH;
    uint32_t multiplier = 1;
    uint16_t length = 0;
    uint8_t digit = 0;
    uint16_t skip = 0;
    uint8_t start = 0;

    do {
        if (len == 5) {
            // Invalid remaining length encoding - kill the connection
            _state = MQTT_DISCONNECTED;
            _client->stop();
            return 0;
        }
        if(!readByte(&digit)) return 0;
        buffer[len++] = digit;
        length += (digit & 127) * multiplier;
        multiplier *= 128;
    } while ((digit & 128) != 0);
    *lengthLength = len-1;

    if (isPublish) {
        // Read in topic length to calculate bytes to skip over for Stream writing
        if(!readByte(buffer, &len)) return 0;
        if(!readByte(buffer, &len)) return 0;
        skip = (buffer[*lengthLength+1]<<8)+buffer[*lengthLength+2];
        start = 2;
        if (buffer[0]&MQTTQOS1) {
            // skip message id
            skip += 2;
        }
    }

    for (uint16_t i = start;i<length;i++) {
        if(!readByte(&digit)) return 0;
        if (this->stream) {
            if (isPublish && len-*lengthLength-2>skip) {
                this->stream->write(digit);
            }
        }
        if (len < MQTT_MAX_PACKET_SIZE) {
            buffer[len] = digit;
        }
        len++;
    }

    if (!this->stream && len > MQTT_MAX_PACKET_SIZE) {
        len = 0; // This will cause the packet to be ignored.
    }

    return len;
}

MQTT_MAX_PACKET_SIZE

转到这个字段的定义:

#define MQTT_MAX_PACKET_SIZE 128

只能接收128字节,超过则返回len=0

 if (!this->stream && len > MQTT_MAX_PACKET_SIZE) {
        len = 0; // This will cause the packet to be ignored.
    }

而获取到的数据是变化前的数据和变化后的数据,字符比较多,是超过128字节的,问题找到了,修改吧,直接加个0

#define MQTT_MAX_PACKET_SIZE 128

果然,就这么好了
端口测试工具
图七

Mongoose OS

这个支持方式比较灵活,可以使用JavaScript,可以使用C语言,可以直接将Arduino代码拿来直接使用,有别于其他的是:有web UI界面,可以通过web进行编写代码和修改配置,当然,那是老版本,新版本配置项只能通过脚本进行修改:

下载Mos,windows版本,直接双击运行
Mos
图八

Mos tool 常用脚本:

mos build(执行编译)、mos flash(执行上传)、mos wifi WiFi账号 WiFi密码(wifi配置)、mos update 2.3(将mos tool 更新到指定版本)网上的教程基本上都是2.3,现在已经是2.7了;mos clone https://github.com/mongoose-os-apps/demo-js app1(从官方下载实例并命名为app1)

常用方法

1、mos clone 下载dome,在app1 文件夹中 修改 fs/init.js 编写自己的业务逻辑
业务逻辑
图九

2、用户自定义配置,需要在fs文件夹中添加conf9.json,进行配置的覆盖,刚开始使用Mongoose OS时,这块花了不少时间,添加的是conf0.json,一直出现各种问题,具体为什么是conf9.json自行百度吧。只是一个文件合并和覆盖的过程。
config9.json配置
图十
3、mos build 、mos flash
如果使用的是这个ESP8266
ESP8266
图十一

需要连接CH340G,USB转TTL连接到电脑上,具体连线需要查一下,FLASH需要将GIO0接低电平;
如果使用的是NodeMcu板子就直接flash就行了,不用任何操作比较方便新手还是建议使用NodeMcu
NodeMcu
图十二

当然,会比ESP8266贵一点点

通过以上配置,ESP8266就可以和天工MQTT服务器连接,并上传温湿度数据,完成了自己的室温监控,加上百度云天工的时序数据库,就可以记录历史数据了;

配置物可视

创建物影子时,需要选择存储配置
物影子存储配置
图十三

存储数据成功后,就可以进行仪表盘创建了
仪表盘列表
图十四

1、创建数据表

创建数据表
图十五

比较简单,选择新建,选择数据来源:也就是类型:时序数据库或者设备影子或者静态数据,完成数据表创建后,进行仪表盘拖拽和数据绑定

2、创建仪表盘

最终效果
绑定完成数据后,一个进行发布了。 分享可以生成一个Url,就可以远程查看指标数据了!!

连接百度云并在 ESP8266 上使用 SSL,您需要执行以下步骤: 1. 首先,您需要获取百度云的 SSL 证书。可以在 https://developer.baidu.com/console#app/project 下载 SSL 证书。 2. 将证书文件转换为 PEM 格式。您可以使用 OpenSSL 工具将证书转换为 PEM 格式。 3. 将 PEM 证书上传到 ESP8266。您可以使用 SPIFFS(SPI Flash File System)将证书文件上传到 ESP8266。 4. 在 ESP8266 上创建 SSL/TLS 连接。使用 Arduino IDE 和 ESP8266WiFiSSL 库,您可以使用以下代码来创建 SSL 连接: ``` #include <ESP8266WiFi.h> #include <ESP8266WiFiSSL.h> const char* ssid = "your_SSID"; const char* password = "your_PASSWORD"; const char* host = "your_HOST"; const int httpsPort = 443; const char* root_ca = \ "-----BEGIN CERTIFICATE-----\n" \ "YOUR_ROOT_CA_CERTIFICATE_HERE" \ "-----END CERTIFICATE-----\n"; void setup() { Serial.begin(115200); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.println("Connecting to WiFi..."); } Serial.println("Connected to WiFi"); WiFiClientSecure client; client.setCACert(root_ca); if (!client.connect(host, httpsPort)) { Serial.println("Connection Failed"); return; } String url = "/your_API_endpoint"; client.print(String("GET ") + url + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Connection: close\r\n\r\n"); Serial.println("Request sent"); while (client.connected()) { String line = client.readStringUntil('\n'); if (line == "\r") { Serial.println("Response:"); } else if (line != "") { Serial.println(line); } } client.stop(); Serial.println("Disconnected"); } void loop() {} ``` 在这个示例中,您需要将 Wi-Fi SSID、密码、主机名和 API 端点替换为您自己的值。根证书需要在 `root_ca` 字符串中提供。 这是一个简单的示例,您可以根据自己的需求进行修改。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值