From 113ff245093457bc34bd27822568569453d5fe60 Mon Sep 17 00:00:00 2001 From: Nathael Pajani Date: Sun, 10 Mar 2019 13:38:18 +0100 Subject: [PATCH] Rename publisher example, in order to differentiate from subscriber one --- mqtt_pub/Makefile | 21 +++ mqtt_pub/main.c | 398 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 419 insertions(+) create mode 100644 mqtt_pub/Makefile create mode 100644 mqtt_pub/main.c diff --git a/mqtt_pub/Makefile b/mqtt_pub/Makefile new file mode 100644 index 0000000..41ae555 --- /dev/null +++ b/mqtt_pub/Makefile @@ -0,0 +1,21 @@ +# Makefile for apps + +MODULE = $(shell basename $(shell cd .. && pwd && cd -)) +NAME = $(shell basename $(CURDIR)) + +# Add this to your ~/.vimrc in order to get proper function of :make in vim : +# let $COMPILE_FROM_IDE = 1 +ifeq ($(strip $(COMPILE_FROM_IDE)),) + PRINT_DIRECTORY = --no-print-directory +else + PRINT_DIRECTORY = + LANG = C +endif + +.PHONY: $(NAME).bin +$(NAME).bin: + @make -C ../../.. ${PRINT_DIRECTORY} NAME=$(NAME) MODULE=$(MODULE) apps/$(MODULE)/$(NAME)/$@ + +clean mrproper: + @make -C ../../.. ${PRINT_DIRECTORY} $@ + diff --git a/mqtt_pub/main.c b/mqtt_pub/main.c new file mode 100644 index 0000000..e6b73a4 --- /dev/null +++ b/mqtt_pub/main.c @@ -0,0 +1,398 @@ +/**************************************************************************** + * apps/base/mqtt/main.c + * + * MQTT client example using data from onboard TMP101 I2C temperature sensor + * + * Copyright 2013-2014 Nathael Pajani + * + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + *************************************************************************** */ + + +#include "core/system.h" +#include "core/systick.h" +#include "core/pio.h" + +#include "lib/stdio.h" +#include "lib/errno.h" +#include "lib/utils.h" +#include "lib/protocols/mqtt.h" + +#include "drivers/i2c.h" +#include "drivers/serial.h" +#include "drivers/gpio.h" + +#include "extdrv/status_led.h" +#include "extdrv/tmp101_temp_sensor.h" + + +#define MODULE_VERSION 0x04 +#define MODULE_NAME "GPIO Demo Module" + +#define APP_BOARD_ADDRESS 0x0102 + +#define SELECTED_FREQ FREQ_SEL_48MHz + +/***************************************************************************** */ +/* Pins configuration */ +/* pins blocks are passed to set_pins() for pins configuration. + * Unused pin blocks can be removed safely with the corresponding set_pins() call + * All pins blocks may be safelly merged in a single block for single set_pins() call.. + */ +const struct pio_config common_pins[] = { + /* UART 0 */ + { LPC_UART0_RX_PIO_0_1, LPC_IO_DIGITAL }, + { LPC_UART0_TX_PIO_0_2, LPC_IO_DIGITAL }, + /* I2C 0 */ + { LPC_I2C0_SCL_PIO_0_10, (LPC_IO_DIGITAL | LPC_IO_OPEN_DRAIN_ENABLE) }, + { LPC_I2C0_SDA_PIO_0_11, (LPC_IO_DIGITAL | LPC_IO_OPEN_DRAIN_ENABLE) }, + ARRAY_LAST_PIO, +}; + +const struct pio status_led_green = LPC_GPIO_1_4; +const struct pio status_led_red = LPC_GPIO_1_5; + +/***************************************************************************** */ +/* Temperature */ +/* The I2C Temperature sensor is at address 0x94 */ +#define TMP101_ADDR 0x94 /* Pin Addr0 (pin5 of tmp101) connected to VCC */ +struct tmp101_sensor_config tmp101_sensor = { + .bus_num = I2C0, + .addr = TMP101_ADDR, + .resolution = TMP_RES_ELEVEN_BITS, +}; + +void temp_config(int uart_num) +{ + int ret = 0; + + /* Temp sensor */ + ret = tmp101_sensor_config(&tmp101_sensor); + if (ret != 0) { + uprintf(uart_num, "Temp config error: %d\n", ret); + } +} + +int temp_read(int uart_num) +{ + uint16_t raw = 0; + int deci_degrees = 0; + int ret = 0; + + tmp101_sensor_start_conversion(&tmp101_sensor); + msleep(250); /* Wait for the end of the conversion : 40ms */ + ret = tmp101_sensor_read(&tmp101_sensor, &raw, &deci_degrees); + if (ret != 0) { + uprintf(uart_num, "Temp read error: %d\n", ret); + } else { + uprintf(uart_num, "Temp read: %d,%d - raw: 0x%04x.\r\n", + (deci_degrees/10), (deci_degrees%10), raw); + } + return deci_degrees; +} + +/***************************************************************************** */ +/* MQTT protocol */ + +/* Our MQTT buffer. MQTT packets may be up to 2^28 bytes, but we will keep them + * very small for our needs */ +#define MQTT_BUFF_SIZE 62 +#define FIRST_PACKET_CHAR '#' +uint8_t txbuf[MQTT_BUFF_SIZE]; +uint16_t app_board_addr = APP_BOARD_ADDRESS; + +/* This is our static connect data */ +const struct mqtt_connect_pkt mqtt_conn = { + .keep_alive_seconds = 600, + .clean_session_flag = MQTT_SESSION_RESUME, + .client_id = "test", + .will_topic = "will/temp/test", + .will_msg_size = 4, + .will_msg = (uint8_t*)"Bye", + .will_QoS = 0, + .will_retain = 1, + .username = "test", + .password = "pass", +}; + +#define HEADER_SIZE sizeof(struct app_header) +struct app_header { + uint8_t start; /* '#' */ + uint8_t type; /* 'M' for MQTT messages */ + uint16_t addr; + uint8_t seqnum; + uint8_t header_cksum; + uint8_t data_len; + uint8_t data_cksum; +}; + +/* Possible states for MQTT communication flow */ +enum mqtt_client_states { + MQTT_UNCONNECTED, + MQTT_IDLE, + MQTT_WAITING_CONNECT_ACK, + MQTT_WAITING_PUBACK, + MQTT_WAITING_PUBREC, + MQTT_WAITING_PUBREL, + MQTT_WAITING_PUBCOMP, + MQTT_WAITING_SUBACK, + MQTT_WAITING_UNSUBACK, + MQTT_WAITING_PINGRESP, +}; +uint8_t mqtt_comm_state = MQTT_UNCONNECTED; + + +void add_packet_header(int pkt_len) +{ + struct app_header* header = (struct app_header*)txbuf; + uint8_t i = 0, cksum = 0; + + /* Compute data checksum */ + for (i = HEADER_SIZE; i < (HEADER_SIZE + pkt_len); i++) { + cksum += txbuf[i]; + } + + /* Add the header */ + header->start = FIRST_PACKET_CHAR; + header->type = 'M'; + header->addr = htons(app_board_addr); + header->seqnum = 0; + header->data_len = pkt_len; + header->data_cksum = cksum; + /* Compute header chksum */ + cksum = 0; + for (i = 0; i < HEADER_SIZE; i++) { + cksum += txbuf[i]; + } + header->header_cksum = (uint8_t)(256 - cksum); +} + +int mqtt_init(int comm_uart, int dbg_uart) +{ + int len = 0, ret = 0; + + memset(txbuf, 0, MQTT_BUFF_SIZE); + /* Create the MQTT connect packet */ + len = mqtt_pack_connect_packet(&mqtt_conn, (txbuf + HEADER_SIZE), (MQTT_BUFF_SIZE - HEADER_SIZE)); + if (len <= 0) { + uprintf(dbg_uart, "MQTT connect pkt pack error : %d\n", len); + return -E2BIG; + } + /* Add our packet header */ + add_packet_header(len); + + /* Send connect MQTT packet */ + ret = serial_write(comm_uart, (char*)txbuf, (len + HEADER_SIZE)); + if (ret < 0) { + uprintf(dbg_uart, "MQTT send error: %d\n", ret); + return ret; + } + mqtt_comm_state = MQTT_WAITING_CONNECT_ACK; + return 0; +} + + +struct mqtt_publish_pkt pub_pkt = { + .topic = "temp/test", + .QoS = 1, + .retain_flag = 1, + .message_size = sizeof(int), +}; +static uint16_t pub_packet_id = 1; + +int mqtt_temp_publish(int comm_uart, int dbg_uart, int temp) +{ + int len = 0, ret = 0; + + memset(txbuf, 0, MQTT_BUFF_SIZE); + /* Create the MQTT publish packet */ + pub_pkt.packet_id = pub_packet_id; + pub_pkt.application_message = (uint8_t*)&temp; + len = mqtt_pack_publish_packet(&pub_pkt, (txbuf + HEADER_SIZE), (MQTT_BUFF_SIZE - HEADER_SIZE)); + if (len <= 0) { + uprintf(dbg_uart, "MQTT publish pkt pack error : %d\n", len); + return -E2BIG; + } + /* Add our packet header */ + add_packet_header(len); + + /* Send publish MQTT packet */ + ret = serial_write(comm_uart, (char*)txbuf, (len + HEADER_SIZE)); + if (ret < 0) { + uprintf(dbg_uart, "MQTT send error: %d\n", ret); + return ret; + } + mqtt_comm_state = MQTT_WAITING_PUBACK; + return 0; +} + + +int mqtt_handle_packet(char* buf, int comm_uart, int dbg_uart) +{ + struct app_header* header = (struct app_header*)buf; + int ret = 0; + + /* Decode address */ + header->addr = ntohs(header->addr); + if ((!buf) || (header->addr != APP_BOARD_ADDRESS)) { + /* This one is not for us, drop it */ + uprintf(dbg_uart, "Dropping packet, not for us\n"); + return -1; + } + if (header->type != 'M') { + uprintf(dbg_uart, "Dropping packet, not MQTT\n"); + return -2; + } + /* This is an MQTT packet for us ... handle it */ + switch (mqtt_comm_state) { + case MQTT_WAITING_CONNECT_ACK: { + /* We must not receive anything before the connect acknowledge */ + struct mqtt_connack_response_pkt* response = (struct mqtt_connack_response_pkt*)(buf + HEADER_SIZE); + ret = mqtt_check_connack_response_pkt(response); + if (ret != 0) { + uprintf(dbg_uart, "Not a connack packet (ret: %d) ... protocol flow error\n", ret); + return -3; + } + /* Valid packet, check return code */ + if (response->ret_code == MQTT_CONNACK_ACCEPTED) { + uprintf(dbg_uart, "Connection accepted\n"); + mqtt_comm_state = MQTT_IDLE; + } else { + uprintf(dbg_uart, "Connection refused: %d\n", response->ret_code); + mqtt_comm_state = MQTT_UNCONNECTED; + } + break; + } + case MQTT_WAITING_PUBACK: { + struct mqtt_publish_response_pkt* response = (struct mqtt_publish_response_pkt*)(buf + HEADER_SIZE); + ret = mqtt_check_publish_response_pkt(response, MQTT_WAITING_PUBACK); + if (ret != 0) { + uprintf(dbg_uart, "Not a connack packet (ret: %d) ... protocol flow error\n", ret); + return -3; + } + mqtt_comm_state = MQTT_IDLE; + break; + } + case MQTT_WAITING_PUBREC: + case MQTT_WAITING_PUBREL: + case MQTT_WAITING_PUBCOMP: + case MQTT_WAITING_SUBACK: + case MQTT_WAITING_UNSUBACK: + case MQTT_WAITING_PINGRESP: + break; + } + return 0; +} + + +uint8_t rx_packets[2][MQTT_BUFF_SIZE]; +volatile uint8_t* rxbuf = rx_packets[0]; +volatile uint8_t* packet_ok = NULL; +void data_rx(uint8_t c) +{ + static uint8_t idx = 0; + static uint8_t sum = 0; + /* Not receiving a packet yet, wait for FIRST_PACKET_CHAR, drop */ + if ((idx == 0) && (c != FIRST_PACKET_CHAR)) { + return; + } + rxbuf[idx++] = c; + sum += c; + /* If header received, make sure checksum is OK */ + if (idx == HEADER_SIZE) { + uint8_t start = 1; + if (sum == 0) { + /* Header received and checksum OK */ + return; + } + /* Shift buffer content if buffer holds a FIRST_PACKET_CHAR */ + while ((rxbuf[start] != FIRST_PACKET_CHAR) && (start <= HEADER_SIZE)) { + start++; + } + idx = 0; /* Restart at 0 (and if no FIRST_PACKET_CHAR found, this drops everything */ + sum = 0; + /* FIRST_PACKET_CHAR found ? */ + while (start < HEADER_SIZE) { + rxbuf[idx] = rxbuf[start++]; + sum += rxbuf[idx]; + idx++; + } + } else if (idx > HEADER_SIZE) { + struct app_header* header = (struct app_header*)rxbuf; + /* Header received, check for data part */ + if (idx == (HEADER_SIZE + header->data_len)) { + /* Full packet received, move to next packet */ + if (sum == header->data_cksum) { + packet_ok = rxbuf; + if (rxbuf == rx_packets[0]) { + rxbuf = rx_packets[1]; + } else { + rxbuf = rx_packets[0]; + } + } + idx = 0; + sum = 0; + } + } +} + +/***************************************************************************** */ +void system_init() +{ + /* Stop the watchdog */ + startup_watchdog_disable(); /* Do it right now, before it gets a chance to break in */ + system_brown_out_detection_config(0); /* No ADC used */ + system_set_default_power_state(); + clock_config(SELECTED_FREQ); + set_pins(common_pins); + gpio_on(); + status_led_config(&status_led_green, &status_led_red); + /* System tick timer MUST be configured and running in order to use the sleeping + * functions */ + systick_timer_on(1); /* 1ms */ + systick_start(); +} + + +/***************************************************************************** */ +int main(void) +{ + int temp = 0, loop = 0; + + system_init(); + uart_on(UART0, 115200, data_rx); + i2c_on(I2C0, I2C_CLK_100KHz, I2C_MASTER); + + /* Configure onboard temp sensor */ + temp_config(UART0); + mqtt_init(UART0, UART0); + + while (1) { + /* Check for received packet on serial line and handle them */ + if (packet_ok != NULL) { + int ret = mqtt_handle_packet((char*)packet_ok, UART0, UART0); + packet_ok = NULL; + } + chenillard(250); + if (loop++ >= 10) { + temp = temp_read(UART0); + mqtt_temp_publish(UART0, UART0, temp); + loop = 0; + } + } + return 0; +} + -- 2.43.0