8266 advanced part: onenet actual combat PubSubClient Library

Posted by Shaun13 on Sun, 16 Jan 2022 23:10:53 +0100

Article source address: https://blog.csdn.net/dpjcn1990/article/details/92831686

1. Preface

In the ESP8266 learning series, bloggers have been using HTTP protocol. HTTP connection belongs to short connection, but MQTT protocol is widely used in Internet of things applications. Therefore, in this article, we will learn the MQTT implementation library PubSubClient on Arduino platform.

2.MQTT protocol

2.1 introduction

MQTT protocol (message queuing Telecommunication Transport), translated as telesignaling message queue transmission, was proposed by IBM in 1999. Now the latest version is 3.1.1. MQTT is a publish subscribe protocol based on TCP. The initial purpose of the design is for the unreliable communication of the network with very limited memory devices and low network bandwidth, which is very suitable for the communication of the Internet of things.

MQTT is an application layer protocol based on TCP protocol to ensure reliability. Bloggers will not talk about MQTT protocol in detail here (there are many contents of MQTT protocol on the Internet, which do not need to be repeated). I hope interested readers can read it by themselves, which can be used for reference MQTT Chinese document.

The MQTT communication model is as follows:

  • The Publisher sends the message to the Broker (MQTT server);
  • After receiving the message, the Broker checks which subscribers subscribe to the message, and then sends the message to these subscribers;
  • The Subscriber gets the message from the Broker.

2.2 QOS of mqtt message

MQTT messages support three QOS levels:

  • QoS 0: "at most once", message publishing completely depends on the underlying TCP/IP network. Distributed messages may be missing or duplicate. For example, this level can be used for environmental sensor data. A single data loss does not matter, because there will be a second transmission in the near future.
  • QoS 1: "at least once" ensures that the message can arrive, but the message may be repeated.
  • QoS 2: "only once" ensures that messages arrive only once. For example, this level can be used in a billing system, where repeated or lost messages will lead to incorrect charging.

2.3 format of mqtt control message

MQTT control message consists of three parts:

  • Fixed header: each MQTT control message contains a fixed header; The fixed header indicates the control message type, flag and remaining length.
  • Variable header: some MQTT control messages contain a variable header; It is between the fixed header and the payload; The content of variable header varies according to different message types, usually including Packet Identifier;
  • Payload: some MQTT control messages contain a payload in the last part of the message, that is, the data information carried;

On the whole, MQTT overall control message protocol is:

Fixed header (certain) + variable header (partial) + payload (partial)

The data structure is simple and the amount of data transmitted is small, which is one of the reasons why it can be applied to the Internet of things.

2.4 MQTT control message

2.4.1 CONNECT - connect the server

Note:

  • After the network connection from the client to the server is established, the first message sent by the client to the server must be CONNECT message;
  • On a network connection, the client can only send CONNECT message once. The server must treat the second CONNECT message sent by the client as a protocol violation and disconnect the client;
  • The payload contains one or more encoded fields. This includes the client's unique identifier, Will topic, Will message, user name and password. In addition to the client ID, other fields are optional. Whether these fields need to be included in the variable header is determined based on the flag bit.

Message format:

Fixed header + variable header + payload

  • Fixed header: mqttconnect (1 < < 4)
  • Variable header: Protocol Name, Protocol Level, Connect Flags and Keep Alive
  • Payload: client identifier, will subject, will message, user name, password

2.4.2 CONNACK - confirm connection request

Note:

  • The server sends CONNACK message in response to the CONNECT message received from the client. The first message sent by the server to the client must be CONNACK;
  • If the client does not receive the CONNACK message from the server within a reasonable time, the client should close the network connection. The reasonable time depends on the type of application and communication infrastructure;

Message format:

Fixed header + variable header

  • Fixed header: mqttconnack (2 < < 4)
  • Variable header: connection confirmation Flag + connection return code

2.4.3 PUBLISH - release message

Note:

  • PUBLISH control message refers to an application message transmitted from the client to the server or from the server to the client;

Message format:

Fixed header + variable header + payload

  • Fixed header: mqttpublish (3 < < 4), retransmission flag DUP, quality of service level QoS, reservation flag RETAIN, remaining length field
  • Variable header: subject name and message identifier
  • Payload: published application message

2.4.4 PUBACK - release confirmation

Note:

  • The PUBACK message is the response to the PUBLISH message of QoS level 1

Message format:

Fixed header + variable header

  • Fixed header: mqttpuback (4 < < 4), remaining length field
  • Variable header: contains the message identifier of the PUBLISH message waiting for confirmation

2.4.5 PUBREC - publish receive (QoS 2, step 1)

Note:

  • PUBREC message is the response to the PUBLISH message of QoS level 2. It is the second message exchanged by QoS level 2 protocol.

Message format:

Fixed header + variable header

  • Fixed header: mqttpubrec (5 < < 4), remaining length field
  • Variable header: contains the message identifier of the PUBLISH message waiting for confirmation

2.4.6 PUBREL - release (QoS 2, step 2)

Note:

  • PUBREL message is the response to PUBREC message. It is the third message exchanged by QoS level 2 protocol.

Message format:

Fixed header + variable header

  • Fixed header: mqttpubrel (6 < < 4), remaining length field
  • Variable header: contains the same message identifier as the PUBREC message waiting for confirmation.

2.4.7 PUBCOMP - release completion (QoS 2, step 3)

Note:

  • PUBCOMP message is the response to PUBREL message. It is the fourth and last message exchanged by QoS level 2 protocol.

Message format:

Fixed header + variable header

  • Fixed header: mqttpubcomp (7 < < 4), remaining length field
  • Variable header: contains the same message identifier as the PUBREL message waiting for confirmation

2.4.8 SUBSCRIBE - subscription topics

Note:

  • The client sends a SUBSCRIBE message to the server to create one or more subscriptions
  • In order to forward application messages to topics matching those subscriptions, the server sends a PUBLISH message to the client
  • The SUBSCRIBE message also specifies the maximum QoS level (for each subscription), and the server sends application messages to the client according to this

Message format:

Fixed header + variable header + payload

  • Fixed header: mqttsubscribe (8 < < 4), remaining length field
  • Variable header: message identifier
  • Payload: contains a list of topic filters that represent the topics that the client wants to subscribe to

2.4.9 SUBACK - subscription confirmation

Note:

  • The server sends a SUBACK message to the client to confirm that it has received and is processing the SUBSCRIBE message
  • The SUBACK message contains a list of return codes, which specify the maximum QoS level granted to each subscription requested by SUBSCRIBE

Message format:

Fixed header + variable header + payload

  • Fixed header: mqttsuback (9 < < 4), remaining length field
  • Variable header: contains the message identifier of the SUBSCRIBE message waiting for confirmation
  • Payload: contains a list of return codes. Each return code corresponds to a subject filter in the SUBSCRIBE message waiting for confirmation

2.4.10 UNSUBSCRIBE - unsubscribe

Note:

  • The client sends an UNSUBSCRIBE message to the server to UNSUBSCRIBE from the topic

Message format:

Fixed header + variable header + payload

  • Fixed header: mqttunsubscribe (10 < < 4), remaining length field
  • Variable header: message identifier
  • Payload: contains a list of topic filters that the client wants to unsubscribe from

2.4.11 UNSUBACK - unsubscribe confirmation

Note:

  • The server sends an UNSUBSCRIBE message to the client to confirm receipt of the UNSUBSCRIBE message

Message format:

Fixed header + variable header

  • Fixed header: mqttunsuback (11 < < 4), remaining length field
  • Variable header: contains the message identifier of UNSUBSCRIBE message waiting for confirmation

2.4.12 PINGREQ - heartbeat request

Note:

  • The client sends PINGREQ message to the server
  • When no other control message is sent from the client to the server, inform the server that the client is still alive
  • Request the server to send a response to confirm that it is still alive
  • Use the network to confirm that the network connection is not disconnected
  • This message is used in Keep Alive processing

Message format:

Fixed header

  • Fixed header: mqttpingreq (12 < < 4), remaining length field

2.4.13 PINGRESP - heartbeat response

Note:

  • The server sends a PINGRESP message in response to the client's PINGREQ message
  • This message is used in Keep Alive processing

Message format:

Fixed header

  • Fixed header: mqttpingresp (13 < < 4), remaining length field

2.4.14 DISCONNECT - disconnect

Note:

  • DISCONNECT message is the last control message sent by the client to the server.
  • Indicates that the client is disconnected normally.

Message format:

Fixed header

  • Fixed header: mqttdisconnect (14 < < 4), remaining length field

3.PubSubClient - ArduinoMQTT Library

Old rule, last Baidu brain map:

3.1 PubSubClient - initialize constructor

Function 1 Description:

/**
 * Create a PubSubClient object that is not initialized
 */
PubSubClient::PubSubClient() {
    this->_state = MQTT_DISCONNECTED;
    this->_client = NULL;
    this->stream = NULL;
    setCallback(NULL);
}

 

    Before using the PubSubClient object, you must configure the complete content:

    WiFiClient espClient;
    PubSubClient client;
    

    void setup() {
    client.setClient(espClient);
    client.setServer("broker.example.com",1883);
    // client is now configured for use
    }

      Function 2 Description:

      /**
       * Create a partially initialized PubSubClient object
       * @param client client example
       */
      PubSubClient::PubSubClient(Client& client) {
          this->_state = MQTT_DISCONNECTED;
          setClient(client);
          this->stream = NULL;
      }
      
       

        Before using the PubSubClient object, you must configure the complete content:

        WiFiClient espClient;
        PubSubClient client(espClient);
        

        void setup() {
        client.setServer("broker.example.com",1883);
        // client is now configured for use
        }

        • Function 3 Description:

          /**
           * Create a fully initialized PubSubClient object
           * @param addr  mqtt server ip address 
           * @param post  mqtt Server port
           * @param client Client instance
           */
          PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client) {
              this->_state = MQTT_DISCONNECTED;
              setServer(addr, port);
              setClient(client);
              this->stream = NULL;
          }
          

        /**

        • Create a fully initialized PubSubClient object
        • @param addr mqtt server ip address
        • @param post mqtt server port
        • @param client instance
        • @param stream output stream, which will output the received message to the stream
          */
          PubSubClient::PubSubClient(IPAddress addr, uint16_t port, Client& client, Stream& stream) {
          this->_state = MQTT_DISCONNECTED;
          setServer(addr,port);
          setClient(client);
          setStream(stream);
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param addr mqtt server ip address
        • @param post mqtt server port
        • @param MQTT_CALLBACK_SIGNATURE callback method
        • @param client instance
          */
          PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
          this->_state = MQTT_DISCONNECTED;
          setServer(addr, port);
          setCallback(callback);
          setClient(client);
          this->stream = NULL;
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param addr mqtt server ip address
        • @param post mqtt server port
        • @param MQTT_CALLBACK_SIGNATURE callback method
        • @param client instance
        • @param stream output stream, which will output the received message to the stream
          */
          PubSubClient::PubSubClient(IPAddress addr, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
          this->_state = MQTT_DISCONNECTED;
          setServer(addr,port);
          setCallback(callback);
          setClient(client);
          setStream(stream);
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param ip mqtt server ip address
        • @param post mqtt server port
        • @param client instance
          /
          PubSubClient::PubSubClient(uint8_t ip, uint16_t port, Client& client) {
          this->_state = MQTT_DISCONNECTED;
          setServer(ip, port);
          setClient(client);
          this->stream = NULL;
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param ip mqtt server ip address
        • @param post mqtt server port
        • @param client instance
        • @param stream output stream, which will output the received message to the stream
          /
          PubSubClient::PubSubClient(uint8_t ip, uint16_t port, Client& client, Stream& stream) {
          this->_state = MQTT_DISCONNECTED;
          setServer(ip,port);
          setClient(client);
          setStream(stream);
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param ip mqtt server ip address
        • @param post mqtt server port
        • @param client instance
        • @param MQTT_CALLBACK_SIGNATURE callback method
          /
          PubSubClient::PubSubClient(uint8_t ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
          this->_state = MQTT_DISCONNECTED;
          setServer(ip, port);
          setCallback(callback);
          setClient(client);
          this->stream = NULL;
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param ip mqtt server ip address
        • @param post mqtt server port
        • @param client instance
        • @param MQTT_CALLBACK_SIGNATURE callback method
        • @param stream output stream, which will output the received message to the stream
          /
          PubSubClient::PubSubClient(uint8_t ip, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
          this->_state = MQTT_DISCONNECTED;
          setServer(ip,port);
          setCallback(callback);
          setClient(client);
          setStream(stream);
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param domain mqtt server domain name
        • @param post mqtt server port
        • @param client instance
          /
          PubSubClient::PubSubClient(const char domain, uint16_t port, Client& client) {
          this->_state = MQTT_DISCONNECTED;
          setServer(domain,port);
          setClient(client);
          this->stream = NULL;
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param domain mqtt server domain name
        • @param post mqtt server port
        • @param client instance
        • @param stream output stream, which will output the received message to the stream
          /
          PubSubClient::PubSubClient(const char domain, uint16_t port, Client& client, Stream& stream) {
          this->_state = MQTT_DISCONNECTED;
          setServer(domain,port);
          setClient(client);
          setStream(stream);
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param domain mqtt server domain name
        • @param post mqtt server port
        • @param client instance
        • @param MQTT_CALLBACK_SIGNATURE callback method
          /
          PubSubClient::PubSubClient(const char domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client) {
          this->_state = MQTT_DISCONNECTED;
          setServer(domain,port);
          setCallback(callback);
          setClient(client);
          this->stream = NULL;
          }

        /**

        • Create a fully initialized PubSubClient object
        • @param domain mqtt server domain name
        • @param post mqtt server port
        • @param client instance
        • @param MQTT_CALLBACK_SIGNATURE callback method
        • @param stream output stream, which will output the received message to the stream
          /
          PubSubClient::PubSubClient(const char domain, uint16_t port, MQTT_CALLBACK_SIGNATURE, Client& client, Stream& stream) {
          this->_state = MQTT_DISCONNECTED;
          setServer(domain,port);
          setCallback(callback);
          setClient(client);
          setStream(stream);
          }
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32
        • 33
        • 34
        • 35
        • 36
        • 37
        • 38
        • 39
        • 40
        • 41
        • 42
        • 43
        • 44
        • 45
        • 46
        • 47
        • 48
        • 49
        • 50
        • 51
        • 52
        • 53
        • 54
        • 55
        • 56
        • 57
        • 58
        • 59
        • 60
        • 61
        • 62
        • 63
        • 64
        • 65
        • 66
        • 67
        • 68
        • 69
        • 70
        • 71
        • 72
        • 73
        • 74
        • 75
        • 76
        • 77
        • 78
        • 79
        • 80
        • 81
        • 82
        • 83
        • 84
        • 85
        • 86
        • 87
        • 88
        • 89
        • 90
        • 91
        • 92
        • 93
        • 94
        • 95
        • 96
        • 97
        • 98
        • 99
        • 100
        • 101
        • 102
        • 103
        • 104
        • 105
        • 106
        • 107
        • 108
        • 109
        • 110
        • 111
        • 112
        • 113
        • 114
        • 115
        • 116
        • 117
        • 118
        • 119
        • 120
        • 121
        • 122
        • 123
        • 124
        • 125
        • 126
        • 127
        • 128
        • 129
        • 130
        • 131
        • 132
        • 133
        • 134
        • 135
        • 136
        • 137
        • 138
        • 139
        • 140
        • 141
        • 142
        • 143
        • 144
        • 145
        • 146
        • 147
        • 148
        • 149
        • 150
        • 151
        • 152
        • 153
        • 154
        • 155
        • 156
        • 157
        • 158
        • 159
        • 160
        • 161
        • 162
        • 163
        • 164
        • 165
        • 166
        • 167
        • 168
        • 169
        • 170
        • 171
        • 172
        • 173

        3.2 setServer - configure server

        Function Description:

        /**
         * configure server
         * @param ip  MQTT Server ip address, array
         * @param port MQTT Server port
         */
        PubSubClient& PubSubClient::setServer(uint8_t * ip, uint16_t port) {
            IPAddress addr(ip[0],ip[1],ip[2],ip[3]);
            return setServer(addr,port);
        }
        

        /**

        • configure server
        • @param ip MQTT server ip address, IPAddress
        • @param port MQTT server port
          /
          PubSubClient& PubSubClient::setServer(IPAddress ip, uint16_t port) {
          this->ip = ip;
          this->port = port;
          this->domain = NULL;
          return this;
          }

        /**

        • configure server
        • @param domain MQTT server domain address
        • @param port MQTT server port
          /
          PubSubClient& PubSubClient::setServer(const char domain, uint16_t port) {
          this->domain = domain;
          this->port = port;
          return *this;
          }
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8
        • 9
        • 10
        • 11
        • 12
        • 13
        • 14
        • 15
        • 16
        • 17
        • 18
        • 19
        • 20
        • 21
        • 22
        • 23
        • 24
        • 25
        • 26
        • 27
        • 28
        • 29
        • 30
        • 31
        • 32

        be careful:

        • This method returns this pointer, which means that we can implement chain call;

        3.3 setClient - configure client

        Function Description:

        /**
         * Configure client
         * @param client  client Instance, such as WiFi client
         */
        PubSubClient& PubSubClient::setClient(Client& client){
            this->_client = &client;
            return *this;
        }
        
         
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7
        • 8

        be careful:

        • This method returns this pointer, which means that we can implement chain call;

        3.4 setStream - configuration stream

        Function description

        /**
         * Configure a flow that can be used to store message content
         */
        PubSubClient& PubSubClient::setStream(Stream& stream){
            this->stream = &stream;
            return *this;
        }
        
         
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
        • 7

        be careful:

        • This method returns this pointer, which means that we can implement chain call;

        3.5 connected -- judge whether the client is connected to the server

        Function description

        /**
         * Determine whether the client is connected to the server
         * @return bool true Indicates the connection 
         */
        boolean PubSubClient::connected() {
            boolean rc;
            if (_client == NULL ) {
                rc = false;
            } else {
                rc = (int)_client->connected();
                if (!rc) {
                    //Judge connection status
                    if (this->_state == MQTT_CONNECTED) {
                        this->_state = MQTT_CONNECTION_LOST;
                        _client->flush();
                        _client->stop();
                    }
                }
            }
            return rc;
        }
        

          3.6 connect -- CONNECT MQTT service (CONNECT control message)

          Function Description:

          /**
           * CONNECT MQTT service (CONNECT control message)
           * @param id client End identifier
           * @return bool Is the connection successful
           */
          boolean PubSubClient::connect(const char *id) {
              return connect(id,NULL,NULL,0,0,0,0,1);
          }
          

          /**

          • CONNECT MQTT service (CONNECT control message)
          • @param id client identifier
          • @param user account
          • @param pass user password
          • @return bool whether the connection was successful
            /
            boolean PubSubClient::connect(const char id, const char user, const char pass) {
            return connect(id,user,pass,0,0,0,0,1);
            }

          /**

          • CONNECT MQTT service (CONNECT control message)
          • @param id client identifier
          • @param willTopic will topic
          • @param willQos message quality level
          • @param willRetain whether to retain information
          • @param willMessage will content
          • @return bool whether the connection was successful
            /
            boolean PubSubClient::connect(const char id, const char willTopic, uint8_t willQos, boolean willRetain, const char willMessage) {
            return connect(id,NULL,NULL,willTopic,willQos,willRetain,willMessage,1);
            }

          /**

          • CONNECT MQTT service (CONNECT control message)
          • @param id client identifier
          • @param user account
          • @param pass user password
          • @param willTopic will topic
          • @param willQos message quality level
          • @param willRetain whether to retain information
          • @param willMessage will content
          • @return bool whether the connection was successful
            /
            boolean PubSubClient::connect(const char id, const char user, const char pass, const char willTopic, uint8_t willQos, boolean willRetain, const char willMessage) {
            return connect(id,user,pass,willTopic,willQos,willRetain,willMessage,1);
            }

          /**

          • CONNECT MQTT service (CONNECT control message)

          • @param id client identifier

          • @param user account

          • @param pass user password

          • @param willTopic will topic

          • @param willQos message quality level

          • @param willRetain whether to retain information

          • @param willMessage will content

          • @param cleanSession clear session

          • @return bool whether the connection was successful

          • @Note: pay attention to the combination of CONNECT and CONNACK message protocols
            /
            boolean PubSubClient::connect(const char id, const char user, const char pass, const char willTopic, uint8_t willQos, boolean willRetain, const char willMessage, boolean cleanSession) {
            if (!connected()) {
            int result = 0;

             <span class="token keyword">if</span> <span class="token punctuation">(</span>domain <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                 result <span class="token operator">=</span> _client<span class="token operator">-&gt;</span><span class="token function">connect</span><span class="token punctuation">(</span>this<span class="token operator">-&gt;</span>domain<span class="token punctuation">,</span> this<span class="token operator">-&gt;</span>port<span class="token punctuation">)</span><span class="token punctuation">;</span>
             <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                 result <span class="token operator">=</span> _client<span class="token operator">-&gt;</span><span class="token function">connect</span><span class="token punctuation">(</span>this<span class="token operator">-&gt;</span>ip<span class="token punctuation">,</span> this<span class="token operator">-&gt;</span>port<span class="token punctuation">)</span><span class="token punctuation">;</span>
             <span class="token punctuation">}</span>
             <span class="token keyword">if</span> <span class="token punctuation">(</span>result <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                 nextMsgId <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
                 <span class="token comment">// Leave room in the buffer for header and variable length field</span>
                 <span class="token comment">//Fixed header</span>
                 uint16_t length <span class="token operator">=</span> MQTT_MAX_HEADER_SIZE<span class="token punctuation">;</span>
                 <span class="token keyword">unsigned</span> <span class="token keyword">int</span> j<span class="token punctuation">;</span>
            

          //The variable header of the fixed CONNECT message contains four fields: protocol name, protocol level, connection flag and keep connection:
          #if MQTT_VERSION == MQTT_VERSION_3_1
          uint8_t d[9] = { 0x00,0x06,'M','Q','I','s','d','p', MQTT_VERSION};
          #define MQTT_HEADER_VERSION_LENGTH 9
          #elif MQTT_VERSION == MQTT_VERSION_3_1_1
          uint8_t d[7] = { 0x00,0x04,'M','Q','T','T',MQTT_VERSION};
          #define MQTT_HEADER_VERSION_LENGTH 7
          #endif
          for (j = 0;j<MQTT_HEADER_VERSION_LENGTH;j++) {
          buffer[length++] = d[j];
          }

                  <span class="token comment">/******************** Connect Flags start*************************/</span>
                  uint8_t v<span class="token punctuation">;</span>
                  <span class="token comment">//Testamentary theme</span>
                  <span class="token keyword">if</span> <span class="token punctuation">(</span>willTopic<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      v <span class="token operator">=</span> <span class="token number">0x04</span><span class="token operator">|</span><span class="token punctuation">(</span>willQos<span class="token operator">&lt;&lt;</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token operator">|</span><span class="token punctuation">(</span>willRetain<span class="token operator">&lt;&lt;</span><span class="token number">5</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                  <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                      v <span class="token operator">=</span> <span class="token number">0x00</span><span class="token punctuation">;</span>
                  <span class="token punctuation">}</span>
                  <span class="token comment">//Clear session</span>
                  <span class="token keyword">if</span> <span class="token punctuation">(</span>cleanSession<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      v <span class="token operator">=</span> v<span class="token operator">|</span><span class="token number">0x02</span><span class="token punctuation">;</span>
                  <span class="token punctuation">}</span>
                  <span class="token comment">//Account password</span>
                  <span class="token keyword">if</span><span class="token punctuation">(</span>user <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      v <span class="token operator">=</span> v<span class="token operator">|</span><span class="token number">0x80</span><span class="token punctuation">;</span>
          
                      <span class="token keyword">if</span><span class="token punctuation">(</span>pass <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                          v <span class="token operator">=</span> v<span class="token operator">|</span><span class="token punctuation">(</span><span class="token number">0x80</span><span class="token operator">&gt;&gt;</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                      <span class="token punctuation">}</span>
                  <span class="token punctuation">}</span>
          
                  buffer<span class="token punctuation">[</span>length<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> v<span class="token punctuation">;</span>
                 <span class="token comment">/***********************Connect Flags end******************************************************/</span>
                 <span class="token comment">/******************** Keep Alive start*************************/</span>
                  buffer<span class="token punctuation">[</span>length<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>MQTT_KEEPALIVE<span class="token punctuation">)</span> <span class="token operator">&gt;&gt;</span> <span class="token number">8</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                  buffer<span class="token punctuation">[</span>length<span class="token operator">++</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>MQTT_KEEPALIVE<span class="token punctuation">)</span> <span class="token operator">&amp;</span> <span class="token number">0xFF</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                 <span class="token comment">/******************** Keep Alive end*************************/</span>
          
                 <span class="token comment">//The payload of the payload CONNECT message contains one or more fields prefixed with length, and the flag in the variable header determines whether to include these fields</ span>
                 <span class="token comment">//If it is included, it must appear in this order: client identifier, will subject, will message, user name and password</ span>
          
                 <span class="token comment">/***********  client Identifier start************/</span>
                  <span class="token function">CHECK_STRING_LENGTH</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span>id<span class="token punctuation">)</span>
                  length <span class="token operator">=</span> <span class="token function">writeString</span><span class="token punctuation">(</span>id<span class="token punctuation">,</span>buffer<span class="token punctuation">,</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
                 <span class="token comment">/***********  client Identifier end************/</span>
          
                 <span class="token comment">/********* Testamentary subject testamentary message start********/</span>
                  <span class="token keyword">if</span> <span class="token punctuation">(</span>willTopic<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      <span class="token function">CHECK_STRING_LENGTH</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span>willTopic<span class="token punctuation">)</span>
                      length <span class="token operator">=</span> <span class="token function">writeString</span><span class="token punctuation">(</span>willTopic<span class="token punctuation">,</span>buffer<span class="token punctuation">,</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
                      <span class="token function">CHECK_STRING_LENGTH</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span>willMessage<span class="token punctuation">)</span>
                      length <span class="token operator">=</span> <span class="token function">writeString</span><span class="token punctuation">(</span>willMessage<span class="token punctuation">,</span>buffer<span class="token punctuation">,</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
                  <span class="token punctuation">}</span>
                 <span class="token comment">/********* Wills subject wills message end********/</span>
          
                  <span class="token comment">/********* User name password start********/</span>
                  <span class="token keyword">if</span><span class="token punctuation">(</span>user <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      <span class="token function">CHECK_STRING_LENGTH</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span>user<span class="token punctuation">)</span>
                      length <span class="token operator">=</span> <span class="token function">writeString</span><span class="token punctuation">(</span>user<span class="token punctuation">,</span>buffer<span class="token punctuation">,</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
                      <span class="token keyword">if</span><span class="token punctuation">(</span>pass <span class="token operator">!=</span> <span class="token constant">NULL</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                          <span class="token function">CHECK_STRING_LENGTH</span><span class="token punctuation">(</span>length<span class="token punctuation">,</span>pass<span class="token punctuation">)</span>
                          length <span class="token operator">=</span> <span class="token function">writeString</span><span class="token punctuation">(</span>pass<span class="token punctuation">,</span>buffer<span class="token punctuation">,</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>
                      <span class="token punctuation">}</span>
                  <span class="token punctuation">}</span>
                  <span class="token comment">/********* User name and password end********/</span>
          
                  <span class="token comment">//Assemble CONNECT message</span>
                  <span class="token function">write</span><span class="token punctuation">(</span>MQTTCONNECT<span class="token punctuation">,</span>buffer<span class="token punctuation">,</span>length<span class="token operator">-</span>MQTT_MAX_HEADER_SIZE<span class="token punctuation">)</span><span class="token punctuation">;</span>
          
                  lastInActivity <span class="token operator">=</span> lastOutActivity <span class="token operator">=</span> <span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
          
                  <span class="token comment">//Wait for the MQTT server to return the response content</span>
                  <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token operator">!</span>_client<span class="token operator">-&gt;</span><span class="token function">available</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      <span class="token keyword">unsigned</span> <span class="token keyword">long</span> t <span class="token operator">=</span> <span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                      <span class="token comment">//Determine whether the timeout occurs</span>
                      <span class="token keyword">if</span> <span class="token punctuation">(</span>t<span class="token operator">-</span>lastInActivity <span class="token operator">&gt;=</span> <span class="token punctuation">(</span><span class="token punctuation">(</span>int32_t<span class="token punctuation">)</span> MQTT_SOCKET_TIMEOUT<span class="token operator">*</span><span class="token number">1000UL</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                          _state <span class="token operator">=</span> MQTT_CONNECTION_TIMEOUT<span class="token punctuation">;</span>
                          _client<span class="token operator">-&gt;</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                          <span class="token keyword">return</span> false<span class="token punctuation">;</span>
                      <span class="token punctuation">}</span>
                  <span class="token punctuation">}</span>
                  uint8_t llen<span class="token punctuation">;</span>
                  <span class="token comment">//Read the contents returned by the response</span>
                  uint16_t len <span class="token operator">=</span> <span class="token function">readPacket</span><span class="token punctuation">(</span><span class="token operator">&amp;</span>llen<span class="token punctuation">)</span><span class="token punctuation">;</span>
          
                  <span class="token comment">/*** Processing CONNACK - confirm connection request message***/</span>
                  <span class="token keyword">if</span> <span class="token punctuation">(</span>len <span class="token operator">==</span> <span class="token number">4</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      <span class="token keyword">if</span> <span class="token punctuation">(</span>buffer<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                          lastInActivity <span class="token operator">=</span> <span class="token function">millis</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                          pingOutstanding <span class="token operator">=</span> false<span class="token punctuation">;</span>
                          _state <span class="token operator">=</span> MQTT_CONNECTED<span class="token punctuation">;</span>
                          <span class="token keyword">return</span> true<span class="token punctuation">;</span>
                      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                          _state <span class="token operator">=</span> buffer<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
                      <span class="token punctuation">}</span>
                  <span class="token punctuation">}</span>
                  _client<span class="token operator">-&gt;</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
              <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                  _state <span class="token operator">=</span> MQTT_CONNECT_FAILED<span class="token punctuation">;</span>
              <span class="token punctuation">}</span>
              <span class="token keyword">return</span> false<span class="token punctuation">;</span>
          <span class="token punctuation">}</span>
          <span class="token keyword">return</span> true<span class="token punctuation">;</span>
          

          }

            be careful:

            • MQTT_KEEPALIVE defaults to 15 S;
            • MQTT_SOCKET_TIMEOUT is 15 S by default;

            3.7 disconnect -- DISCONNECT (DISCONNECT message)

            Function Description:

            /**
             * Disconnect
             * The client disconnects (the last control message sent by the client to the server. It indicates that the client disconnects normally)
             * @Note Format of unsubscribed message: fixed header (message type + remaining length)
             */
            void PubSubClient::disconnect() {
                /*** Disconnect message protocol***/
                buffer[0] = MQTTDISCONNECT;
                buffer[1] = 0;
                _client->write(buffer,2);
                _state = MQTT_DISCONNECTED;
                _client->flush();
                _client->stop();
                lastInActivity = lastOutActivity = millis();
            }
            
             

              3.8 subscribe - subscription subject (SUBSCRIBE message)

              Function Description:

              /**
               * Subscribe to topics
               * @param topic theme
               * @return bool Is the subscription successful
               */
              boolean PubSubClient::subscribe(const char* topic) {
                  return subscribe(topic, 0);
              }
              

              /**

              • Subscription topic (the client sends a SUBSCRIBE message to the server to create one or more subscriptions)
              • @param topic topic
              • @param qos quality level
              • @return bool whether the subscription was successful
              • @Note subscription message format: fixed header + variable header (message identifier) + payload (subject filter)
              •   Format of subscription confirmation message: fixed header variable header (message identifier)+ Payload (return code list)
                

              /
              boolean PubSubClient::subscribe(const char topic, uint8_t qos) {
              if (qos > 1) {
              return false;
              }
              if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
              // Too long
              return false;
              }
              if (connected()) {
              // Leave room in the buffer for header and variable length field
              uint16_t length = MQTT_MAX_HEADER_SIZE;
              nextMsgId++;
              if (nextMsgId == 0) {
              nextMsgId = 1;
              }
              buffer[length++] = (nextMsgId >> 8);
              buffer[length++] = (nextMsgId & 0xFF);
              length = writeString((char*)topic, buffer,length);
              buffer[length++] = qos;
              return write(MQTTSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
              }
              return false;
              }

                3.9 unsubscribe - unsubscribe topic

                Function Description:

                /**
                 * UNSUBSCRIBE the topic (the client sends UNSUBSCRIBE message to the server to UNSUBSCRIBE the topic)
                 * @param topic Specific theme
                 * @return bool Cancel successfully
                 * @Note Format of unsubscribed message: fixed header (message type + remaining length) + variable header (message identifier) + payload (subject filter list)
                 */
                boolean PubSubClient::unsubscribe(const char* topic) {
                    if (MQTT_MAX_PACKET_SIZE < 9 + strlen(topic)) {
                        // Too long
                        return false;
                    }
                    if (connected()) {
                        uint16_t length = MQTT_MAX_HEADER_SIZE;
                        nextMsgId++;
                        if (nextMsgId == 0) {
                            nextMsgId = 1;
                        }
                        //Variable header (message identifier)
                        buffer[length++] = (nextMsgId >> 8);
                        buffer[length++] = (nextMsgId & 0xFF);
                        length = writeString(topic, buffer,length);
                        return write(MQTTUNSUBSCRIBE|MQTTQOS1,buffer,length-MQTT_MAX_HEADER_SIZE);
                    }
                    return false;
                }
                
                 

                  3.10 publish/publish_P - release message

                  Function Description:

                  /**
                   * Publish corresponding topic message
                   * @param topic theme
                   * @param payload Payload
                   */
                  boolean PubSubClient::publish(const char* topic, const char* payload) {
                      return publish(topic,(const uint8_t*)payload,strlen(payload),false);
                  }
                  

                  /**

                  • Publish corresponding topic message
                  • @param topic topic
                  • @param payload
                  • @param retained
                    /
                    boolean PubSubClient::publish(const char topic, const char payload, boolean retained) {
                    return publish(topic,(const uint8_t)payload,strlen(payload),retained);
                    }

                  /**

                  • Publish corresponding topic message
                  • @param topic topic
                  • @param payload
                  • @param plength payload content length
                    /
                    boolean PubSubClient::publish(const char topic, const uint8_t* payload, unsigned int plength) {
                    return publish(topic, payload, plength, false);
                    }

                  /**

                  • Publish corresponding topic message
                  • @param topic topic
                  • @param payload
                  • @param plength payload content length
                  • @param retained
                    /
                    boolean PubSubClient::publish(const char topic, const uint8_t* payload, unsigned int plength, boolean retained) {
                    if (connected()) {
                    if (MQTT_MAX_PACKET_SIZE < MQTT_MAX_HEADER_SIZE + 2+strlen(topic) + plength) {
                    // Too long
                    return false;
                    }
                    // Leave room in the buffer for header and variable length field
                    uint16_t length = MQTT_MAX_HEADER_SIZE;
                    length = writeString(topic,buffer,length);
                    uint16_t i;
                    for (i=0;i<plength;i++) {
                    buffer[length++] = payload[i];
                    }
                    uint8_t header = MQTTPUBLISH;
                    if (retained) {
                    header |= 1;
                    }
                    return write(header,buffer,length-MQTT_MAX_HEADER_SIZE);
                    }
                    return false;
                    }

                  /**

                  • Publish corresponding topic message
                  • @param topic topic
                  • @param payload (F(xxx))
                  • @param retained
                    /
                    boolean PubSubClient::publish_P(const char topic, const char payload, boolean retained) {
                    return publish_P(topic, (const uint8_t)payload, strlen(payload), retained);
                    }

                  /**

                  • Publish corresponding topic message

                  • @param topic topic

                  • @param payload (F(xxx))

                  • @param plength payload content length

                  • @param retained
                    /
                    boolean PubSubClient::publish_P(const char topic, const uint8_t* payload, unsigned int plength, boolean retained) {
                    uint8_t llen = 0;
                    uint8_t digit;
                    unsigned int rc = 0;
                    uint16_t tlen;
                    unsigned int pos = 0;
                    unsigned int i;
                    uint8_t header;
                    unsigned int len;

                    if (!connected()) {
                    return false;
                    }

                    tlen = strlen(topic);

                    header = MQTTPUBLISH;
                    if (retained) {
                    header |= 1;
                    }
                    buffer[pos++] = header;
                    len = plength + 2 + tlen;
                    do {
                    digit = len % 128;
                    len = len / 128;
                    if (len > 0) {
                    digit |= 0x80;
                    }
                    buffer[pos++] = digit;
                    llen++;
                    } while(len>0);

                    pos = writeString(topic,buffer,pos);

                    rc += _client->write(buffer,pos);

                    for (i=0;i<plength;i++) {
                    rc += _client->write((char)pgm_read_byte_near(payload + i));
                    }

                    lastOutActivity = millis();

                    return rc == tlen + 4 + plength;
                    }

                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11
                  • 12
                  • 13
                  • 14
                  • 15
                  • 16
                  • 17
                  • 18
                  • 19
                  • 20
                  • 21
                  • 22
                  • 23
                  • 24
                  • 25
                  • 26
                  • 27
                  • 28
                  • 29
                  • 30
                  • 31
                  • 32
                  • 33
                  • 34
                  • 35
                  • 36
                  • 37
                  • 38
                  • 39
                  • 40
                  • 41
                  • 42
                  • 43
                  • 44
                  • 45
                  • 46
                  • 47
                  • 48
                  • 49
                  • 50
                  • 51
                  • 52
                  • 53
                  • 54
                  • 55
                  • 56
                  • 57
                  • 58
                  • 59
                  • 60
                  • 61
                  • 62
                  • 63
                  • 64
                  • 65
                  • 66
                  • 67
                  • 68
                  • 69
                  • 70
                  • 71
                  • 72
                  • 73
                  • 74
                  • 75
                  • 76
                  • 77
                  • 78
                  • 79
                  • 80
                  • 81
                  • 82
                  • 83
                  • 84
                  • 85
                  • 86
                  • 87
                  • 88
                  • 89
                  • 90
                  • 91
                  • 92
                  • 93
                  • 94
                  • 95
                  • 96
                  • 97
                  • 98
                  • 99
                  • 100
                  • 101
                  • 102
                  • 103
                  • 104
                  • 105
                  • 106
                  • 107
                  • 108
                  • 109
                  • 110
                  • 111
                  • 112
                  • 113
                  • 114
                  • 115
                  • 116
                  • 117
                  • 118
                  • 119

                  3.11 setCallback -- processing message callback

                  Function Description:

                  /**
                   * Set message callback function
                   * @param MQTT_CALLBACK_SIGNATURE 
                   */
                  PubSubClient& PubSubClient::setCallback(MQTT_CALLBACK_SIGNATURE) {
                      this->callback = callback;
                      return *this;
                  }
                  
                   
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8

                  be careful:

                  • MQTT_CALLBACK_SIGNATURE is a function definition
                  #if defined(ESP8266) || defined(ESP32)
                  #include <functional>
                  #define MQTT_CALLBACK_SIGNATURE std::function<void(char*, uint8_t*, unsigned int)> callback
                  #else
                  #define MQTT_CALLBACK_SIGNATURE void (*callback)(char*, uint8_t*, unsigned int)
                  #endif
                  
                   
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6

                  3.12 loop - process messages and keep heartbeat

                  Function Description:

                  /**
                   * Process messages and keep heartbeat
                   */
                  boolean PubSubClient::loop() {
                      if (connected()) {
                          unsigned long t = millis();
                          if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) {
                              if (pingOutstanding) {
                                  this->_state = MQTT_CONNECTION_TIMEOUT;
                                  _client->stop();
                                  return false;
                              } else {
                                  /*** PINGREQ-Heartbeat request****/
                                  buffer[0] = MQTTPINGREQ;
                                  buffer[1] = 0;
                                  _client->write(buffer,2);
                                  lastOutActivity = t;
                                  lastInActivity = t;
                                  pingOutstanding = true;
                              }
                          }
                          if (_client->available()) {
                              uint8_t llen;
                              uint16_t len = readPacket(&llen);
                              uint16_t msgId = 0;
                              uint8_t *payload;
                              if (len > 0) {
                                  lastInActivity = t;
                                  uint8_t type = buffer[0]&0xF0;
                                  if (type == MQTTPUBLISH) {
                                   //Server release message
                                      if (callback) {
                                          uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */
                                          memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */
                                          buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */
                                          char *topic = (char*) buffer+llen+2;
                                          // msgId only present for QOS>0
                                          if ((buffer[0]&0x06) == MQTTQOS1) {
                                              msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1];
                                              payload = buffer+llen+3+tl+2;
                                              callback(topic,payload,len-llen-3-tl-2);
                                              //Client publish reply
                                              buffer[0] = MQTTPUBACK;
                                              buffer[1] = 2;
                                              buffer[2] = (msgId >> 8);
                                              buffer[3] = (msgId & 0xFF);
                                              _client->write(buffer,4);
                                              lastOutActivity = t;
                  
                                      <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                                          payload <span class="token operator">=</span> buffer<span class="token operator">+</span>llen<span class="token operator">+</span><span class="token number">3</span><span class="token operator">+</span>tl<span class="token punctuation">;</span>
                                          <span class="token function">callback</span><span class="token punctuation">(</span>topic<span class="token punctuation">,</span>payload<span class="token punctuation">,</span>len<span class="token operator">-</span>llen<span class="token operator">-</span><span class="token number">3</span><span class="token operator">-</span>tl<span class="token punctuation">)</span><span class="token punctuation">;</span>
                                      <span class="token punctuation">}</span>
                                  <span class="token punctuation">}</span>
                              <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">==</span> MQTTPINGREQ<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                                  <span class="token comment">/**** PINGRESP-Heartbeat response****/</span>
                                  buffer<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span> <span class="token operator">=</span> MQTTPINGRESP<span class="token punctuation">;</span>
                                  buffer<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
                                  _client<span class="token operator">-&gt;</span><span class="token function">write</span><span class="token punctuation">(</span>buffer<span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                              <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span>type <span class="token operator">==</span> MQTTPINGRESP<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                                  <span class="token comment">/**** PINGRESP-Heartbeat response****/</span>
                                  pingOutstanding <span class="token operator">=</span> false<span class="token punctuation">;</span>
                              <span class="token punctuation">}</span>
                          <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token function">connected</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                              <span class="token comment">// readPacket has closed the connection</span>
                              <span class="token keyword">return</span> false<span class="token punctuation">;</span>
                          <span class="token punctuation">}</span>
                      <span class="token punctuation">}</span>
                      <span class="token keyword">return</span> true<span class="token punctuation">;</span>
                  <span class="token punctuation">}</span>
                  <span class="token keyword">return</span> false<span class="token punctuation">;</span>
                  

                  }

                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11
                  • 12
                  • 13
                  • 14
                  • 15
                  • 16
                  • 17
                  • 18
                  • 19
                  • 20
                  • 21
                  • 22
                  • 23
                  • 24
                  • 25
                  • 26
                  • 27
                  • 28
                  • 29
                  • 30
                  • 31
                  • 32
                  • 33
                  • 34
                  • 35
                  • 36
                  • 37
                  • 38
                  • 39
                  • 40
                  • 41
                  • 42
                  • 43
                  • 44
                  • 45
                  • 46
                  • 47
                  • 48
                  • 49
                  • 50
                  • 51
                  • 52
                  • 53
                  • 54
                  • 55
                  • 56
                  • 57
                  • 58
                  • 59
                  • 60
                  • 61
                  • 62
                  • 63
                  • 64
                  • 65
                  • 66
                  • 67
                  • 68
                  • 69
                  • 70
                  • 71
                  • 72
                  • 73

                  3.13 beginPublish - publish big data (step 1)

                  The above methods of publishing news are small data publishing. What is small data? Just look at the buffer size:

                  // MQTT_MAX_PACKET_SIZE : Maximum packet size
                  #ifndef MQTT_MAX_PACKET_SIZE
                  #define MQTT_MAX_PACKET_SIZE 128
                  #endif
                  
                   
                  • 1
                  • 2
                  • 3
                  • 4

                  The default buffer is 128 bytes. Of course, bloggers do not recommend sending a large amount of data.
                  If you want to publish slightly larger data, you have to use the trilogy method.

                  Function Description:

                  /**
                   * Publish big data (step 1) - just fixed header + remaining length 
                   * @param topic theme
                   * @param plength Load content length
                   * @param retained Keep
                   *
                   * @Note buffer[128] is still used here
                   */
                  boolean PubSubClient::beginPublish(const char* topic, unsigned int plength, boolean retained) {
                      if (connected()) {
                          // Send the header and variable length field
                          uint16_t length = MQTT_MAX_HEADER_SIZE;
                          length = writeString(topic,buffer,length);
                          uint8_t header = MQTTPUBLISH;
                          if (retained) {
                              header |= 1;
                          }
                          size_t hlen = buildHeader(header, buffer, plength+length-MQTT_MAX_HEADER_SIZE);
                          uint16_t rc = _client->write(buffer+(MQTT_MAX_HEADER_SIZE-hlen),length-(MQTT_MAX_HEADER_SIZE-hlen));
                          lastOutActivity = millis();
                          return (rc == (length-(MQTT_MAX_HEADER_SIZE-hlen)));
                      }
                      return false;
                  }
                  
                   
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11
                  • 12
                  • 13
                  • 14
                  • 15
                  • 16
                  • 17
                  • 18
                  • 19
                  • 20
                  • 21
                  • 22
                  • 23
                  • 24

                  3.14 write - release big data (step 2)

                  Function Description:

                  /**
                   * Publishing big data (step 2) - payload
                   * @param buffer content
                   * @param size Load content length
                   *
                   * @Note buffer[128] is still used here
                   */
                  size_t PubSubClient::write(const uint8_t *buffer, size_t size) {
                      lastOutActivity = millis();
                      return _client->write(buffer,size);
                  }
                  
                   
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11

                  3.15 endPublish - publish big data (step 3)

                  Function Description:

                  /**
                   * Publishing big data (step 3) feels useless
                   */
                  int PubSubClient::endPublish() {
                   return 1;
                  }
                  
                   
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6

                  3.16 state -- get the current state of Mqtt client

                  Function Description:

                  //State definition
                  // Possible values for client.state()
                  #define MQTT_CONNECTION_TIMEOUT     -4
                  #define MQTT_CONNECTION_LOST        -3
                  #define MQTT_CONNECT_FAILED         -2
                  #define MQTT_DISCONNECTED           -1
                  #define MQTT_CONNECTED               0
                  #define MQTT_CONNECT_BAD_PROTOCOL    1
                  #define MQTT_CONNECT_BAD_CLIENT_ID   2
                  #define MQTT_CONNECT_UNAVAILABLE     3
                  #define MQTT_CONNECT_BAD_CREDENTIALS 4
                  #define MQTT_CONNECT_UNAUTHORIZED    5
                  

                  /**

                  • Get the current status of Mqtt client
                    */
                    int PubSubClient::state() {
                    return this->_state;
                    }
                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11
                  • 12
                  • 13
                  • 14
                  • 15
                  • 16
                  • 17
                  • 18
                  • 19

                  4. Test cases

                  After talking about the tools, let's directly look at the examples provided by the library (bloggers will use MQTT in combination with OneNet later. Please look forward to it).

                  4.1 mqtt-8266 cases

                  Case description:

                  • Connect to the previous MQTT server and publish a "hello world" message to the topic "outTopic" every 2 seconds
                  • The client monitors the topic "inTopic" and judges the load content to control the light on and off

                  Case code:

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

                  // Update these with values suitable for your network.

                  const char ssid = “…”;// wifi account
                  const char password = “…”;// wifi secret
                  const char* mqtt_server = “broker.mqtt-dashboard.com”;// Mqtt server

                  WiFiClient espClient;
                  PubSubClient client(espClient);
                  long lastMsg = 0;
                  char msg[50];
                  int value = 0;

                  void setup_wifi() {

                  delay(10);
                  // We start by connecting to a WiFi network
                  Serial.println();
                  Serial.print("Connecting to ");
                  Serial.println(ssid);

                  WiFi.begin(ssid, password);

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

                  randomSeed(micros());

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

                  /**

                  • Message callback
                    /
                    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[i]);
                    }
                    Serial.println();

                  // Switch on the LED if an 1 was received as first character
                  if ((char)payload[0] == '1') {
                  digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level
                  // but actually the LED is on; this is because
                  // it is active low on the ESP-01)
                  } else {
                  digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH
                  }

                  }

                  /**

                  • Disconnect and reconnect
                    */
                    void reconnect() {
                    // Loop until we're reconnected
                    while (!client.connected()) {
                    Serial.print("Attempting MQTT connection...");
                    // Create a random client ID
                    String clientId = "ESP8266Client-";
                    clientId += String(random(0xffff), HEX);
                    // Attempt to connect
                    if (client.connect(clientId.c_str())) {
                    Serial.println("connected");
                    // Once connected, publish an announcement...
                    client.publish("outTopic", "hello world");
                    // ... and resubscribe
                    client.subscribe("inTopic");
                    } else {
                    Serial.print("failed, rc=");
                    Serial.print(client.state());
                    Serial.println(" try again in 5 seconds");
                    // Wait 5 seconds before retrying
                    delay(5000);
                    }
                    }
                    }

                  void setup() {
                  pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
                  Serial.begin(115200);
                  setup_wifi();
                  //Configure mqtt server address and port
                  client.setServer(mqtt_server, 1883);
                  //Set subscription message callback
                  client.setCallback(callback);
                  }

                  void loop() {
                  //Reconnection mechanism
                  if (!client.connected()) {
                  reconnect();
                  }
                  //Constantly listening for information
                  client.loop();

                  long now = millis();
                  if (now - lastMsg > 2000) {
                  //Publish information every 2s
                  lastMsg = now;
                  ++value;
                  snprintf (msg, 50, "hello world #%ld", value);
                  Serial.print("Publish message: ");
                  Serial.println(msg);
                  client.publish("outTopic", msg);
                  }
                  }

                  • 1
                  • 2
                  • 3
                  • 4
                  • 5
                  • 6
                  • 7
                  • 8
                  • 9
                  • 10
                  • 11
                  • 12
                  • 13
                  • 14
                  • 15
                  • 16
                  • 17
                  • 18
                  • 19
                  • 20
                  • 21
                  • 22
                  • 23
                  • 24
                  • 25
                  • 26
                  • 27
                  • 28
                  • 29
                  • 30
                  • 31
                  • 32
                  • 33
                  • 34
                  • 35
                  • 36
                  • 37
                  • 38
                  • 39
                  • 40
                  • 41
                  • 42
                  • 43
                  • 44
                  • 45
                  • 46
                  • 47
                  • 48
                  • 49
                  • 50
                  • 51
                  • 52
                  • 53
                  • 54
                  • 55
                  • 56
                  • 57
                  • 58
                  • 59
                  • 60
                  • 61
                  • 62
                  • 63
                  • 64
                  • 65
                  • 66
                  • 67
                  • 68
                  • 69
                  • 70
                  • 71
                  • 72
                  • 73
                  • 74
                  • 75
                  • 76
                  • 77
                  • 78
                  • 79
                  • 80
                  • 81
                  • 82
                  • 83
                  • 84
                  • 85
                  • 86
                  • 87
                  • 88
                  • 89
                  • 90
                  • 91
                  • 92
                  • 93
                  • 94
                  • 95
                  • 96
                  • 97
                  • 98
                  • 99
                  • 100
                  • 101
                  • 102
                  • 103
                  • 104
                  • 105
                  • 106
                  • 107
                  • 108
                  • 109
                  • 110
                  • 111
                  • 112
                  • 113
                  • 114
                  • 115
                  • 116
                  • 117

                  4.2 mqtt auth cases

                  Case description:

                  • To connect to an MQTT server, you need an account and password

                  Case code:

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

                  const char ssid = "...";
                  const char password = "...";
                  const char* mqtt_server = "broker.mqtt-dashboard.com";

                  WiFiClient espClient;

                  void callback(char topic, byte payload, unsigned int length) {
                  // handle message arrived
                  }

                  PubSubClient client(mqtt_server, 1883, callback, espClient);

                  void setup_wifi() {
                  delay(10);
                  // We start by connecting to a WiFi network
                  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 setup()
                  {

                  setup_wifi();

                  // Note - the default maximum packet size is 128 bytes. If the
                  // combined length of clientId, username and password exceed this,
                  // you will need to increase the value of MQTT_MAX_PACKET_SIZE in
                  // PubSubClient.h

                  if (client.connect("arduinoClient", "testuser", "testpass")) {
                  client.publish("outTopic","hello world");
                  client.subscribe("inTopic");
                  }
                  }

                  void loop()
                  {
                  client.loop();
                  }

                    4.3 mqtt larget message case

                    Case description:

                    • Connect to the previous MQTT server and publish big data

                    Case code:

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

                    // Update these with values suitable for your network.

                    const char ssid = "...";
                    const char password = "...";
                    const char* mqtt_server = "broker.mqtt-dashboard.com";

                    WiFiClient espClient;
                    PubSubClient client(espClient);

                    void setup_wifi() {

                    delay(10);
                    // We start by connecting to a WiFi network
                    Serial.println();
                    Serial.print("Connecting to ");
                    Serial.println(ssid);

                    WiFi.begin(ssid, password);

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

                    randomSeed(micros());

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

                    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[i]);
                    }
                    Serial.println();

                    // Find out how many bottles we should generate lyrics for
                    String topicStr(topic);
                    int bottleCount = 0; // assume no bottles unless we correctly parse a value from the topic
                    if (topicStr.indexOf('/') >= 0) {
                    // The topic includes a '/', we'll try to read the number of bottles from just after that
                    topicStr.remove(0, topicStr.indexOf('/')+1);
                    // Now see if there's a number of bottles after the '/'
                    bottleCount = topicStr.toInt();
                    }

                    if (bottleCount > 0) {
                    // Work out how big our resulting message will be
                    int msgLen = 0;
                    for (int i = bottleCount; i > 0; i–) {
                    String numBottles(i);
                    msgLen += 2numBottles.length();
                    if (i == 1) {
                    msgLen += 2String(" green bottle, standing on the wall\n").length();
                    } else {
                    msgLen += 2*String(" green bottles, standing on the wall\n").length();
                    }
                    msgLen += String("And if one green bottle should accidentally fall\nThere'll be ").length();
                    switch (i) {
                    case 1:
                    msgLen += String("no green bottles, standing on the wall\n\n").length();
                    break;
                    case 2:
                    msgLen += String("1 green bottle, standing on the wall\n\n").length();
                    break;
                    default:
                    numBottles = i-1;
                    msgLen += numBottles.length();
                    msgLen += String(" green bottles, standing on the wall\n\n").length();
                    break;
                    };
                    }

                    <span class="token comment">// Display start publishing big data</span>
                    client<span class="token punctuation">.</span><span class="token function">beginPublish</span><span class="token punctuation">(</span><span class="token string">"greenBottles/lyrics"</span><span class="token punctuation">,</span> msgLen<span class="token punctuation">,</span> false<span class="token punctuation">)</span><span class="token punctuation">;</span>
                    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> i <span class="token operator">=</span> bottleCount<span class="token punctuation">;</span> i <span class="token operator">&gt;</span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">--</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">int</span> j <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> j <span class="token operator">&lt;</span> <span class="token number">2</span><span class="token punctuation">;</span> j<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                        client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>i<span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token keyword">if</span> <span class="token punctuation">(</span>i <span class="token operator">==</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                          client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">" green bottle, standing on the wall\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{<!-- --></span>
                          client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">" green bottles, standing on the wall\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token punctuation">}</span>
                      <span class="token punctuation">}</span>
                      client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"And if one green bottle should accidentally fall\nThere'll be "</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                      <span class="token keyword">switch</span> <span class="token punctuation">(</span>i<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
                      <span class="token keyword">case</span> <span class="token number">1</span><span class="token punctuation">:</span>
                        client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"no green bottles, standing on the wall\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token keyword">break</span><span class="token punctuation">;</span>
                      <span class="token keyword">case</span> <span class="token number">2</span><span class="token punctuation">:</span>
                        client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">"1 green bottle, standing on the wall\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token keyword">break</span><span class="token punctuation">;</span>
                      <span class="token keyword">default</span><span class="token punctuation">:</span>
                        client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span>i<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        client<span class="token punctuation">.</span><span class="token function">print</span><span class="token punctuation">(</span><span class="token string">" green bottles, standing on the wall\n\n"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                        <span class="token keyword">break</span><span class="token punctuation">;</span>
                      <span class="token punctuation">}</span><span class="token punctuation">;</span>
                    <span class="token punctuation">}</span>
                    <span class="token comment">// Release complete</span>
                    client<span class="token punctuation">.</span><span class="token function">endPublish</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
                    

                    }
                    }

                    /**

                    • Reconnection mechanism
                      */
                      void reconnect() {
                      // Loop until we're reconnected
                      while (!client.connected()) {
                      Serial.print("Attempting MQTT connection...");
                      // Create a random client ID
                      String clientId = "ESP8266Client-";
                      clientId += String(random(0xffff), HEX);
                      // Attempt to connect
                      if (client.connect(clientId.c_str())) {
                      Serial.println("connected");
                      // Once connected, publish an announcement...
                      client.publish("outTopic", "hello world");
                      // ... and resubscribe
                      client.subscribe("greenBottles/#");
                      } else {
                      Serial.print("failed, rc=");
                      Serial.print(client.state());
                      Serial.println(" try again in 5 seconds");
                      // Wait 5 seconds before retrying
                      delay(5000);
                      }
                      }
                      }

                    void setup() {
                    pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output
                    Serial.begin(115200);
                    setup_wifi();
                    client.setServer(mqtt_server, 1883);
                    client.setCallback(callback);
                    }

                    void loop() {

                    if (!client.connected()) {
                    reconnect();
                    }
                    client.loop();
                    }