Arduino MQTT通信库-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 10963|回复: 9

Arduino MQTT通信库

[复制链接]
发表于 2017-8-14 18:07 | 显示全部楼层 |阅读模式
github:
https://github.com/knolleary/pubsubclient

该库支持以下设备:
Arduino Ethernet
Arduino Ethernet Shield
Arduino YUN
Arduino WiFi Shield
Sparkfun WiFly Shield – library
TI CC3000 WiFi - library
Intel Galileo/Edison
ESP8266




发表于 2018-10-19 10:30 | 显示全部楼层
谢谢楼主分享。
发表于 2019-1-14 11:09 | 显示全部楼层


您好,我按照例子,写的程序,发布消息没问题,mqtt服务器可以接受,但UNO却无法接受订阅消息,是哪里出了问题?
[mw_shl_code=arduino,true]
#include <OneWire.h>
#include <U8glib.h>
#include <MsTimer2.h>
#include <WiFiEsp.h>
#include <WiFiEspUdp.h>
#include <WiFiEspClient.h>
#include <PubSubClient.h>
#include <SoftwareSerial.h>
#define MqttServer_IP "10.1.3.172" // 连接服务器
#define MqttServer_PORT 1883 // 连接服务器8234
#define WIFI_AP "z"
#define WIFI_PASSWORD "3333222222"
#define ID "10002"
int status = WL_IDLE_STATUS;     // the Wifi radio's status
float celsius;
bool flag_second;//每秒触发一次,用于每隔1秒,串口发送一次数据
byte addr[8];
byte pwmpin=5;//UNO中只能用 3,5,6,9,10,11
String inString="";//输入指令字符 SET_PWM=52
String PWM_valStr;
byte PWM_val=255;//0-255,越大,速度越慢

const byte interruptPin = 3;//脉冲输入IO ,UNO中断引脚只有 pin2 (int0) 和 pin3(int1)
byte Val = 0; //设置变量 Val,计数 (服务器散热风扇,12V下最高风速时,162转/s)
byte Val_n = 0; //每秒多少转
unsigned int RPM = 0; //每分多少转
OneWire  ds(13);  // on pin 10 (a 4.7K resistor is necessary)
U8GLIB_KS0108_128 u8g(6, 7, 8, 9, 10,11, 12, A0,     A1, A2, A3, A4, A5 );
//U8GLIB_KS0108_128 u8g(6(pin 7), 7(pin 8), 8(pin 9), 9(pin 10), 10(pin 11),11(pin 12), 12(pin 13), A0(pin 14)     A1(pin 6), A2(pin 15), A3(pin 16), A4(pin 4), A5(pin 5) );
//          8Bit Com: D0..D7: 8,9,10,11,4,5,6,7 en=18, cs1=14, cs2=15,di=17,rw=16
//YXD-12864BG液晶屏1.Vss   2.+3.3V  3.背光调节  4.RS Comand/Data Input 5.R/W Read/Write Signal Input 6.E 7.D0 8.D1 9.D2 10.D3 11.D4 12.D5 13.D6 14.D7 15.CS1 16.CS2 17.RES 18.Vout 19.LED +5V 20.GND
SoftwareSerial Serial_wifi(2, 4); // RX, TX
// 初始化以太网客户端对象
WiFiEspClient espClient;
// 初始化MQTT库PubSubClient.h的对象
PubSubClient client(espClient);
void setup(void) {
  Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(interruptPin), count, FALLING);//FALLING  RISING CHANGE
  InitWiFi();                                // 连接WiFi
  client.setServer( MqttServer_IP, MqttServer_PORT);      // 连接WiFi之后,连接MQTT服务器
  client.setCallback(callback);
  client.subscribe("v1/devices/me/IntelligentFan_CMD");
  pinMode(pwmpin, OUTPUT);
   // 中断设置函数,每 1000ms 进入一次中断
   MsTimer2::set(1000, rpm_count);
   MsTimer2::start();  
}

void loop(void) {
  initDs18b20();//ds18b20中间取温度需要 750ms 用delay太浪费所以,程序分成两部分,运行其他
  
  status = WiFi.status();
  if ( status != WL_CONNECTED) {
    while ( status != WL_CONNECTED) {
      Serial.print("[loop()]Attempting connect to WPA SSID: ");
      Serial.println(WIFI_AP);
      // 连接WiFi热点
      status = WiFi.begin(WIFI_AP, WIFI_PASSWORD);
      delay(500);
    }
    Serial.println("[loop()]Connected to AP");   
  }
  if ( !client.connected() ) {
    reconnect();
  }
  client.loop();
  /*
  while(Serial.available()>0){
    char inChar= Serial.read();
    inString +=(char) inChar;
    delay(10);
  }
  if(inString!=""){
    Serial.print("Input String:");  
    Serial.println(inString);
   
    PWM_valStr=inString.substring(8);//SET_PWM=52
    PWM_val=PWM_valStr.toInt();   
    Serial.println(PWM_val);
   
//    analogWrite(pwmpin, PWM_val);
  inString="";
  }
  */
  analogWrite(pwmpin, PWM_val);//设置pwm,
  //每秒发送一次数据
  if(flag_second==1){
    getandSendTemperatureAndRPMData();   
    //每秒标记
    flag_second=0;   
  }


  draw();  
  //delay(500);
  getDs18b20WenDu();
  

}
void initDs18b20(void) {
  byte i;
  if ( !ds.search(addr)) {
    //Serial.println("No more addresses.");
    ds.reset_search();
    delay(250);
    return;
  }

  //Serial.print("ROM =");
  //for ( i = 0; i < 8; i++) {
    //Serial.write(' ');
    //Serial.print(addr, HEX);
// }

  if (OneWire::crc8(addr, 7) != addr[7]) {
    Serial.println("CRC is not valid!");
    return;
  }
  //Serial.println();



  ds.reset();
  ds.select(addr);
  ds.write(0x44, 1);        // start conversion, with parasite power on at the end

  //delay(1000);     // maybe 750ms is enough, maybe not
  // we might do a ds.depower() here, but the reset will take care of it.
}

void getDs18b20WenDu(void) {
  byte i;
  byte present = 0;
  byte data[12];

  present = ds.reset();
  ds.select(addr);
  ds.write(0xBE);         // Read Scratchpad
  for ( i = 0; i < 9; i++) {           // we need 9 bytes
    data = ds.read();
    //Serial.print(data, HEX);
    //Serial.print(" ");
  }

  int16_t raw = (data[1] << 8) | data[0];

    byte cfg = (data[4] & 0x60);
    // at lower res, the low bits are undefined, so let's zero them
    if (cfg == 0x00) raw = raw & ~7;  // 9 bit resolution, 93.75 ms
    else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
    else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
    //// default is 12 bit resolution, 750 ms conversion time

  celsius = (float)raw / 16.0;
  //Serial.print("  T = ");//Temperature
  //Serial.println(celsius);
  //Serial.print(" Celsius, ");

}
/*
*
* 把温度、转速发送到MQTT服务器上去
*
*/
void getandSendTemperatureAndRPMData()
{
  Serial.println("Collecting data.");
  //温度
  Serial.print("T=");//Temperature
  Serial.print(celsius,2);
  //转速
  Serial.print("; V=");
  Serial.print(Val_n);//Val是1秒钟转多少圈
  Serial.print("; RPM=");
  RPM=60*Val_n;
  Serial.print(RPM);//转换成rpm,Val是1秒钟转多少圈,rpm=60*val
  Serial.println(";");
  String celsiusString = String(celsius);
  String Val_nString = String(Val_n);  
  String RPMString = String(RPM);
  // 构建一个 JSON 格式的payload的字符串
  String payload = "{";
  payload += "\"temperature\":"; payload += celsiusString; payload += ",";
  payload += "\"Val\":"; payload += Val_nString;
  payload += ",\"RPM\":"; payload += RPMString;
  payload += "}";
  // Send payload
  char attributes[100];
  //payload.toCharArray( attributes, 100 );
  payload.toCharArray( attributes, 90 );
  // boolean publish(const char* topic, const char* payload);  
  client.publish( "v1/devices/me/IntelligentFan", attributes );
  Serial.print("[publish]-->>");
  Serial.println( attributes );
}
void InitWiFi()
{
  // 初始化软串口,软串口连接ESP模块
  Serial_wifi.begin(9600);
  // 初始化ESP模块
  WiFi.init(&Serial_wifi);
  // 检测WiFi模块在不在,宏定义:WL_NO_SHIELD = 255,WL_IDLE_STATUS = 0,
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println("WiFi not present");
    while (true);
  }

  Serial.println("[InitWiFi]Connect AP ...");
  // 尝试连接WiFi网络
  while ( status != WL_CONNECTED) {
    Serial.print("[InitWiFi]Attempt connect WPA SSID: ");
    Serial.println(WIFI_AP);
    // Connect to WPA/WPA2 network
    status = WiFi.begin(WIFI_AP, WIFI_PASSWORD);
    delay(500);
  }
  Serial.println("[InitWiFi]Connected AP");
}
/**
*
* MQTT客户端断线重连函数
*
*/

void reconnect() {
  // 一直循环直到连接上MQTT服务器
  while (!client.connected()) {
    Serial.print("[reconnect]Connect MQTT Server ...");
    // 尝试连接connect是个重载函数 (clientId, username, password)
  //boolean connect(const char* id, const char* willTopic, uint8_t willQos, boolean willRetain, const char* willMessage);
  //client.connect(ID, "v1/devices/me/telemetry_will",0, 0,"willdead");
    if ( client.connect(ID, "v1/devices/me/IntelligentFan_will",0, 0,"willdead") ) {//该设备的遗愿信息,如果mqtt服务器收不到信号,就会向订阅号发willdead信息
    //if ( client.connect(ID, NULL, NULL) ) {
    client.subscribe("v1/devices/me/IntelligentFan_CMD");
      Serial.println( "[DONE]" );
    } else {
      Serial.print( "[FAILED][mqtt connect error code=" );
      Serial.print( client.state() );
      Serial.println( " :retrying in 3 seconds]" );// Wait 5 seconds before retrying
      delay( 3000 );
    }
  }
}
void callback(char* topic, byte* payload, unsigned int length) {
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i=0;i<length;i++) {
    Serial.print((char)payload);
  }
  Serial.println();
}
void draw(void) {
  u8g.firstPage();
  do {
  //u8g.setColorIndex(1);
  u8g.setFont(u8g_font_unifont);
  //u8g.setFont(u8g_font_osb21);
  u8g.drawStr( 0, 40, "T:");
  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(16, 40);
  u8g.print(celsius, 2);  
  //u8g.drawBitmapP ( 0 , 0 , 2 , 16 , bitmap_z);
  //u8g.drawBitmapP ( 17 , 0 , 2 , 16 , bitmap_s );
  //u8g.drawBitmapP ( 33 , 0 , 2 , 16 , bitmap_j );
  u8g.drawStr( 0, 52, "V:");
  u8g.setFont(u8g_font_unifont);
  u8g.setPrintPos(16, 52);
  u8g.print(Val_n);
  u8g.drawStr( 0,64, "RPM:");
  u8g.setPrintPos(32, 64);
  u8g.print(RPM);  
  } while ( u8g.nextPage() );
}
void count() {
  Val += 1;
}
void rpm_count() {
  Val_n = Val;
  flag_second=1;
  Val = 0;//输出速度结果后清零,记录下一秒的触发次数
}[/mw_shl_code]
发表于 2020-4-20 14:28 | 显示全部楼层
xxzxzj 发表于 2019-1-14 11:09
您好,我按照例子,写的程序,发布消息没问题,mqtt服务器可以接受,但UNO却无法接受订阅消息,是哪里出 ...

我也遇到了这个问题,请问解决了吗?
发表于 2020-5-17 18:15 | 显示全部楼层
大佬,我查看API文档的时候,发现publish中的负载只能是常数,如果我想将传感器的实时变量publish,我该怎么办呢?
发表于 2020-5-19 00:34 | 显示全部楼层
YGCall 发表于 2020-5-17 18:15
大佬,我查看API文档的时候,发现publish中的负载只能是常数,如果我想将传感器的实时变量publish,我该怎 ...

实在惭愧,是本人语言基础没打好,这里只需要定义一个数组常量指针,指向数组变量就行了。万分感谢。
发表于 2020-10-20 12:10 | 显示全部楼层
xxzxzj 发表于 2019-1-14 11:09
您好,我按照例子,写的程序,发布消息没问题,mqtt服务器可以接受,但UNO却无法接受订阅消息,是哪里出 ...

请问问题解决了吗?
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 07:26 , Processed in 0.173510 second(s), 15 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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