mqtt/mqtt.c
A.M. Rowsell cbc182fed4
Started the rewrite of the library on this new branch. See full log.
Created a README, as yet incomplete. Added more files to the gitignore
to get rid of emacs temporary files. Currently making the mqtt_send command
independent of connecting, which is all it can do currently.
2018-08-16 14:26:31 -04:00

225 lines
8.3 KiB
C

#include <stdint.h>
#include "user_interface.h"
#include "ets_sys.h"
#include "osapi.h"
#include "mem.h"
#include "gpio.h"
#include "espconn.h"
#include "os_type.h"
#include "mqtt.h"
/* Functions we will need to implement:
* Send -- will handle all sending of all packets
* Connect -- set up TCP connection and parameters
* Publish -- send message to server
* Subscribe -- we probably won't need this
* We just want to connect, and publish info. We don't care about
* security or QoS in this basic implementation.
*/
static os_timer_t oneTimer;
static os_timer_t testTimer;
LOCAL void ICACHE_FLASH_ATTR data_sent_callback(void *arg) {
os_printf("Data sent!\n");
}
LOCAL void ICACHE_FLASH_ATTR data_recv_callback(void *arg, char *pdata, unsigned short len) {
// deal with received data
os_printf("Received data of length %d -- %s \r\n", len, pdata);
}
LOCAL void ICACHE_FLASH_ATTR connected_callback(void *arg) {
struct espconn *pConn = arg;
os_printf("Connected callback\n");
espconn_regist_recvcb(pConn, (espconn_recv_callback)data_recv_callback);
espconn_regist_sentcb(pConn, (espconn_sent_callback)data_sent_callback);
// enable keepalive
espconn_set_opt(pConn, ESPCONN_KEEPALIVE);
}
LOCAL void ICACHE_FLASH_ATTR reconnected_callback(void *arg, sint8 err) {
os_printf("Reconnected?\n");
os_printf("Error code: %d\n", err);
}
LOCAL void ICACHE_FLASH_ATTR disconnected_callback(void *arg) {
os_printf("Disconnected\n");
}
LOCAL uint8_t ICACHE_FLASH_ATTR tcpConnect(void *arg) {
mqtt_session_t *session = arg;
struct ip_info ipConfig;
LOCAL struct espconn conn;
LOCAL struct _esp_tcp tcp_s;
if (wifi_station_get_connect_status() == STATION_GOT_IP && ipConfig.ip.addr != 0) {
os_printf("Everything looks good!\n");
}
os_printf("Entered tcpConnect\n");
wifi_get_ip_info(STATION_IF, &ipConfig);
// set up basic TCP connection parameters
os_printf("about to set up TCP params\n");
conn.proto.tcp = &tcp_s;
conn.type = ESPCONN_TCP;
conn.proto.tcp->local_port = espconn_port();
conn.proto.tcp->remote_port = session->port;
conn.state = ESPCONN_NONE;
os_memcpy(conn.proto.tcp->remote_ip, session->ip, 4);
os_printf("About to register callbacks\n");
// register callbacks
espconn_regist_connectcb(&conn, (espconn_connect_callback)connected_callback);
espconn_regist_reconcb(&conn, (espconn_reconnect_callback)reconnected_callback);
espconn_regist_disconcb(&conn, (espconn_connect_callback)disconnected_callback);
os_printf("About to connect\n");
//make the connection
if(espconn_connect(&conn) == 0) {
os_printf("Connection successful\n");
} else {
os_printf("Connection error\n");
}
session->activeConnection = &conn;
os_printf("About to return\n");
return 0;
}
LOCAL uint8_t ICACHE_FLASH_ATTR mqtt_connect(mqtt_session_t *session, uint8_t *username, uint8_t *password) {
}
/*************************************************************************************/
/* Function: mqtt_send */
/* Parameters: active mqtt_session_t, pointer to data, data length, and message type */
/* This function must do a few different things: */
/* * It must create the packet based on the message type and data */
/* * It must send the packet to the server */
/*************************************************************************************/
LOCAL uint8_t ICACHE_FLASH_ATTR mqtt_send(mqtt_session_t *session, uint8_t *data, uint32_t len, mqtt_message_type msgType) {
/** First thing to do is check the packet type.
* This will inform everything else we do
*/
os_printf("Entering mqtt_send!\n");
LOCAL mqtt_packet_t packet;
LOCAL mqtt_packet_t *pPacket = &packet;
uint8_t *fullPacket;
switch(msgType) {
case MQTT_MSG_TYPE_CONNECT:
// prepare packet for connect type
pPacket->fixedHeader = (uint8_t *)os_zalloc(sizeof(uint8_t) * 2); // fixed header cannot be longer than 5
pPacket->fixedHeader[0] = ((uint8_t)msgType << 4) & 0xF0; // make sure lower 4 are clear
// prepare variable header
pPacket->varHeader = os_zalloc(sizeof(uint8_t) * 10); // 10 bytes for connect
pPacket->varHeader[0] = 0;
pPacket->varHeader[1] = 4; // length of protocol name
pPacket->varHeader[2] = 0x4D; // M
pPacket->varHeader[3] = 0x51; // Q
pPacket->varHeader[4] = 0x54; // T
pPacket->varHeader[5] = 0x54; // T
pPacket->varHeader[6] = 4; // protocol level
pPacket->varHeader[7] = 0b11000010; // connect flags, no QOS or will, clean session, user/pass
pPacket->varHeader[8] = 0;
pPacket->varHeader[9] = 10; // keepalive time
pPacket->varHeader_len = 10;
// prepare payload
pPacket->payload = (uint8_t *)os_zalloc(sizeof(uint8_t) * 26);
// client identifier "FRZN0"
pPacket->payload[0] = 0;
pPacket->payload[1] = 5;
pPacket->payload[2] = 0x46; // F
pPacket->payload[3] = 0x52; // R
pPacket->payload[4] = 0x5A; // Z
pPacket->payload[5] = 0x4E; // N
pPacket->payload[6] = 0x30; // 0
// Username
pPacket->payload[7] = 0;
pPacket->payload[8] = 11;
// os_memcpy(pPacket->payload + 9, data, username_len);
pPacket->payload[9] = 0x4D; // M
pPacket->payload[10] = 0x72; // r
pPacket->payload[11] = 0x41; // A
pPacket->payload[12] = 0x75; // u
pPacket->payload[13] = 0x72; // r
pPacket->payload[14] = 0x65; // e
pPacket->payload[15] = 0x6C; // l
pPacket->payload[16] = 0x69; // i
pPacket->payload[17] = 0x75; // u
pPacket->payload[18] = 0x73; // s
pPacket->payload[19] = 0x52; // R
// Password
pPacket->payload[20] = 0;
pPacket->payload[21] = 4;
// os_memcpy(pPacket->payload + 22, data + offset, password_len);
pPacket->payload[22] = 0x74; // t
pPacket->payload[23] = 0x65; // e
pPacket->payload[24] = 0x73; // s
pPacket->payload[25] = 0x74; // t
pPacket->payload_len = 26;
pPacket->fixedHeader[1] = 36; // length of varHeader + payload_len
pPacket->length = 38;
fullPacket = os_zalloc(sizeof(uint8_t) * pPacket->length); //full packet length is 38
os_memcpy(fullPacket, pPacket->fixedHeader, 2);
os_memcpy(fullPacket + 2, pPacket->varHeader, 10);
os_memcpy(fullPacket + 12, pPacket->payload, 26);
break;
case MQTT_MSG_TYPE_PUBLISH:
// prepare for publish
break;
case MQTT_MSG_TYPE_SUBSCRIBE:
// prepare for subscribe
break;
case MQTT_MSG_TYPE_UNSUBSCRIBE:
// prepare for unsubscribe
break;
case MQTT_MSG_TYPE_PINGREQ:
// prepare for ping
break;
case MQTT_MSG_TYPE_DISCONNECT:
// disconnect from broker
break;
default:
// something has gone wrong
os_printf("Attempt to send incorrect packet type: %d", (uint8_t)msgType);
return -1;
}
os_printf("About to send MQTT connect...\n");
espconn_send(session->activeConnection, fullPacket, pPacket->length);
os_free(fullPacket);
}
LOCAL void ICACHE_FLASH_ATTR test(void *arg) {
os_printf("Entered test!\n");
mqtt_session_t *pSession = (mqtt_session_t *)arg;
mqtt_send(pSession, NULL, 0, MQTT_MSG_TYPE_CONNECT);
}
void ICACHE_FLASH_ATTR user_init() {
uint8_t wifiStatus;
LOCAL mqtt_session_t globalSession;
LOCAL mqtt_session_t *pGlobalSession = &globalSession;
char ssid[32] = "Kwangmyong";
char passkey[64] = "vqmfg55020";
struct station_config stationConf;
gpio_init(); // init gpio so we can use the LED
wifi_status_led_install(0, PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0); // set GPIO0 as status LED
stationConf.bssid_set = 0;
os_memcpy(&stationConf.ssid, ssid, 32); // copy the ssid and passkey into the station_config struct
os_memcpy(&stationConf.password, passkey, 64);
wifi_set_opmode_current(0x01); //station mode
wifi_station_set_config_current(&stationConf); // tell it about our config, this auto-connects us as well
// prepare the TCP/MQTT connection stuff
// test server is at 51.15.65.206
char testUser[] = "MrAureliusR";
char testPass[] = "test";
char testTopic[] = "input";
pGlobalSession->port = 1883; // port 80 just for testing
const char esp_tcp_server_ip[4] = {51, 15, 65, 206}; // remote IP of TCP server
os_memcpy(pGlobalSession->ip, esp_tcp_server_ip, 4);
pGlobalSession->username = &testUser[0];
pGlobalSession->password = &testPass[0];
pGlobalSession->topic_name = &testTopic[0];
os_timer_setfn(&oneTimer, (os_timer_func_t *)tcpConnect, pGlobalSession);
os_timer_arm(&oneTimer, 15000, 0);
os_timer_setfn(&testTimer, (os_timer_func_t *)test, pGlobalSession);
os_timer_arm(&testTimer, 16000, 0);
}