Untitled

mail@pastecode.io avatar
unknown
plain_text
2 years ago
6.8 kB
1
Indexable
Never
 /**
 * A mqtt wrapper for ESP01(ESP8266) using serial ports.
 */

#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Dictionary.h>
#define DEBUG false
#define DEBUG_SERIAL if(DEBUG)Serial
#define BUFFER_SIZE 30

// WiFi
const char *ssid = "mqtt8266"; // Enter your WiFi name
const char *password = "espesp8266";  // Enter WiFi password

// MQTT Broker 配置mosquitto.org公共服务
bool mqtt_is_ready = false;
const char *mqtt_broker = "test.mosquitto.org";
const char *topic_log = "Boiler/log";
const char *topic_power = "Boiler/power";
const char *topic_switch = "Boiler/switch";
const char *topic_soakset = "Boiler/soaktime";
const char *topic_firstset = "Boiler/firstTime";
const char *topic_secondset = "Boiler/secondTime";
const char *mqtt_username = "smart_pot";
const char *mqtt_password = "smart_pot";
const int mqtt_port = 1883;

// For embedded C, a fixed-length buffer will be good.
// 对于嵌入式C, 固定长度的缓冲区比较合适
byte uart_send[BUFFER_SIZE];
byte uart_in[BUFFER_SIZE];
bool new_from_server = false;
bool new_from_device = false;

Dictionary *dict;

WiFiClient espClient;
PubSubClient client(espClient);

void blink(int times, int gap)
{
  for(int i = 0; i < times; i++)
  {
    digitalWrite(LED_BUILTIN, LOW);   // Turn the LED on 
    delay(gap);
    digitalWrite(LED_BUILTIN, HIGH);  // Turn the LED off
    delay(gap * 2);
  }
}

void serialEvent() {
  if (Serial.available() > 0) {
    // read the incoming byte:
    int incomingByte = Serial.readBytes(uart_in, BUFFER_SIZE);
    // say what you got:

    if (uart_in[0] == 0xAB && uart_in[1] == 0xCD) {
      if (mqtt_is_ready) {
          uart_send[0] = 0xAB;
          uart_send[1] = 0xCD;
          Serial.write(uart_send, BUFFER_SIZE);
          Serial.flush();
      }
      else {
          uart_send[0] = 0xFF;
          uart_send[1] = 0xFF;
          Serial.write(uart_send, BUFFER_SIZE);
          Serial.flush();
      }

    }
    DEBUG_SERIAL.print("I received: ");
    DEBUG_SERIAL.print(incomingByte, DEC);
    DEBUG_SERIAL.print(" bytes: ");
    for(int i=0; i < incomingByte; i++){
      DEBUG_SERIAL.print(uart_in[i], HEX);
    }
    DEBUG_SERIAL.println("");

    new_from_device = true;

  }
}

byte checksum(const byte *uart_buf, uint len){
  uint sum = 0;
  for(byte i = 0; i < len; i++){
    sum += uart_buf[i];
  }
  byte result = sum & 0xFF;

  return result;
}


void uart_pack_msg(char *topic, byte *msg, byte *uart_buf, unsigned int length)
{
  uint len = length + 3;
  for (uint i = 0; i <= dict->size(); i++)
  {
    if (i == dict->size()) break;
    if (dict->key(i) == String(topic)) uart_buf[0] = dict->value(i).toInt();
  }

  // if (strcmp(topic,"esp8266/msg")==0)
  // {
  //   uart_buf[0]=MSG;
  // }
  // else if (strcmp(topic,"esp8266/led")==0)
  // {
  //   uart_buf[0]=LED;
  // }

  uart_buf[1] = len;
  for(uint i = 0; i < length; i++)
  {
    uart_buf[i+2] = msg[i];
  }
  
  uart_buf[len-1] = checksum(uart_buf, len - 1);
}


void parse_and_publish(byte *msg)
{
  // default topic
  String topic_s = "esp8266/log";
  // msg[1] holds the length of whole msg with payload from msg[2] ~ msg[msg[1] - 1]
  if ( checksum(msg, msg[1] - 1 ) ==  msg[msg[1] - 1])
  {
    DEBUG_SERIAL.print("msg[0]: ");
    DEBUG_SERIAL.println(String(msg[0]));
    for (uint i = 0; i <= dict->size(); i++)
    {
      if (i == dict->size()) break;
      if (dict->value(i) == String(msg[0])) topic_s = dict->key(i);
    }

    const uint plen = msg[1] - 3;
    if( client.publish( topic_s.c_str(), &msg[2], plen))
    {
      DEBUG_SERIAL.println("msg published");
      blink(2, 100);
    }
    else
    {
      DEBUG_SERIAL.println("error in publish");
      blink(4, 50);
    }
  }
  else
  {
    DEBUG_SERIAL.println("wrong sum check!");
  }

}

void callback(char *topic, byte *payload, unsigned int length) {
  DEBUG_SERIAL.print("\nMessage arrived in topic: ");
  DEBUG_SERIAL.println(topic);
  DEBUG_SERIAL.print("Message with: ");
  DEBUG_SERIAL.print(length, DEC);
  DEBUG_SERIAL.print(" bytes: ");
  for (int i = 0; i < length; i++) {
      DEBUG_SERIAL.print((char) payload[i]);
  }
  DEBUG_SERIAL.println();
  DEBUG_SERIAL.println("-----------------------");

  uart_pack_msg(topic, payload, uart_send, length);
  new_from_server = true;

}

void setup() {
  dict = new Dictionary();
  dict->insert("Boiler/log", String(0xA0));
  dict->insert("Boiler/temper", String(0xA1));
  dict->insert("Boiler/switch", String(0xA2));
  dict->insert("Boiler/soaktime", String(0xA3));
  dict->insert("Boiler/firstTime", String(0xA4));
  dict->insert("Boiler/secondTime", String(0xA5));
  dict->insert("Boiler/soakprogress", String(0xA6));
  dict->insert("Boiler/firstboil", String(0xA6));
  dict->insert("Boiler/secondboil", String(0xA7));
  dict->insert("Boiler/dryalarm", String(0xA8));
  dict->insert("Boiler/finish", String(0xA9));
  dict->insert("Boiler/power", String(0xAA));
  // Set software serial baud to 115200;
  Serial.begin(115200);
  pinMode(LED_BUILTIN, OUTPUT);     // Initialize the LED_BUILTIN pin as an output
  // connecting to a WiFi network
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
      //delay(500);
      blink(1, 1000);
      DEBUG_SERIAL.println("Connecting to WiFi..");
  }
  blink(3, 100);
  DEBUG_SERIAL.println("Connected to the WiFi network");
  //connecting to a mqtt broker
  client.setServer(mqtt_broker, mqtt_port);
  client.setCallback(callback);
  while (!client.connected()) {
      String client_id = "esp8266-client-";
      client_id += String(WiFi.macAddress());
      DEBUG_SERIAL.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());
      if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {
          DEBUG_SERIAL.println("Public mosquitto mqtt broker connected");
          mqtt_is_ready = true;
          blink(4, 50);
      } else {
          DEBUG_SERIAL.print("failed with state ");
          DEBUG_SERIAL.print(client.state());
          delay(2000);
      }
  }
  // publish and subscribe
  client.publish(topic_log, "hello mqtt");
  client.subscribe(topic_power);
  client.subscribe(topic_firstset);
  client.subscribe(topic_secondset);
  client.subscribe(topic_switch);
  client.subscribe(topic_soakset);
}



void loop() {

  client.loop();

  if(new_from_server)
  {
    Serial.write(uart_send, BUFFER_SIZE);
    Serial.flush();
    blink(1, 100);
    new_from_server = false;
  }

  if(new_from_device)
  {
    parse_and_publish(uart_in);
    new_from_device = false;
  }
  delay(50);
}