mqtt/mqtt.h
A.M. Rowsell 627df20e53
Squashed commit of the following:
commit a4632bb7ad
Author: A.M. Rowsell <amrowsell@frozenelectronics.ca>
Date:   Mon Jan 21 20:13:12 2019 -0500

    Sanitizing key and wifi

    Signed-off-by: A.M. Rowsell <amrowsell@frozenelectronics.ca>

commit 5e3be0f561
Author: A.M. Rowsell <amrowsell@frozenelectronics.ca>
Date:   Mon Jan 21 19:53:42 2019 -0500

    It's alive! New code all working.

    The OneWire library works. It's a bit hacked together, as neither
    the software timer or hardware timer APIs would have worked well,
    because they are implemented terribly by Espressif. The easiest
    way to get around this was to just use system_get_time() and work
    off of that for timing in one-wire comms.

    Split the publish function into two separate functions: one to
    publish floating point numbers, and one to publish integers. In
    a language like Lua or C++ you could have these as one function,
    but in C it's easier to just split them.

    The main.c has a new function called dataLog that deals with
    getting the DS18B20 data and then handing that off to pubfloat().

    I updated the timer names to be more descriptive.

    I grabbed some code to convert integers and floats to strings, as
    I can't be bothered to write that code myself for the millionth
    time.

    If something goes wrong and we are disconnected from our TCP
    connection, all timers are halted so we don't blindly keep
    trying to send packets over a non-existent link.

    Unfortunately the onewire library is hardcoded to use pin 5.
    That will be the next update.

    Signed-off-by: A.M. Rowsell <amrowsell@frozenelectronics.ca>

commit 48702bf328
Author: A.M. Rowsell <amrowsell@frozenelectronics.ca>
Date:   Sun Jan 20 21:13:04 2019 -0500

    First version that compiles with new file layout.

    Had to make many changes to get it to compile across many files,
    including removing the LOCAL specifier from almost all functions.
    Edited the Makefile to compile all three files and link them.
    Haven't tested on hardware yet, that's the next step.

    Lots of small changes to avoid warnings, now that I have turned
    -Wall on. This makes the code a bit "better".

    Signed-off-by: A.M. Rowsell <amrowsell@frozenelectronics.ca>

commit 1cd8191682
Author: A.M. Rowsell <amrowsell@frozenelectronics.ca>
Date:   Sat Jan 19 15:25:44 2019 -0500

    New branch for my new AIO key.

    Will have to remember to sanitize before committing to master.

    Signed-off-by: A.M. Rowsell <amrowsell@frozenelectronics.ca>

Signed-off-by: A.M. Rowsell <amrowsell@frozenelectronics.ca>
2019-01-21 20:14:09 -05:00

141 lines
6.8 KiB
C

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/********************************************************************************/
/* Some portions of this file were taken from the NodeMCU firmware project, */
/* at https://github.com/nodemcu/nodemcu-firmware. The original author is */
/* listed as "zeroday nodemcu.com". The code was licensed under the MIT */
/* license, which allows me to relicense it under the MPL, which I have done. */
/********************************************************************************/
/**
* @file
* @brief This is the main header file for all MQTT/TCP related functions.
*/
#include "user_interface.h"
#include "ets_sys.h"
#include "osapi.h"
#include "espconn.h"
#include "os_type.h"
#define DEBUG 1 /**< This define enables or disables serial debug output in most places */
/**
* @typedef
* This is the enum for message types.
*
* This enum was taken from the NodeMCU mqtt headers. Credit is given to "zeroday" of nodemcu.com. This enum gives us both easily readable names for each message type, but also the correct value for each type. These are used in mqtt_send() to construct the correct packet type.
*/
typedef enum mqtt_message_enum
{
MQTT_MSG_TYPE_CONNECT = 1,
MQTT_MSG_TYPE_CONNACK = 2,
MQTT_MSG_TYPE_PUBLISH = 3,
MQTT_MSG_TYPE_PUBACK = 4,
MQTT_MSG_TYPE_PUBREC = 5,
MQTT_MSG_TYPE_PUBREL = 6,
MQTT_MSG_TYPE_PUBCOMP = 7,
MQTT_MSG_TYPE_SUBSCRIBE = 8,
MQTT_MSG_TYPE_SUBACK = 9,
MQTT_MSG_TYPE_UNSUBSCRIBE = 10,
MQTT_MSG_TYPE_UNSUBACK = 11,
MQTT_MSG_TYPE_PINGREQ = 12,
MQTT_MSG_TYPE_PINGRESP = 13,
MQTT_MSG_TYPE_DISCONNECT = 14
} mqtt_message_type;
/**
* @struct mqtt_packet_t
* A structure which contains all the information for an MQTT packet.
*
* This structure contains pointers to the three main parts of an MQTT packet: the fixed header, the variable header, and the payload. Not all message types contain a variable header or payload, but *all* message types have a fixed header.
*/
typedef struct {
uint8_t *fixedHeader; /**< The pointer to the fixed header bytes */
uint32_t fixedHeader_len; /**< The length of the fixed header */
uint8_t *varHeader; /**< The pointer to the variable header bytes */
uint32_t varHeader_len; /**< The length of the variable header */
uint8_t *payload; /**< The pointer to the payload bytes */
uint32_t payload_len; /**< The length of the payload */
uint32_t length; /**< The full length of the packet */
mqtt_message_type msgType; /**< What message type this packet contains */
} mqtt_packet_t;
/**
* @struct mqtt_session_t
* Structure that contains all the information to establish and maintain a TCP-based MQTT connection to the broker
*/
typedef struct {
uint8_t ip[4]; /**< An array containing the four bytes of the IP address of the broker */
uint32_t port; /**< The port the broker is listening on */
uint32_t localPort; /**< The local port returned by the ESP8266 function espconn_port() */
uint8_t *client_id; /**< Pointer to the client ID string */
uint32_t client_id_len; /**< Length of the client ID string */
uint8_t *topic_name; /**< Pointer to the topic name string */
uint32_t topic_name_len; /**< Length of the topic name string */
uint8_t qos_level; /**< QOS level of the MQTT connection (always 0, not currently used) */
uint8_t *username; /**< Pointer to the username string, for brokers which require authentication */
uint32_t username_len; /**< The length of the username string */
uint8_t *password; /**< Pointer to the password string, for brokers which require password authentication */
uint32_t password_len; /**< The length of the password string */
char validConnection; /**< Boolean value which indicates whether or not the TCP connection is established, set in tcpConnect() */
struct espconn *activeConnection; /**< A pointer to the espconn structure containing details of the TCP connection */
void *userData; /**< Used to pass data to the PUBLISH function */
// Add pointers to user callback functions
void (*publish_cb)(void *arg); /**< Pointer to user callback function for publish */
void (*connack_cb)(void *arg); /**< Pointer to user callback function for connack */
} mqtt_session_t;
/**
* A function which initiates the connection to the TCP server.
* @param arg A pointer to void, so it can be called from a timer or task
* @return 0 on success
*/
uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg);
void ICACHE_FLASH_ATTR disconnected_callback(void *arg);
void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err);
/**
* A callback function which is called when TCP connection is successful.
* @param *arg A pointer to void, which needs to be cast to espconn *pConn
* @returns Void
*
* This function is called once the TCP connection to the server is completed. This allows us to register the callbacks for received and sent data, as well as enable TCP keepalive and set validConnection in mqtt_session_t to 1 to show the connection has been successful.
*/
void ICACHE_FLASH_ATTR connected_callback(void *arg);
/**
* A callback function that deals with received data.
* @param *arg A pointer to void, which needs to be cast to espconn *pConn
* @param *pdata A pointer to the received data blob
* @param len The length of *pdata
* @return Void
*
* At this point the function does little more than detect what type of MQTT message is sent, and prints out debug info to the serial port. The next few versions should improve this so the user can register their own callback functions which will be called when the particular message type is receieved.
*/
void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len);
void ICACHE_FLASH_ATTR data_sent_callback(void *arg);
void ICACHE_FLASH_ATTR pingAlive(void *arg);
/**
* A function which takes a uint32_t and returns a pointer to a properly formatted MQTT length.
* @param trueLength the length in bytes
* @return encoded multi-byte number per MQTT standards. The first byte this pointer
* returns is the number of bytes to follow.
* The MQTT standard uses a very strange method of encoding the lengths of the various sections
* of the packets. This makes it simpler to implement in code.
*/
uint8_t ICACHE_FLASH_ATTR *encodeLength(uint32_t trueLength);
/**
* This function handles all the sending of various MQTT messages.
* @param session a pointer to the active mqtt_session_t
* @param data a pointer to the data to be published; only applied to MQTT_MSG_TYPE_PUBLISH
* @param len the length of the above data
* @param msgType the type of message to be send, one of the mqtt_message_type
* @return -1 in case of error, 0 otherwise
*/
uint8_t ICACHE_FLASH_ATTR mqtt_send(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType);