Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

IoT watchman #94

Open
wants to merge 5 commits into
base: sensors
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/cpp/sensor_monitor/esp32/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
PROJECT_NAME := hardware_lib

export IDF_PATH := /usr/share/esp/esp-idf
include $(IDF_PATH)/make/project.mk
25 changes: 25 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
cmake_minimum_required(VERSION 3.7)
project(esp-mqtt)

set(CMAKE_C_STANDARD 99)

include_directories(
test/build/include
test/xtensa-esp32-elf/xtensa-esp32-elf/include
test/esp-idf/components/esp32/include
test/esp-idf/components/freertos/include
test/esp-idf/components/log/include
test/esp-idf/components/tcpip_adapter/include
test/esp-idf/components/lwip/include/lwip/port
test/esp-idf/components/lwip/include/lwip
lwmqtt/include
.)

set(SOURCE_FILES
esp_lwmqtt.c
esp_lwmqtt.h
esp_mqtt.c
esp_mqtt.h
test/main/main.c)

add_library(esp-mqtt ${SOURCE_FILES})
26 changes: 26 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
menu "esp-mqtt"

config ESP_MQTT_ENABLED
bool "Enable the MQTT component"
select LWIP_SO_RCVBUF
default y
help
This is currently only used to enforce the selection of LWIP_SO_RCVBUF.
Disabling the component does not actually disable something.

config ESP_MQTT_TASK_STACK_SIZE
int "MQTT background process task stack size"
default 4096

config ESP_MQTT_TASK_STACK_PRIORITY
int "MQTT background process task priority"
default 5

config ESP_MQTT_EVENT_QUEUE_SIZE
int "MQTT event queue size"
default 64
help
This value defines the amount of messages that are queued during various
calls and dispatched by the background process.

endmenu
21 changes: 21 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2017 Joël Gähwiler

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
40 changes: 40 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
UNAME := $(shell uname)

XTENSA_TOOLCHAIN := "xtensa-esp32-elf-linux64-1.22.0-73-ge28a011-5.2.0.tar.gz"

ifeq ($(UNAME), Darwin)
XTENSA_TOOLCHAIN := "xtensa-esp32-elf-osx-1.22.0-73-ge28a011-5.2.0.tar.gz"
endif

fmt:
clang-format -i ./*.c ./*.h -style="{BasedOnStyle: Google, ColumnLimit: 120}"
clang-format -i ./test/main/*.c -style="{BasedOnStyle: Google, ColumnLimit: 120}"

test/xtensa-esp32-elf:
wget https://dl.espressif.com/dl/$(XTENSA_TOOLCHAIN)
cd test; tar -xzf ../$(XTENSA_TOOLCHAIN)
rm *.tar.gz

test/esp-idf:
git clone --recursive --depth 1 https://github.com/espressif/esp-idf.git test/esp-idf

defconfig: test/xtensa-esp32-elf test/esp-idf
export PATH=$(shell pwd)/test/xtensa-esp32-elf/bin:$$PATH; cd ./test; make defconfig

erase: test/xtensa-esp32-elf test/esp-idf
export PATH=$(shell pwd)/test/xtensa-esp32-elf/bin:$$PATH; cd ./test; make erase_flash

clean: test/xtensa-esp32-elf test/esp-idf
export PATH=$(shell pwd)/test/xtensa-esp32-elf/bin:$$PATH; cd ./test; make clean

build: test/xtensa-esp32-elf test/esp-idf
export PATH=$(shell pwd)/test/xtensa-esp32-elf/bin:$$PATH; cd ./test; make

flash: test/xtensa-esp32-elf test/esp-idf
export PATH=$(shell pwd)/test/xtensa-esp32-elf/bin:$$PATH; cd ./test; make flash

monitor: test/xtensa-esp32-elf test/esp-idf
@clear
miniterm.py /dev/cu.SLAB_USBtoUART 115200 --rts 0 --dtr 0 --raw --exit-char 99

run: erase build flash monitor
49 changes: 49 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# esp-mqtt

[![Build Status](https://travis-ci.org/256dpi/esp-mqtt.svg?branch=master)](https://travis-ci.org/256dpi/esp-mqtt)
[![Release](https://img.shields.io/github/release/256dpi/esp-mqtt.svg)](https://github.com/256dpi/esp-mqtt/releases)

**MQTT component for esp-idf projects based on the [lwmqtt](https://github.com/256dpi/lwmqtt) library**

This component bundles the lwmqtt client and adds a simple async API similar to other esp networking components.

## Installation

You can install the component by adding it as a git submodule:

```bash
git submodule add https://github.com/256dpi/esp-mqtt.git components/esp-mqtt
git submodule update --init --recursive
```

The component will automatically enable the LWIP receive buffers.

## API

Initialize the component once by passing the necessary callbacks:

```c++
void esp_mqtt_init(esp_mqtt_status_callback_t scb, esp_mqtt_message_callback_t mcb,
size_t buffer_size, int command_timeout);
```

When the WiFi connection has been established, start the process:

```c++
void esp_mqtt_start(const char *host, int port, const char *client_id,
const char *username, const char *password);
```

When the client has connected, interact with the broker:

```c++
bool esp_mqtt_subscribe(const char *topic, int qos);
bool esp_mqtt_unsubscribe(const char *topic);
bool esp_mqtt_publish(const char *topic, uint8_t *payload, size_t len, int qos, bool retained);
```

If the WiFi connection has been lost, stop the process:

```c++
void esp_mqtt_stop();
```
2 changes: 2 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/component.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
COMPONENT_ADD_INCLUDEDIRS := . lwmqtt/include
COMPONENT_SRCDIRS := . lwmqtt/src
150 changes: 150 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/esp_lwmqtt.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
#include <lwip/api.h>

// Some docs about netconn: http://www.ecoscentric.com/ecospro/doc/html/ref/lwip-api-sequential-reference.html.

#include "esp_lwmqtt.h"

void esp_lwmqtt_timer_set(lwmqtt_client_t *client, void *ref, uint32_t timeout) {
// cast timer reference
esp_lwmqtt_timer_t *t = (esp_lwmqtt_timer_t *)ref;

// set deadline
t->deadline = (xTaskGetTickCount() / portTICK_PERIOD_MS) + timeout;
}

uint32_t esp_lwmqtt_timer_get(lwmqtt_client_t *client, void *ref) {
// cast timer reference
esp_lwmqtt_timer_t *t = (esp_lwmqtt_timer_t *)ref;

return t->deadline - (xTaskGetTickCount() / portTICK_PERIOD_MS);
}

lwmqtt_err_t esp_lwmqtt_network_connect(esp_lwmqtt_network_t *network, char *host, int port) {
// disconnect if not already the case
esp_lwmqtt_network_disconnect(network);

// resolve address
ip_addr_t addr;
err_t err = netconn_gethostbyname_addrtype(host, &addr, NETCONN_DNS_IPV4);
if (err != ERR_OK) {
return LWMQTT_NETWORK_FAILED_CONNECT;
}

// create new connection
network->conn = netconn_new(NETCONN_TCP);

// create new socket
err = netconn_connect(network->conn, &addr, (u16_t)port);
if (err != ERR_OK) {
return LWMQTT_NETWORK_FAILED_CONNECT;
}

return LWMQTT_SUCCESS;
}

void esp_lwmqtt_network_disconnect(esp_lwmqtt_network_t *network) {
// immediately return if conn is not set
if (network->conn == NULL) {
return;
}

// delete connection
netconn_delete(network->conn);
}

lwmqtt_err_t esp_lwmqtt_network_peek(lwmqtt_client_t *client, esp_lwmqtt_network_t *network, size_t *available) {
*available = (size_t)network->conn->recv_avail;
return LWMQTT_SUCCESS;
}

lwmqtt_err_t esp_lwmqtt_network_read(lwmqtt_client_t *client, void *ref, uint8_t *buffer, size_t len, size_t *read,
uint32_t timeout) {
// cast network reference
esp_lwmqtt_network_t *network = (esp_lwmqtt_network_t *)ref;

// prepare counter
size_t copied_len = 0;

// check if some data is left
if (network->rest_len > 0) {
// copy from rest buffer
netbuf_copy_partial(network->rest_buf, buffer, (u16_t)len,
(u16_t)(netbuf_len(network->rest_buf) - network->rest_len));

// check if there is still data left
if (network->rest_len > len) {
network->rest_len -= len;
*read += len;
return LWMQTT_SUCCESS;
}

// delete rest buffer
copied_len = network->rest_len;
netbuf_delete(network->rest_buf);
network->rest_len = 0;

// immediately return if we have enough
if (copied_len == len) {
*read += len;
return LWMQTT_SUCCESS;
}
}

// copied_len has the already written amount of data

// set timeout
netconn_set_recvtimeout(network->conn, timeout);

// receive data
struct netbuf *buf;
err_t err = netconn_recv(network->conn, &buf);
if (err == ERR_TIMEOUT) {
// return zero if timeout has been reached
*read += copied_len;
return LWMQTT_SUCCESS;
} else if (err != ERR_OK) {
return LWMQTT_NETWORK_FAILED_READ;
}

// get length
size_t bytes = netbuf_len(buf);

// copy data
netbuf_copy(buf, buffer + copied_len, len - copied_len);

// delete buffer and return bytes less or equal to the missing amount
if (copied_len + bytes <= len) {
netbuf_delete(buf);
*read += copied_len + bytes;
return LWMQTT_SUCCESS;
}

// otherwise save the rest and current offset
network->rest_buf = buf;
network->rest_len = bytes - (len - copied_len);

// adjust counter
*read += len;

return LWMQTT_SUCCESS;
}

lwmqtt_err_t esp_lwmqtt_network_write(lwmqtt_client_t *client, void *ref, uint8_t *buffer, size_t len, size_t *sent,
uint32_t timeout) {
// cast network reference
esp_lwmqtt_network_t *network = (esp_lwmqtt_network_t *)ref;

// set timeout
netconn_set_sendtimeout(network->conn, timeout);

// send data
err_t err = netconn_write(network->conn, buffer, len, NETCONN_COPY);
if (err != ERR_OK) {
return LWMQTT_NETWORK_FAILED_WRITE;
}

// adjust counter
*sent += len;

return LWMQTT_SUCCESS;
}
65 changes: 65 additions & 0 deletions src/cpp/sensor_monitor/esp32/components/esp-mqtt/esp_lwmqtt.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#ifndef ESP_LWMQTT_H
#define ESP_LWMQTT_H

#include <lwip/api.h>
#include <lwmqtt.h>

/**
* The lwmqtt timer object for the esp platform.
*/
typedef struct {
uint32_t deadline;
} esp_lwmqtt_timer_t;

/**
* The lwmqtt timer set callback for the esp platform.
*/
void esp_lwmqtt_timer_set(lwmqtt_client_t *client, void *ref, uint32_t timeout);

/**
* The lwmqtt timer get callback for the esp platform.
*/
uint32_t esp_lwmqtt_timer_get(lwmqtt_client_t *client, void *ref);

/**
* The lwmqtt network object for the esp platform.
*/
typedef struct {
struct netconn *conn;
struct netbuf *rest_buf;
size_t rest_len;
} esp_lwmqtt_network_t;

/**
* The initializer for the lwmqtt network object.
*/
#define esp_lwmqtt_default_network \
{ NULL, NULL, 0 }

/**
* Initiate a connection to the specified remote hose.
*/
lwmqtt_err_t esp_lwmqtt_network_connect(esp_lwmqtt_network_t *network, char *host, int port);

/**
* Terminate the connection.
*/
void esp_lwmqtt_network_disconnect(esp_lwmqtt_network_t *network);

/**
* Will set available to the available amount of data in the underlying network buffer.
*/
lwmqtt_err_t esp_lwmqtt_network_peek(lwmqtt_client_t *client, esp_lwmqtt_network_t *network, size_t *available);

/**
* The lwmqtt network read callback for the esp platform.
*/
lwmqtt_err_t esp_lwmqtt_network_read(lwmqtt_client_t *client, void *ref, uint8_t *buf, size_t len, size_t *read,
uint32_t timeout);
/**
* The lwmqtt network write callback for the esp platform.
*/
lwmqtt_err_t esp_lwmqtt_network_write(lwmqtt_client_t *client, void *ref, uint8_t *buf, size_t len, size_t *sent,
uint32_t timeout);

#endif // ESP_LWMQTT_H
Loading