remote client and MQTT bridging functionality

pull/16/head
Martin Ger 2017-06-03 15:44:03 +02:00
rodzic 0d735c8024
commit ede97ea37b
13 zmienionych plików z 257 dodań i 181 usunięć

Wyświetl plik

@ -43,7 +43,8 @@ LIB_MODULES = mqtt
LIBS = c gcc hal pp phy net80211 lwip wpa main
# compiler flags using during compilation of source files
CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DUSE_OPTIMIZE_PRINTF
CFLAGS = -Os -g -O2 -Wpointer-arith -Wundef -Werror -Wl,-EL -fno-inline-functions -nostdlib -mlongcalls -mtext-section-literals -D__ets__ -DICACHE_FLASH -DUSE_OPTIMIZE_PRINTF
#-DMQTT_DEBUG_ON
# linker flags used to generate the main object file
LDFLAGS = -nostdlib -Wl,--no-check-sections -u call_user_start -Wl,-static

Wyświetl plik

@ -88,14 +88,8 @@ Advanced commands:
While the user interface looks similar to my esp_wifi_repeater at https://github.com/martin-ger/esp_wifi_repeater this does NO NAT routing. AP and STA network are stricly separated and there is no routing in between. The only possible connection via both networks is the uMQTT broker that listens on both interfaces.
# LOCAL client
The broker comes with a "LOCAL client", which means, the broker itself can publish and subscribe topics (without the need of an additional TCP connection). You can test this with the commands:
- publish [topic] [data]: this publishes a topic
- subscribe [topic]: subscribes to a topic, received topic will be printed to serial output
- unsubscribe [topic]: unsubscribes from a topic
This feature is meant to provide the basis for a local rule engine that can react on MQTT events, e.g. to switch GPIOs or send other messages (MQTT, HTTP,...). You can use this with the functions:
# MQTT client/bridging functionality
The broker comes with a "local" and a "remote" client, which means, the broker itself can publish and subscribe topics. The "local" client is a client to the own broker (without the need of an additional TCP connection). This feature is meant to provide the basis for a local rule engine that can react on MQTT events, e.g. to switch GPIOs or send other messages (MQTT, HTTP,...). You can use this at source level with the functions:
```c
bool MQTT_local_publish(uint8_t* topic, uint8_t* data, uint16_t data_length, uint8_t qos, uint8_t retain);
@ -103,3 +97,17 @@ bool MQTT_local_subscribe(uint8_t* topic, uint8_t qos);
bool MQTT_local_unsubscribe(uint8_t* topic);
void MQTT_local_onData(MqttDataCallback dataCb);
```
By default the "remote" MQTT client is disabled. It can be enabled by setting the config parameter "mqtt_host" to a hostname different from "none". To configure the "remote" MQTT client you can set the following parameters:
- set mqtt_host _IP_or_hostname_: IP or hostname of the MQTT broker ("none" disables the MQTT client)
- set mqtt_user _username_: Username for authentication ("none" if no authentication is required at the broker)
- set mqtt_user _password_: Password for authentication
- set mqtt_id _clientId_: Id of the client at the broker (default: "ESPRouter_xxxxxx" derived from the MAC address)
You can test this with the commands:
- publish [local|remote] [topic] [data]: this publishes a topic
- subscribe [local|remote] [topic]: subscribes to a topic, received topic will be printed to serial output
- unsubscribe [local|remote] [topic]: unsubscribes from a topic
Currently the clients republish everything they receive (and they have subscribed) to the other client, thus it can act as something like an MQTT bridge. Up to now, the subscriptions are not persistently saved to config, so they have to be entered manually after each reboot - will work on this...

Plik binarny nie jest wyświetlany.

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -1,44 +0,0 @@
#############################################################
# Required variables for each makefile
# Discard this section from all parent makefiles
# Expected variables (with automatic defaults):
# CSRCS (all "C" files in the dir)
# SUBDIRS (all subdirs with a Makefile)
# GEN_LIBS - list of libs to be generated ()
# GEN_IMAGES - list of images to be generated ()
# COMPONENTS_xxx - a list of libs/objs in the form
# subdir/lib to be extracted and rolled up into
# a generated lib/image xxx.a ()
#
ifndef PDIR
GEN_LIBS = libmqtt.a
endif
#############################################################
# Configuration i.e. compile options etc.
# Target specific stuff (defines etc.) goes in here!
# Generally values applying to a tree are captured in the
# makefile at its root level - these are then overridden
# for a subtree within the makefile rooted therein
#
#DEFINES +=
#############################################################
# Recursion Magic - Don't touch this!!
#
# Each subtree potentially has an include directory
# corresponding to the common APIs applicable to modules
# rooted at that subtree. Accordingly, the INCLUDE PATH
# of a module can only contain the include directories up
# its parent path, and not its siblings
#
# Required for each makefile to inherit from the parent
#
INCLUDES := $(INCLUDES) -I $(PDIR)include
INCLUDES += -I ./
PDIR := ../$(PDIR)
sinclude $(PDIR)Makefile

Wyświetl plik

@ -1,13 +0,0 @@
/*
* wifi.h
*
* Created on: Dec 30, 2014
* Author: Minh
*/
#ifndef USER_WIFI_H_
#define USER_WIFI_H_
#include "os_type.h"
typedef void (*WifiCallback)(uint8_t);
void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback cb);
#endif /* USER_WIFI_H_ */

Wyświetl plik

@ -1,79 +0,0 @@
/*
* wifi.c
*
* Created on: Dec 30, 2014
* Author: Minh
*/
#include "wifi.h"
#include "user_interface.h"
#include "osapi.h"
#include "espconn.h"
#include "os_type.h"
#include "mem.h"
#include "mqtt_msg.h"
#include "debug.h"
#include "user_config.h"
static ETSTimer WiFiLinker;
WifiCallback wifiCb = NULL;
static uint8_t wifiStatus = STATION_IDLE, lastWifiStatus = STATION_IDLE;
static void ICACHE_FLASH_ATTR wifi_check_ip(void *arg)
{
struct ip_info ipConfig;
os_timer_disarm(&WiFiLinker);
wifi_get_ip_info(STATION_IF, &ipConfig);
wifiStatus = wifi_station_get_connect_status();
if (wifiStatus == STATION_GOT_IP && ipConfig.ip.addr != 0)
{
os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
os_timer_arm(&WiFiLinker, 2000, 0);
}
else
{
if (wifi_station_get_connect_status() == STATION_WRONG_PASSWORD)
{
INFO("STATION_WRONG_PASSWORD\r\n");
wifi_station_connect();
}
else if (wifi_station_get_connect_status() == STATION_NO_AP_FOUND)
{
INFO("STATION_NO_AP_FOUND\r\n");
wifi_station_connect();
}
else if (wifi_station_get_connect_status() == STATION_CONNECT_FAIL)
{
INFO("STATION_CONNECT_FAIL\r\n");
wifi_station_connect();
}
else
{
INFO("STATION_IDLE\r\n");
}
os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
os_timer_arm(&WiFiLinker, 500, 0);
}
if (wifiStatus != lastWifiStatus) {
lastWifiStatus = wifiStatus;
if (wifiCb)
wifiCb(wifiStatus);
}
}
void ICACHE_FLASH_ATTR WIFI_Connect(uint8_t* ssid, uint8_t* pass, WifiCallback cb)
{
struct station_config stationConf;
INFO("WIFI_INIT\r\n");
wifi_set_opmode_current(STATION_MODE);
wifiCb = cb;
os_memset(&stationConf, 0, sizeof(struct station_config));
os_sprintf(stationConf.ssid, "%s", ssid);
os_sprintf(stationConf.password, "%s", pass);
wifi_station_set_config_current(&stationConf);
os_timer_disarm(&WiFiLinker);
os_timer_setfn(&WiFiLinker, (os_timer_func_t *)wifi_check_ip, NULL);
os_timer_arm(&WiFiLinker, 1000, 0);
wifi_station_connect();
}

Wyświetl plik

@ -470,7 +470,6 @@ mqtt_tcpclient_sent_cb(void *arg)
void ICACHE_FLASH_ATTR mqtt_timer(void *arg)
{
MQTT_Client* client = (MQTT_Client*)arg;
if (client->connState == MQTT_DATA) {
client->keepAliveTick ++;
if (client->keepAliveTick > (client->mqtt_state.connect_info->keepalive / 2)) {
@ -700,6 +699,7 @@ MQTT_Task(os_event_t *e)
uint16_t dataLen;
if (e->par == 0)
return;
MQTT_INFO("MQTT: Client task activated - state %d\r\n", client->connState);
switch (client->connState) {
case TCP_RECONNECT_REQ:

Wyświetl plik

@ -18,6 +18,7 @@ return _v;
#include "mqtt_topics.h"
#include "mqtt_topiclist.h"
#include "mqtt_retainedlist.h"
#include "debug.h"
#ifndef QUEUE_BUFFER_SIZE
#define QUEUE_BUFFER_SIZE 2048
@ -25,7 +26,7 @@ return _v;
#define MAX_SUBS_PER_REQ 16
#define MQTT_TASK_PRIO 2
#define MQTT_SERVER_TASK_PRIO 1
#define MQTT_TASK_QUEUE_SIZE 1
#define MQTT_SEND_TIMOUT 5
@ -36,7 +37,7 @@ LOCAL uint8_t zero_len_id[2] = { 0, 0 };
MQTT_ClientCon *clientcon_list;
LOCAL MqttDataCallback local_data_cb = NULL;
#define MQTT_INFO //
//#define MQTT_INFO os_printf
#define MQTT_WARNING os_printf
#define MQTT_ERROR os_printf
@ -99,7 +100,7 @@ MQTT_ClientCon *clientcon = clientcon_list;
for (clientcon = clientcon_list; clientcon != NULL; clientcon = clientcon->next) {
if (!QUEUE_IsEmpty(&clientcon->msgQueue)) {
MQTT_INFO("MQTT: Next message to client: %s\r\n", clientcon->connect_info.client_id);
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)clientcon);
system_os_post(MQTT_SERVER_TASK_PRIO, 0, (os_param_t)clientcon);
return true;
}
}
@ -243,7 +244,7 @@ MQTT_ServerDisconnect(MQTT_ClientCon *mqttClientCon)
mqttClientCon->mqtt_state.message_length_read = 0;
mqttClientCon->connState = TCP_DISCONNECTED;
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)mqttClientCon);
system_os_post(MQTT_SERVER_TASK_PRIO, 0, (os_param_t)mqttClientCon);
os_timer_disarm(&mqttClientCon->mqttTimer);
}
@ -668,7 +669,7 @@ READPACKET:
clientcon->mqtt_state.message_length_read = 0;
if (msg_type != MQTT_MSG_TYPE_PUBLISH) {
system_os_post(MQTT_TASK_PRIO, 0, (os_param_t)clientcon);
system_os_post(MQTT_SERVER_TASK_PRIO, 0, (os_param_t)clientcon);
} else {
activate_next_client();
}
@ -741,7 +742,7 @@ MQTT_ServerTask(os_event_t *e)
if (e->par == 0)
return;
MQTT_INFO("MQTT Task: State %d \r\n", clientcon->connState);
MQTT_INFO("MQTT: Server task activated - state %d\r\n", clientcon->connState);
switch (clientcon->connState) {
@ -800,7 +801,7 @@ bool ICACHE_FLASH_ATTR MQTT_server_start(uint16_t portno, uint16_t max_subscript
/* Put the connection in accept mode */
espconn_accept(pCon);
system_os_task(MQTT_ServerTask, MQTT_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE);
system_os_task(MQTT_ServerTask, MQTT_SERVER_TASK_PRIO, mqtt_procTaskQueue, MQTT_TASK_QUEUE_SIZE);
return true;
}

Wyświetl plik

@ -33,6 +33,15 @@ uint8_t mac[6];
config->clock_speed = 80;
config->config_port = CONSOLE_SERVER_PORT;
#ifdef MQTT_CLIENT
os_sprintf(config->mqtt_host,"%s", "none");
config->mqtt_port = 1883;
os_sprintf(config->mqtt_user,"%s", "none");
config->mqtt_password[0] = 0;
wifi_get_macaddr(0, mac);
os_sprintf(config->mqtt_id,"%s_%2x%2x%2x", MQTT_ID, mac[3], mac[4], mac[5]);
#endif
}
int config_load(sysconfig_p config)

Wyświetl plik

@ -44,6 +44,16 @@ typedef struct
uint16_t clock_speed; // Freq of the CPU
uint16_t config_port; // Port on which the concole listenes (0 if no access)
#ifdef MQTT_CLIENT
uint8_t mqtt_host[32]; // IP or hostname of the MQTT broker, "none" if empty
uint16_t mqtt_port; // Port of the MQTT broker
uint8_t mqtt_user[32]; // Username for broker login, "none" if empty
uint8_t mqtt_password[32]; // Password for broker login
uint8_t mqtt_id[32]; // MQTT clientId
#endif
} sysconfig_t, *sysconfig_p;
int config_load(sysconfig_p config);

Wyświetl plik

@ -16,12 +16,17 @@ typedef enum {SIG_DO_NOTHING=0, SIG_START_SERVER=1, SIG_SEND_DATA, SIG_UART0, SI
// Here the MQTT stuff
//
// Define this if you want to have it work as a MQTT client
#define MQTT_CLIENT 1
#define MQTT_BUF_SIZE 1024
#define MQTT_KEEPALIVE 120 /*seconds*/
#define MQTT_RECONNECT_TIMEOUT 5 /*seconds*/
//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
#define PROTOCOL_NAMEv311 /*MQTT version 3.11 compatible with https://eclipse.org/paho/clients/testing/*/
#define MQTT_ID "ESPBroker"
//
// Size of the console buffers
//

Wyświetl plik

@ -45,6 +45,49 @@ uint8_t remote_console_disconnect;
void ICACHE_FLASH_ATTR user_set_softap_wifi_config(void);
void ICACHE_FLASH_ATTR user_set_softap_ip_config(void);
#ifdef MQTT_CLIENT
MQTT_Client mqttClient;
bool mqtt_enabled, mqtt_connected;
static void ICACHE_FLASH_ATTR mqttConnectedCb(uint32_t *args)
{
uint8_t ip_str[16];
MQTT_Client* client = (MQTT_Client*)args;
mqtt_connected = true;
os_printf("MQTT client connected\r\n");
}
static void ICACHE_FLASH_ATTR mqttDisconnectedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
mqtt_connected = false;
os_printf("MQTT client disconnected\r\n");
}
static void ICACHE_FLASH_ATTR mqttPublishedCb(uint32_t *args)
{
MQTT_Client* client = (MQTT_Client*)args;
// os_printf("MQTT: Published\r\n");
}
static void ICACHE_FLASH_ATTR mqttDataCb(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t data_len)
{
MQTT_Client* client = (MQTT_Client*)args;
uint8_t buffer[256];
if (topic_len >= sizeof(buffer)) {
os_printf("Topic to long for republication");
return;
}
strncpy(buffer, topic, topic_len);
buffer[topic_len] = 0;
MQTT_local_publish(buffer, (uint8_t*)data, data_len, 0, 0);
}
#endif /* MQTT_CLIENT */
int parse_str_into_tokens(char *str, char **tokens, int max_tokens)
{
char *p, *q;
@ -139,7 +182,7 @@ bool ICACHE_FLASH_ATTR printf_topic(topic_entry *topic, void *user_data)
uint8_t *response = (uint8_t *)user_data;
os_sprintf(response, "%s: \"%s\" (QoS %d)\r\n",
topic->clientcon!=LOCAL_MQTT_CLIENT?topic->clientcon->connect_info.client_id:"LOCAL", topic->topic, topic->qos);
topic->clientcon!=LOCAL_MQTT_CLIENT?topic->clientcon->connect_info.client_id:"local", topic->topic, topic->qos);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
return false;
}
@ -155,7 +198,12 @@ bool ICACHE_FLASH_ATTR printf_retainedtopic(retained_entry *entry, void *user_da
void MQTT_local_DataCallback(uint32_t *args, const char* topic, uint32_t topic_len, const char *data, uint32_t length)
{
os_printf("Received: \"%s\" len: %d\r\n", topic, length);
os_printf("Received: \"%s\" len: %d\r\n", topic, length);
#ifdef MQTT_CLIENT
if (mqtt_connected) {
MQTT_Publish(&mqttClient, topic, data, length, 0, 0);
}
#endif
}
static char INVALID_LOCKED[] = "Invalid command. Config locked\r\n";
@ -164,7 +212,7 @@ static char INVALID_ARG[] = "Invalid argument\r\n";
void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
{
#define MAX_CMD_TOKENS 9
#define MAX_CMD_TOKENS 4
char cmd_line[MAX_CON_CMD_SIZE+1];
char response[256];
@ -188,11 +236,15 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
if (strcmp(tokens[0], "help") == 0)
{
os_sprintf(response, "show [config|stats|mqtt|mqtt_broker]\r\n|set [ssid|password|auto_connect|ap_ssid|ap_password|network|dns|ip|netmask|gw|ap_on|ap_open|speed|config_port] <val>\r\n|quit|save [config]|reset [factory]|lock|unlock <password>|publish <topic> <data>|subscribe <topic>|unsubscribe <topic>");
os_sprintf(response, "show [config|stats|mqtt|mqtt_broker]\r\n|set [ssid|password|auto_connect|ap_ssid|ap_password|network|dns|ip|netmask|gw|ap_on|ap_open|speed|config_port] <val>\r\n|quit|save [config]|reset [factory]|lock|unlock <password>|publish <topic> <data>|subscribe [local|remote] <topic>|unsubscribe [local|remote] <topic>");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#ifdef ALLOW_SCANNING
os_sprintf(response, "|scan");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#endif
#ifdef MQTT_CLIENT
os_sprintf(response, "|set [mqtt_host|mqtt_port|mqtt_user|mqtt_password|mqtt_id] <val>\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#endif
ringbuf_memcpy_into(console_tx_buffer, "\r\n", 2);
goto command_handled_2;
@ -210,21 +262,32 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
config.auto_connect?"":" [AutoConnect:0]");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
os_sprintf(response, "AP: SSID:%s PW:%s%s%s IP:%d.%d.%d.%d/24",
os_sprintf(response, "AP: SSID:%s PW:%s%s%s IP:%d.%d.%d.%d/24\r\n",
config.ap_ssid,
config.locked?"***":(char*)config.ap_password,
config.ap_open?" [open]":"",
config.ap_on?"":" [disabled]",
IP2STR(&config.network_addr));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
// if static DNS, add it
os_sprintf(response, config.dns_addr.addr?" DNS: %d.%d.%d.%d\r\n":"\r\n", IP2STR(&config.dns_addr));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
// if static IP, add it
os_sprintf(response, config.my_addr.addr?"Static IP: %d.%d.%d.%d Netmask: %d.%d.%d.%d Gateway: %d.%d.%d.%d\r\n":"",
IP2STR(&config.my_addr), IP2STR(&config.my_netmask), IP2STR(&config.my_gw));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
// if static DNS, add it
os_sprintf(response, config.dns_addr.addr?"DNS: %d.%d.%d.%d\r\n":"", IP2STR(&config.dns_addr));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#ifdef MQTT_CLIENT
os_sprintf(response, "MQTT client %s\r\n", mqtt_enabled?"enabled":"disabled");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
if (os_strcmp(config.mqtt_host, "none") != 0) {
os_sprintf(response, "MQTT host: %s\r\nMQTT port: %d\r\nMQTT user: %s\r\nMQTT password: %s\r\nMQTT id: %s\r\n",
config.mqtt_host, config.mqtt_port, config.mqtt_user,
config.locked?"***":(char*)config.mqtt_password, config.mqtt_id);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
}
#endif
os_sprintf(response, "Clock speed: %d\r\n", config.clock_speed);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
goto command_handled_2;
@ -238,7 +301,6 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
time/3600, (time%3600)/60, time%60);
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
if (connected) {
os_sprintf(response, "External IP-address: " IPSTR "\r\n", IP2STR(&my_ip));
} else {
@ -246,29 +308,34 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
}
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
if (config.ap_on)
os_sprintf(response, "%d Stations connected\r\n", wifi_softap_get_station_num());
os_sprintf(response, "%d Station%s connected to AP\r\n", wifi_softap_get_station_num(),
wifi_softap_get_station_num()==1?"":"s");
else
os_sprintf(response, "AP disabled\r\n");
os_sprintf(response, "AP disabled\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
goto command_handled_2;
}
if (nTokens == 2 && (strcmp(tokens[1], "mqtt_broker")==0 || strcmp(tokens[1], "mqtt")==0)) {
MQTT_ClientCon *clientcon;
int ccnt = 0;
os_sprintf(response, "Current clients:\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
for (clientcon = clientcon_list; clientcon != NULL; clientcon = clientcon->next) {
for (clientcon = clientcon_list; clientcon != NULL; clientcon = clientcon->next, ccnt++) {
os_sprintf(response, "%s%s", clientcon->connect_info.client_id, clientcon->next != NULL?", ":"");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
}
os_sprintf(response, "\r\nCurrent subsriptions:\r\n");
os_sprintf(response, "%sCurrent subsriptions:\r\n", ccnt?"\r\n":"");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
iterate_topics(printf_topic, response);
os_sprintf(response, "Retained topics:\r\n");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
iterate_retainedtopics(printf_retainedtopic, response);
#ifdef MQTT_CLIENT
os_sprintf(response, "MQTT client %s\r\n", mqtt_connected?"connected":"disconnected");
ringbuf_memcpy_into(console_tx_buffer, response, os_strlen(response));
#endif
goto command_handled_2;
}
}
@ -321,35 +388,59 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
MQTT_local_publish(tokens[1], tokens[2], os_strlen(tokens[2]), 0, 0);
if (strcmp(tokens[1], "local") == 0) {
MQTT_local_publish(tokens[1], tokens[2], os_strlen(tokens[2]), 0, 0);
}
#ifdef MQTT_CLIENT
else if (strcmp(tokens[1], "remote") == 0 && mqtt_connected) {
MQTT_Publish(&mqttClient, tokens[2], tokens[2], os_strlen(tokens[2]), 0, 0);
}
#endif
os_sprintf(response, "Published topic\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "subscribe") == 0)
{
if (nTokens != 2) {
bool retval = false;
if (nTokens != 3) {
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
MQTT_local_subscribe(tokens[1], 0);
os_sprintf(response, "subscribed topic\r\n");
if (strcmp(tokens[1], "local") == 0) {
retval = MQTT_local_subscribe(tokens[2], 0);
}
#ifdef MQTT_CLIENT
else if (strcmp(tokens[1], "remote") == 0 && mqtt_connected) {
retval = MQTT_Subscribe(&mqttClient, tokens[2], 0);
}
#endif
if (retval)
os_sprintf(response, "subscribed topic\r\n");
else
os_sprintf(response, "subscribe failed\r\n");
goto command_handled;
}
if (strcmp(tokens[0], "unsubscribe") == 0)
{
if (nTokens != 2) {
bool retval = false;
if (nTokens != 3) {
os_sprintf(response, INVALID_NUMARGS);
goto command_handled;
}
uint8_t retval = MQTT_local_unsubscribe(tokens[1]);
if (strcmp(tokens[1], "local") == 0) {
retval = MQTT_local_unsubscribe(tokens[2]);
}
#ifdef MQTT_CLIENT
else if (strcmp(tokens[1], "remote") == 0 && mqtt_connected) {
retval = MQTT_UnSubscribe(&mqttClient, tokens[2]);
}
#endif
if (retval)
os_sprintf(response, "unsubscribed topic\r\n");
else
@ -490,6 +581,22 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
goto command_handled;
}
if (strcmp(tokens[1],"dns") == 0)
{
if (os_strcmp(tokens[2], "dhcp") == 0) {
config.dns_addr.addr = 0;
os_sprintf(response, "DNS from DHCP\r\n");
} else {
config.dns_addr.addr = ipaddr_addr(tokens[2]);
os_sprintf(response, "DNS set to %d.%d.%d.%d\r\n",
IP2STR(&config.dns_addr));
if (config.dns_addr.addr) {
dns_ip.addr = config.dns_addr.addr;
}
}
goto command_handled;
}
if (strcmp(tokens[1],"ip") == 0)
{
if (os_strcmp(tokens[2], "dhcp") == 0) {
@ -519,7 +626,48 @@ void ICACHE_FLASH_ATTR console_handle_command(struct espconn *pespconn)
goto command_handled;
}
#ifdef MQTT_CLIENT
if (strcmp(tokens[1], "mqtt_host") == 0)
{
os_strncpy(config.mqtt_host, tokens[2], 32);
config.mqtt_host[31] = 0;
os_sprintf(response, "MQTT host set\r\n");
goto command_handled;
}
if (strcmp(tokens[1], "mqtt_port") == 0)
{
config.mqtt_port = atoi(tokens[2]);
os_sprintf(response, "MQTT port set\r\n");
goto command_handled;
}
if (strcmp(tokens[1], "mqtt_user") == 0)
{
os_strncpy(config.mqtt_user, tokens[2], 32);
config.mqtt_user[31] = 0;
os_sprintf(response, "MQTT user set\r\n");
goto command_handled;
}
if (strcmp(tokens[1], "mqtt_password") == 0)
{
os_strncpy(config.mqtt_password, tokens[2], 32);
config.mqtt_password[31] = 0;
os_sprintf(response, "MQTT password set\r\n");
goto command_handled;
}
if (strcmp(tokens[1], "mqtt_id") == 0)
{
os_strncpy(config.mqtt_id, tokens[2], 32);
config.mqtt_id[31] = 0;
os_sprintf(response, "MQTT id set\r\n");
goto command_handled;
}
#endif /* MQTT_CLIENT */
}
}
/* Control comes here only if the tokens[0] command is not handled */
@ -658,6 +806,11 @@ void wifi_handle_event_cb(System_Event_t *evt)
case EVENT_STAMODE_DISCONNECTED:
os_printf("disconnect from ssid %s, reason %d\n", evt->event_info.disconnected.ssid, evt->event_info.disconnected.reason);
connected = false;
#ifdef MQTT_CLIENT
if (mqtt_enabled) MQTT_Disconnect(&mqttClient);
#endif /* MQTT_CLIENT */
break;
case EVENT_STAMODE_AUTHMODE_CHANGE:
@ -665,11 +818,19 @@ void wifi_handle_event_cb(System_Event_t *evt)
break;
case EVENT_STAMODE_GOT_IP:
if (config.dns_addr.addr == 0) {
dns_ip.addr = dns_getserver(0);
}
os_printf("ip:" IPSTR ",mask:" IPSTR ",gw:" IPSTR ",dns:" IPSTR "\n", IP2STR(&evt->event_info.got_ip.ip), IP2STR(&evt->event_info.got_ip.mask), IP2STR(&evt->event_info.got_ip.gw), IP2STR(&dns_ip));
my_ip = evt->event_info.got_ip.ip;
connected = true;
#ifdef MQTT_CLIENT
if (mqtt_enabled) MQTT_Connect(&mqttClient);
#endif /* MQTT_CLIENT */
// Post a Server Start message as the IP has been acquired to Task with priority 0
system_os_post(user_procTaskPrio, SIG_START_SERVER, 0 );
break;
@ -785,10 +946,8 @@ struct ip_info info;
config_load(&config);
// Configure the AP and start it, if required
if (config.dns_addr.addr == 0)
// Google's DNS as default, as long as we havn't got one from DHCP
IP4_ADDR(&dns_ip, 8, 8, 8, 8);
else
if (config.dns_addr.addr != 0)
// We have a static DNS server
dns_ip.addr = config.dns_addr.addr;
@ -828,6 +987,25 @@ struct ip_info info;
}
#endif
#ifdef MQTT_CLIENT
mqtt_connected = false;
mqtt_enabled = (os_strcmp(config.mqtt_host, "none") != 0);
if (mqtt_enabled) {
MQTT_InitConnection(&mqttClient, config.mqtt_host, config.mqtt_port, 0);
if (os_strcmp(config.mqtt_user, "none") == 0) {
MQTT_InitClient(&mqttClient, config.mqtt_id, 0, 0, 120, 1);
} else {
MQTT_InitClient(&mqttClient, config.mqtt_id, config.mqtt_user, config.mqtt_password, 120, 1);
}
// MQTT_InitLWT(&mqttClient, "/lwt", "offline", 0, 0);
MQTT_OnConnected(&mqttClient, mqttConnectedCb);
MQTT_OnDisconnected(&mqttClient, mqttDisconnectedCb);
MQTT_OnPublished(&mqttClient, mqttPublishedCb);
MQTT_OnData(&mqttClient, mqttDataCb);
}
#endif /* MQTT_CLIENT */
remote_console_disconnect = 0;
// Now start the STA-Mode