kopia lustrzana https://github.com/martin-ger/esp_mqtt
ADC support and shared output buffer
rodzic
ed3a3b621e
commit
f89c74a715
2
Makefile
2
Makefile
|
@ -33,7 +33,7 @@ ESPPORT ?= /dev/ttyUSB0
|
|||
TARGET = app
|
||||
|
||||
# which modules (subdirectories) of the project to include in compiling
|
||||
MODULES = driver user mqtt ntp easygpio pwm httpclient
|
||||
MODULES = driver user mqtt ntp easygpio pwm httpclient adc
|
||||
#EXTRA_INCDIR = $(BUILD_AREA)/esp-open-sdk/esp-open-lwip/include include
|
||||
EXTRA_INCDIR = include
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# esp_uMQTT_broker
|
||||
An MQTT Broker/Client with scripting support on the ESP8266
|
||||
|
||||
This program enables the ESP8266 to become the central node in a small distributed IoT system. It implements an MQTT Broker and a simple scripted rule engine with event/action statements that links together the MQTT sensors and actors. It can act as STA, as AP, or as both and it can connect to another MQTT broker (i.e. in the cloud). Here it can act as bridge and forward and rewrite topics in both directions. Also it can parse JSON structures, write to local GPIO pins, react on timers and GPIO interrupts, drive GPIO pins with PWM, and do basic HTTP GET requests.
|
||||
This program enables the ESP8266 to become the central node in a small distributed IoT system. It implements an MQTT Broker and a simple scripted rule engine with event/action statements that links together the MQTT sensors and actors. It can act as STA, as AP, or as both and it can connect to another MQTT broker (i.e. in the cloud). Here it can act as bridge and forward and rewrite topics in both directions. Also it can parse JSON structures, send basic HTTP GET requests and do basic I/O: i.e. read and write to local GPIO pins, react on timers and GPIO interrupts, drive GPIO pins with PWM, and read the ADC.
|
||||
|
||||
Find a video that explains the ideas and the architecture of the project at: https://www.youtube.com/watch?v=0K9q4IuB_oA
|
||||
|
||||
|
@ -227,6 +227,11 @@ If an *MqttAuthCallback* function is registered with MQTT_server_onAuth(), it is
|
|||
|
||||
The *MqttConnectCallback* function does a similar check for the connection, but it is called right after the connect request before any internal status is allocated. This is done in order to reject requests from unautorized clients in an early stage.
|
||||
|
||||
# Limitations on the number of clients
|
||||
To adjust memory consumption of one MQTT connection and thus the max number of concurrent connections you can redefine MQTT_BUF_SIZE and QUEUE_BUFFER_SIZE in "user_config.h". MQTT_BUF_SIZE is the max. size of pending inbound messages for one connection (and thus also the max. size of a single MQTT message) and QUEUE_BUFFER_SIZE is the max. size of all pending outbound messages for one connection. Currently these parameters are set to 1024 resp. 2048 bytes, resulting in a memory consumption of about 4 KB per connection and a max number of connections of about 8-9 (depending on the memory usage of the rest of the program). When you reduce buffer sizes, e.g. to 512 and 1024 bytes, a single connection requires only about 2.5 KB resulting in up to 13 possible concurrent MQTT connections. In any case you have to increase the number of TCP connections (default 5) first by calling "espconn_tcp_set_max_con(n)" with n, the max. number of concurrent TCP connections, less or equal to 15.
|
||||
|
||||
Also there is a hard limitation on the number of STAs connected to the SoftAP, which is 8. I.e. when using the esp_uMQTT_broker only with clients via the SoftAP interface, even with reduced memory consumtion, the limit of different client nodes is still 8, as it is imposed by the binary WiFi driver. Only when used via the STA interface and an external AP you can connect more than 8 MQTT clients.
|
||||
|
||||
# Thanks
|
||||
- pfalcon for esp_open_sdk (https://github.com/martin-ger/esp-open-sdk)
|
||||
- tuanpmt for esp_mqtt (https://github.com/tuanpmt/esp_mqtt )
|
||||
|
|
19
SCRIPTING.md
19
SCRIPTING.md
|
@ -1,4 +1,5 @@
|
|||
# Scripting Language
|
||||
Scripting Language
|
||||
==================
|
||||
|
||||
The scripting language of the esp_uMQTT_broker is stricly event based. It mainly consists of "on _event_ do _action_" clauses. An event can be:
|
||||
- the reception of an MQTT item,
|
||||
|
@ -56,7 +57,7 @@ In general, scripts conform to the following BNF:
|
|||
<op> := '=' | '>' | gte | str_ge | str_gte | '+' | '-' | '*' | '|' | div
|
||||
|
||||
<val> := <string> | <const> | #<hex-string> | $[any ASCII]* | @<num> |
|
||||
gpio_in(<num>) | $this_item | $this_data | $this_gpio |
|
||||
gpio_in(<num>) | $adc | $this_item | $this_data | $this_gpio |
|
||||
$this_http_code | $this_http_body | $timestamp | $weekday
|
||||
|
||||
<string> := "[any ASCII]*" | [any ASCII]*
|
||||
|
@ -223,13 +224,14 @@ gpio_in(<num>)
|
|||
Reads the current boolean input value of the given GPIO pin. This pin has to be defined as input before using the "gpio_pinmode" action.
|
||||
|
||||
```
|
||||
$this_item | $this_data | $this_gpio | $timestamp | $weekday | $this_http_body | $this_http_code
|
||||
$adc | $this_item | $this_data | $this_gpio | $timestamp | $weekday | $this_http_body | $this_http_code
|
||||
```
|
||||
Special variables:
|
||||
$this_topic and $this_data are only defined in "on topic" clauses and contain the current topic and its data.
|
||||
$this_gpio contains the state of the GPIO in an "on gpio_interrupt" clause.
|
||||
$timestamp contains the current time of day in "hh:mm:ss" format. If no NTP sync happened the time will be reported as "99:99:99". $weekday returns the day of week as three letters ("Mon","Tue",...).
|
||||
$this_http_body and $this_http_code are only defined inside the "on http_response" clause and contain the body of an HTTP response and the HTTP return code.
|
||||
- $adc gives you the current value of the ADC (analog to digital input pin)
|
||||
- $this_topic and $this_data are only defined in "on topic" clauses and contain the current topic and its data.
|
||||
- $this_gpio contains the state of the GPIO in an "on gpio_interrupt" clause.
|
||||
- $timestamp contains the current time of day in "hh:mm:ss" format. If no NTP sync happened the time will be reported as "99:99:99". $weekday returns the day of week as three letters ("Mon","Tue",...).
|
||||
- $this_http_body and $this_http_code are only defined inside the "on http_response" clause and contain the body of an HTTP response and the HTTP return code.
|
||||
|
||||
# Operators
|
||||
Operators are used to combine values and expressions.
|
||||
|
@ -242,7 +244,7 @@ These operators result in boolean values and are typically used in comparisons i
|
|||
```
|
||||
'+' | '-' | '*' | div
|
||||
```
|
||||
These operators are the arithmetical operations. CAUTION: arithmetical preceedence does not (yet) apply automatically, all expressions are evaluated from left to right. I.e. "2+3*4" evaluates to 20 instead of 14. However, the preceedence can be fully controlled by brackets. Write "2+(3*4)" instead.
|
||||
These operators are the arithmetical operations. CAUTION: arithmetical preceedence does not (yet) apply automatically, all expressions are evaluated from left to right. I.e. "2+3\*4" evaluates to 20 instead of 14. However, the preceedence can be fully controlled by brackets. Write "2+(3\*4)" instead.
|
||||
|
||||
```
|
||||
'|'
|
||||
|
@ -376,3 +378,4 @@ do
|
|||
publish local $command_topic "off"
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
#include "ets_sys.h"
|
||||
#include "osapi.h"
|
||||
|
||||
#include "adc.h"
|
||||
|
||||
#define i2c_bbpll 0x67
|
||||
#define i2c_bbpll_en_audio_clock_out 4
|
||||
#define i2c_bbpll_en_audio_clock_out_msb 7
|
||||
#define i2c_bbpll_en_audio_clock_out_lsb 7
|
||||
#define i2c_bbpll_hostid 4
|
||||
#define i2c_saradc 0x6C
|
||||
#define i2c_saradc_hostid 2
|
||||
|
||||
#define i2c_saradc_en_test 0
|
||||
#define i2c_saradc_en_test_msb 5
|
||||
#define i2c_saradc_en_test_lsb 5
|
||||
|
||||
#define i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata) \
|
||||
rom_i2c_writeReg_Mask(block, host_id, reg_add, Msb, Lsb, indata)
|
||||
|
||||
#define i2c_readReg_Mask(block, host_id, reg_add, Msb, Lsb) \
|
||||
rom_i2c_readReg_Mask_(block, host_id, reg_add, Msb, Lsb)
|
||||
|
||||
#define i2c_writeReg_Mask_def(block, reg_add, indata) \
|
||||
i2c_writeReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb, indata)
|
||||
|
||||
#define i2c_readReg_Mask_def(block, reg_add) \
|
||||
i2c_readReg_Mask(block, block##_hostid, reg_add, reg_add##_msb, reg_add##_lsb)
|
||||
|
||||
#ifdef ADC_DEBUG
|
||||
#define ADC_DBG os_printf
|
||||
#else
|
||||
#define ADC_DBG
|
||||
#endif
|
||||
|
||||
uint16 ICACHE_FLASH_ATTR adc_read(void)
|
||||
{
|
||||
uint8 i;
|
||||
uint16 sar_dout, tout, sardata[8];
|
||||
|
||||
i2c_writeReg_Mask_def(i2c_saradc, i2c_saradc_en_test, 1); //select test mux
|
||||
|
||||
//PWDET_CAL_EN=0, PKDET_CAL_EN=0
|
||||
SET_PERI_REG_MASK(0x60000D5C, 0x200000);
|
||||
|
||||
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
|
||||
|
||||
sar_dout = 0;
|
||||
CLEAR_PERI_REG_MASK(0x60000D50, 0x02); //force_en=0
|
||||
SET_PERI_REG_MASK(0x60000D50, 0x02); //force_en=1
|
||||
|
||||
os_delay_us(2);
|
||||
|
||||
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
|
||||
|
||||
read_sar_dout(sardata);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
sar_dout += sardata[i];
|
||||
ADC_DBG("%d, ", sardata[i]);
|
||||
}
|
||||
|
||||
tout = (sar_dout + 8) >> 4; //tout is 10 bits fraction
|
||||
|
||||
i2c_writeReg_Mask_def(i2c_saradc, i2c_saradc_en_test, 1); //select test mux
|
||||
|
||||
while (GET_PERI_REG_BITS(0x60000D50, 26, 24) > 0); //wait r_state == 0
|
||||
|
||||
CLEAR_PERI_REG_MASK(0x60000D5C, 0x200000);
|
||||
SET_PERI_REG_MASK(0x60000D60, 0x1); //force_en=1
|
||||
CLEAR_PERI_REG_MASK(0x60000D60, 0x1); //force_en=1
|
||||
|
||||
return tout; //tout is 10 bits fraction
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef __ADC_H__
|
||||
#define __ADC_H__
|
||||
|
||||
uint16 adc_read(void);
|
||||
|
||||
#endif
|
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
Plik binarny nie jest wyświetlany.
|
@ -1,2 +1,2 @@
|
|||
8c0436ab218b8b4165f57501775797e09e818ae0 0x00000.bin
|
||||
b02f819746fe72bb7692e9c6bb2c37d175f58b24 0x10000.bin
|
||||
25afd95372b46210eedc30515d63589985c2d281 0x00000.bin
|
||||
3ef293f39d57c0379b8c9ec4795fb38360d2b214 0x10000.bin
|
||||
|
|
|
@ -278,7 +278,7 @@ void ICACHE_FLASH_ATTR mqtt_tcpclient_recv(void *arg, char *pdata, unsigned shor
|
|||
struct espconn *pCon = (struct espconn *)arg;
|
||||
MQTT_Client *client = (MQTT_Client *) pCon->reverse;
|
||||
|
||||
client->keepAliveTick = 0;
|
||||
//client->keepAliveTick = 0;
|
||||
READPACKET:
|
||||
MQTT_INFO("TCP: data received %d bytes\r\n", len);
|
||||
// MQTT_INFO("STATE: %d\r\n", client->connState);
|
||||
|
@ -722,6 +722,7 @@ void ICACHE_FLASH_ATTR MQTT_Task(os_event_t * e) {
|
|||
client->sendTimeout = MQTT_SEND_TIMOUT;
|
||||
MQTT_INFO("MQTT: Sending, type: %d, id: %04X\r\n", client->mqtt_state.pending_msg_type,
|
||||
client->mqtt_state.pending_msg_id);
|
||||
client->keepAliveTick = 0;
|
||||
if (client->security) {
|
||||
#ifdef MQTT_SSL_ENABLE
|
||||
espconn_secure_send(client->pCon, dataBuffer, dataLen);
|
||||
|
|
|
@ -22,10 +22,6 @@ return _v;
|
|||
#define os_malloc(x) my_os_zalloc(x, __LINE__)
|
||||
*/
|
||||
|
||||
#ifndef QUEUE_BUFFER_SIZE
|
||||
#define QUEUE_BUFFER_SIZE 2048
|
||||
#endif
|
||||
|
||||
#define MAX_SUBS_PER_REQ 16
|
||||
|
||||
#define MQTT_SERVER_TASK_PRIO 1
|
||||
|
@ -125,6 +121,8 @@ bool ICACHE_FLASH_ATTR activate_next_client() {
|
|||
return true;
|
||||
}
|
||||
|
||||
static uint8_t shared_out_buffer[MQTT_BUF_SIZE];
|
||||
|
||||
bool ICACHE_FLASH_ATTR MQTT_InitClientCon(MQTT_ClientCon * mqttClientCon) {
|
||||
uint32_t temp;
|
||||
MQTT_INFO("MQTT:InitClientCon\r\n");
|
||||
|
@ -138,7 +136,8 @@ bool ICACHE_FLASH_ATTR MQTT_InitClientCon(MQTT_ClientCon * mqttClientCon) {
|
|||
|
||||
mqttClientCon->mqtt_state.in_buffer = (uint8_t *) os_zalloc(MQTT_BUF_SIZE);
|
||||
mqttClientCon->mqtt_state.in_buffer_length = MQTT_BUF_SIZE;
|
||||
mqttClientCon->mqtt_state.out_buffer = (uint8_t *) os_zalloc(MQTT_BUF_SIZE);
|
||||
// mqttClientCon->mqtt_state.out_buffer = (uint8_t *) os_zalloc(MQTT_BUF_SIZE);
|
||||
mqttClientCon->mqtt_state.out_buffer = shared_out_buffer;
|
||||
mqttClientCon->mqtt_state.out_buffer_length = MQTT_BUF_SIZE;
|
||||
mqttClientCon->mqtt_state.connect_info = &mqttClientCon->connect_info;
|
||||
|
||||
|
@ -182,18 +181,20 @@ bool ICACHE_FLASH_ATTR MQTT_DeleteClientCon(MQTT_ClientCon * mqttClientCon) {
|
|||
mqttClientCon->mqtt_state.in_buffer = NULL;
|
||||
}
|
||||
|
||||
if (mqttClientCon->mqtt_state.out_buffer != NULL) {
|
||||
os_free(mqttClientCon->mqtt_state.out_buffer);
|
||||
mqttClientCon->mqtt_state.out_buffer = NULL;
|
||||
}
|
||||
/* We use one static buffer for all connections
|
||||
// if (mqttClientCon->mqtt_state.out_buffer != NULL) {
|
||||
// os_free(mqttClientCon->mqtt_state.out_buffer);
|
||||
// mqttClientCon->mqtt_state.out_buffer = NULL;
|
||||
// }
|
||||
|
||||
if (mqttClientCon->mqtt_state.outbound_message != NULL) {
|
||||
if (mqttClientCon->mqtt_state.outbound_message->data != NULL) {
|
||||
os_free(mqttClientCon->mqtt_state.outbound_message->data);
|
||||
// Don't think, this is has ever been allocated separately
|
||||
// os_free(mqttClientCon->mqtt_state.outbound_message->data);
|
||||
mqttClientCon->mqtt_state.outbound_message->data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
if (mqttClientCon->mqtt_state.mqtt_connection.buffer != NULL) {
|
||||
// Already freed but not NULL
|
||||
mqttClientCon->mqtt_state.mqtt_connection.buffer = NULL;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
% Config params, overwrite any previous settings from the commandline
|
||||
% Nothing here
|
||||
|
||||
% Now the events, checked whenever something happens
|
||||
|
||||
on init
|
||||
do
|
||||
settimer 1 1000
|
||||
|
||||
on timer 1
|
||||
do
|
||||
println "ADC value: " | $adc
|
||||
settimer 1 1000
|
||||
|
||||
|
16
user/lang.c
16
user/lang.c
|
@ -16,6 +16,10 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef ADC
|
||||
#include "adc.h"
|
||||
#endif
|
||||
|
||||
#ifdef JSON_PARSE
|
||||
#include "json_path.h"
|
||||
#endif
|
||||
|
@ -1340,6 +1344,18 @@ int ICACHE_FLASH_ATTR parse_value(int next_token, char **data, int *data_len, Va
|
|||
*data_type = STRING_T;
|
||||
return next_token + 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef ADC
|
||||
else if (is_token(next_token, "$adc")) {
|
||||
static char adcbuf[8];
|
||||
lang_debug("val $adc\r\n");
|
||||
|
||||
os_sprintf(adcbuf, "%d", adc_read());
|
||||
*data = adcbuf;
|
||||
*data_len = os_strlen(*data);
|
||||
*data_type = STRING_T;
|
||||
return next_token + 1;
|
||||
}
|
||||
#endif
|
||||
else if (my_token[next_token][0] == '$' && my_token[next_token][1] != '\0') {
|
||||
lang_debug("val var %s\r\n", &(my_token[next_token][1]));
|
||||
|
|
|
@ -20,7 +20,14 @@
|
|||
#define MQTT_CLIENT 1
|
||||
//#define MQTT_SSL_ENABLE 1
|
||||
|
||||
//
|
||||
// Change this to adjust memory consuption of one MQTT connection
|
||||
// MQTT_BUF_SIZE is the max. size of pending inbound messages for one connection
|
||||
// QUEUE_BUFFER_SIZE is the max. size of all pending outbound messages for one connection
|
||||
//
|
||||
#define MQTT_BUF_SIZE 1024
|
||||
#define QUEUE_BUFFER_SIZE 2048
|
||||
|
||||
#define MQTT_KEEPALIVE 120 /*seconds*/
|
||||
#define MQTT_RECONNECT_TIMEOUT 5 /*seconds*/
|
||||
//#define PROTOCOL_NAMEv31 /*MQTT version 3.1 compatible with Mosquitto v0.15*/
|
||||
|
@ -47,21 +54,18 @@
|
|||
|
||||
//
|
||||
// Define this if you want to have GPIO OUT support in scripts.
|
||||
// Define GPIO_PWM if you want to have additionally GPIO PWM support in scripts.
|
||||
//
|
||||
#define GPIO 1
|
||||
|
||||
//
|
||||
// Define this if you want to have additionally GPIO PWM support in scripts.
|
||||
//
|
||||
#define GPIO_PWM 1
|
||||
|
||||
//
|
||||
// Define this if you want to have NTP support.
|
||||
// Define this if you want to have ADC support.
|
||||
//
|
||||
#define NTP 1
|
||||
#define ADC 1
|
||||
|
||||
//
|
||||
// Define this if you want to have HTTP client support.
|
||||
// Define this if you want to have HTTP client support in scripts.
|
||||
// Define HTTPCS if you want to have additional HTTPS support.
|
||||
//
|
||||
#define HTTPC 1
|
||||
|
@ -72,6 +76,11 @@
|
|||
//
|
||||
#define JSON_PARSE 1
|
||||
|
||||
//
|
||||
// Define this if you want to have NTP support.
|
||||
//
|
||||
#define NTP 1
|
||||
|
||||
//
|
||||
// Define this if you want to have mDNS support.
|
||||
//
|
||||
|
|
|
@ -1626,7 +1626,7 @@ void user_init() {
|
|||
|
||||
// Start the broker only if it accessible
|
||||
if (config.mqtt_broker_access != 0) {
|
||||
espconn_tcp_set_max_con(10);
|
||||
espconn_tcp_set_max_con(15);
|
||||
os_printf("Max number of TCP clients: %d\r\n", espconn_tcp_get_max_con());
|
||||
|
||||
MQTT_server_onData(MQTT_local_DataCallback);
|
||||
|
|
Ładowanie…
Reference in New Issue