Files
EMS20_handshake/src/mqtt_client_app.c
Mats van Reenen e1a0dbb5ab the final test
2020-11-08 15:00:49 +01:00

606 lines
20 KiB
C

/*
* Copyright (c) 2016, Texas Instruments Incorporated
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*****************************************************************************
Application Name - MQTT Client
Application Overview - The device is running a MQTT client which is
connected to the online broker. Three LEDs on the
device can be controlled from a web client by
publishing msg on appropriate topics. Similarly,
message can be published on pre-configured topics
by pressing the switch buttons on the device.
Application Details - Refer to 'MQTT Client' README.html
*****************************************************************************/
#include "mqtt_if.h"
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <mqueue.h>
#include <ti/drivers/net/wifi/simplelink.h>
#include <ti/drivers/net/wifi/slnetifwifi.h>
#include <ti/drivers/SPI.h>
// #include <ti/drivers/GPIO.h>
// #include <ti/drivers/Timer.h>
#include <ti/net/mqtt/mqttclient.h>
#include "network_if.h"
#include "uart_term.h"
#include "mqtt_if.h"
#include "debug_if.h"
#include "ti_drivers_config.h"
extern int32_t ti_net_SlNet_initConfig();
#define APPLICATION_NAME "Eindopdracht"
#define APPLICATION_VERSION "0.1.0"
#define SL_TASKSTACKSIZE 2048
#define SPAWN_TASK_PRIORITY 9
// un-comment this if you want to connect to an MQTT broker securely
//#define MQTT_SECURE_CLIENT
#define MQTT_MODULE_TASK_PRIORITY 2
#define MQTT_MODULE_TASK_STACK_SIZE 2048
#define MQTT_WILL_TOPIC "jesus_cc32xx_will_topic"
#define MQTT_WILL_MSG "will_msg_works"
#define MQTT_WILL_QOS MQTT_QOS_2
#define MQTT_WILL_RETAIN false
#define MQTT_CLIENT_PASSWORD NULL
#define MQTT_CLIENT_USERNAME NULL
#define MQTT_CLIENT_KEEPALIVE 0
#define MQTT_CLIENT_CLEAN_CONNECT true
#define MQTT_CLIENT_MQTT_V3_1 true
#define MQTT_CLIENT_BLOCKING_SEND true
#ifndef MQTT_SECURE_CLIENT
#define MQTT_CONNECTION_FLAGS MQTTCLIENT_NETCONN_URL
#define MQTT_CONNECTION_ADDRESS "mqtt.eclipse.org"
#define MQTT_CONNECTION_PORT_NUMBER 1883
#else
#define MQTT_CONNECTION_FLAGS MQTTCLIENT_NETCONN_IP4 | MQTTCLIENT_NETCONN_SEC
#define MQTT_CONNECTION_ADDRESS "192.168.178.67"
#define MQTT_CONNECTION_PORT_NUMBER 8883
#endif
mqd_t appQueue;
int connected;
int deinit;
int longPress = 0;
/* Client ID */
/* If ClientId isn't set, the MAC address of the device will be copied into */
/* the ClientID parameter. */
char ClientId[13] = {'\0'};
extern void MQTTCB_reply(char* topic, char* payload);
extern void MQTTCB_request(char* topic, char* payload);
enum{
APP_MQTT_PUBLISH,
APP_MQTT_CON_TOGGLE,
APP_MQTT_DEINIT,
APP_BTN_HANDLER
};
struct msgQueue
{
int event;
char* topic;
char* payload;
};
MQTT_IF_InitParams_t mqttInitParams =
{
MQTT_MODULE_TASK_STACK_SIZE, // stack size for mqtt module - default is 2048
MQTT_MODULE_TASK_PRIORITY // thread priority for MQTT - default is 2
};
MQTTClient_Will mqttWillParams =
{
MQTT_WILL_TOPIC, // will topic
MQTT_WILL_MSG, // will message
MQTT_WILL_QOS, // will QoS
MQTT_WILL_RETAIN // retain flag
};
MQTT_IF_ClientParams_t mqttClientParams =
{
ClientId, // client ID
MQTT_CLIENT_USERNAME, // user name
MQTT_CLIENT_PASSWORD, // password
MQTT_CLIENT_KEEPALIVE, // keep-alive time
MQTT_CLIENT_CLEAN_CONNECT, // clean connect flag
MQTT_CLIENT_MQTT_V3_1, // true = 3.1, false = 3.1.1
MQTT_CLIENT_BLOCKING_SEND, // blocking send flag
&mqttWillParams // will parameters
};
#ifndef MQTT_SECURE_CLIENT
MQTTClient_ConnParams mqttConnParams =
{
MQTT_CONNECTION_FLAGS, // connection flags
MQTT_CONNECTION_ADDRESS, // server address
MQTT_CONNECTION_PORT_NUMBER, // port number of MQTT server
0, // method for secure socket
0, // cipher for secure socket
0, // number of files for secure connection
NULL // secure files
};
#else
/*
* In order to connect to an MQTT broker securely, the MQTTCLIENT_NETCONN_SEC flag,
* method for secure socket, cipher, secure files, number of secure files must be set
* and the certificates must be programmed to the file system.
*
* The first parameter is a bit mask which configures the server address type and security mode.
* Server address type: IPv4, IPv6 and URL must be declared with the corresponding flag.
* All flags can be found in mqttclient.h.
*
* The flag MQTTCLIENT_NETCONN_SEC enables the security (TLS) which includes domain name
* verification and certificate catalog verification. Those verifications can be skipped by
* adding to the bit mask: MQTTCLIENT_NETCONN_SKIP_DOMAIN_NAME_VERIFICATION and
* MQTTCLIENT_NETCONN_SKIP_CERTIFICATE_CATALOG_VERIFICATION.
*
* Note: The domain name verification requires URL Server address type otherwise, this
* verification will be disabled.
*
* Secure clients require time configuration in order to verify the server certificate validity (date)
*/
/* Day of month (DD format) range 1-31 */
#define DAY 1
/* Month (MM format) in the range of 1-12 */
#define MONTH 5
/* Year (YYYY format) */
#define YEAR 2020
/* Hours in the range of 0-23 */
#define HOUR 4
/* Minutes in the range of 0-59 */
#define MINUTES 00
/* Seconds in the range of 0-59 */
#define SEC 00
char *MQTTClient_secureFiles[1] = {"ca-cert.pem"};
MQTTClient_ConnParams mqttConnParams =
{
MQTT_CONNECTION_FLAGS, // connection flags
MQTT_CONNECTION_ADDRESS, // server address
MQTT_CONNECTION_PORT_NUMBER, // port number of MQTT server
SLNETSOCK_SEC_METHOD_SSLv3_TLSV1_2, // method for secure socket
SLNETSOCK_SEC_CIPHER_FULL_LIST, // cipher for secure socket
1, // number of files for secure connection
MQTTClient_secureFiles // secure files
};
void setTime(){
SlDateTime_t dateTime = {0};
dateTime.tm_day = (uint32_t)DAY;
dateTime.tm_mon = (uint32_t)MONTH;
dateTime.tm_year = (uint32_t)YEAR;
dateTime.tm_hour = (uint32_t)HOUR;
dateTime.tm_min = (uint32_t)MINUTES;
dateTime.tm_sec = (uint32_t)SEC;
sl_DeviceSet(SL_DEVICE_GENERAL, SL_DEVICE_GENERAL_DATE_TIME,
sizeof(SlDateTime_t), (uint8_t *)(&dateTime));
}
#endif
//*****************************************************************************
//!
//! Set the ClientId with its own mac address
//! This routine converts the mac address which is given
//! by an integer type variable in hexadecimal base to ASCII
//! representation, and copies it into the ClientId parameter.
//!
//! \param macAddress - Points to string Hex.
//!
//! \return void.
//!
//*****************************************************************************
int32_t SetClientIdNamefromMacAddress()
{
int32_t ret = 0;
uint8_t Client_Mac_Name[2];
uint8_t Index;
uint16_t macAddressLen = SL_MAC_ADDR_LEN;
uint8_t macAddress[SL_MAC_ADDR_LEN];
/*Get the device Mac address */
ret = sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, 0, &macAddressLen,
&macAddress[0]);
/*When ClientID isn't set, use the mac address as ClientID */
if(ClientId[0] == '\0')
{
/*6 bytes is the length of the mac address */
for(Index = 0; Index < SL_MAC_ADDR_LEN; Index++)
{
/*Each mac address byte contains two hexadecimal characters */
/*Copy the 4 MSB - the most significant character */
Client_Mac_Name[0] = (macAddress[Index] >> 4) & 0xf;
/*Copy the 4 LSB - the least significant character */
Client_Mac_Name[1] = macAddress[Index] & 0xf;
if(Client_Mac_Name[0] > 9)
{
/*Converts and copies from number that is greater than 9 in */
/*hexadecimal representation (a to f) into ascii character */
ClientId[2 * Index] = Client_Mac_Name[0] + 'a' - 10;
}
else
{
/*Converts and copies from number 0 - 9 in hexadecimal */
/*representation into ascii character */
ClientId[2 * Index] = Client_Mac_Name[0] + '0';
}
if(Client_Mac_Name[1] > 9)
{
/*Converts and copies from number that is greater than 9 in */
/*hexadecimal representation (a to f) into ascii character */
ClientId[2 * Index + 1] = Client_Mac_Name[1] + 'a' - 10;
}
else
{
/*Converts and copies from number 0 - 9 in hexadecimal */
/*representation into ascii character */
ClientId[2 * Index + 1] = Client_Mac_Name[1] + '0';
}
}
}
return(ret);
}
void MQTT_EventCallback(int32_t event){
struct msgQueue queueElement;
switch(event){
case MQTT_EVENT_CONNACK:
{
deinit = 0;
connected = 1;
LOG_INFO("MQTT_EVENT_CONNACK\r\n");
// GPIO_clearInt(CONFIG_GPIO_BUTTON_1);
// GPIO_enableInt(CONFIG_GPIO_BUTTON_1);
break;
}
case MQTT_EVENT_SUBACK:
{
LOG_INFO("MQTT_EVENT_SUBACK\r\n");
break;
}
case MQTT_EVENT_PUBACK:
{
LOG_INFO("MQTT_EVENT_PUBACK\r\n");
break;
}
case MQTT_EVENT_UNSUBACK:
{
LOG_INFO("MQTT_EVENT_UNSUBACK\r\n");
break;
}
case MQTT_EVENT_CLIENT_DISCONNECT:
{
connected = 0;
LOG_INFO("MQTT_EVENT_CLIENT_DISCONNECT\r\n");
if(deinit == 0){
// GPIO_clearInt(CONFIG_GPIO_BUTTON_1);
// GPIO_enableInt(CONFIG_GPIO_BUTTON_1);
}
break;
}
case MQTT_EVENT_SERVER_DISCONNECT:
{
connected = 0;
LOG_INFO("MQTT_EVENT_SERVER_DISCONNECT\r\n");
queueElement.event = APP_MQTT_CON_TOGGLE;
int res = mq_send(appQueue, (const char*)&queueElement, sizeof(struct msgQueue), 0);
if(res < 0){
LOG_ERROR("msg queue send error %d", res);
}
break;
}
case MQTT_EVENT_DESTROY:
{
LOG_INFO("MQTT_EVENT_DESTROY\r\n");
break;
}
}
}
int32_t DisplayAppBanner(char* appName, char* appVersion){
int32_t ret = 0;
uint8_t macAddress[SL_MAC_ADDR_LEN];
uint16_t macAddressLen = SL_MAC_ADDR_LEN;
uint16_t ConfigSize = 0;
uint8_t ConfigOpt = SL_DEVICE_GENERAL_VERSION;
SlDeviceVersion_t ver = {0};
ConfigSize = sizeof(SlDeviceVersion_t);
// get the device version info and MAC address
ret = sl_DeviceGet(SL_DEVICE_GENERAL, &ConfigOpt, &ConfigSize, (uint8_t*)(&ver));
ret |= (int32_t)sl_NetCfgGet(SL_NETCFG_MAC_ADDRESS_GET, 0, &macAddressLen, &macAddress[0]);
UART_PRINT("\n\r\t============================================\n\r");
UART_PRINT("\t %s V%s",appName, appVersion);
UART_PRINT("\n\r\t============================================\n\r\n\r");
UART_PRINT("\t CHIP: 0x%x\n\r",ver.ChipId);
UART_PRINT("\t MAC: %d.%d.%d.%d\n\r",ver.FwVersion[0],ver.FwVersion[1],
ver.FwVersion[2],
ver.FwVersion[3]);
UART_PRINT("\t PHY: %d.%d.%d.%d\n\r",ver.PhyVersion[0],ver.PhyVersion[1],
ver.PhyVersion[2],
ver.PhyVersion[3]);
UART_PRINT("\t NWP: %d.%d.%d.%d\n\r",ver.NwpVersion[0],ver.NwpVersion[1],
ver.NwpVersion[2],
ver.NwpVersion[3]);
UART_PRINT("\t ROM: %d\n\r",ver.RomVersion);
UART_PRINT("\t HOST: %s\n\r", SL_DRIVER_VERSION);
UART_PRINT("\t MAC address: %02x:%02x:%02x:%02x:%02x:%02x\r\n", macAddress[0],
macAddress[1], macAddress[2], macAddress[3], macAddress[4],
macAddress[5]);
UART_PRINT("\n\r\t============================================\n\r");
return(ret);
}
int WifiInit(){
int32_t ret;
SlWlanSecParams_t security_params;
pthread_t spawn_thread = (pthread_t) NULL;
pthread_attr_t pattrs_spawn;
struct sched_param pri_param;
pthread_attr_init(&pattrs_spawn);
pri_param.sched_priority = SPAWN_TASK_PRIORITY;
ret = pthread_attr_setschedparam(&pattrs_spawn, &pri_param);
ret |= pthread_attr_setstacksize(&pattrs_spawn, SL_TASKSTACKSIZE);
ret |= pthread_attr_setdetachstate(&pattrs_spawn, PTHREAD_CREATE_DETACHED);
ret = pthread_create(&spawn_thread, &pattrs_spawn, sl_Task, NULL);
if(ret != 0){
LOG_ERROR("could not create simplelink task");
while(1);
}
Network_IF_ResetMCUStateMachine();
Network_IF_DeInitDriver();
ret = Network_IF_InitDriver(ROLE_STA);
if(ret < 0){
LOG_ERROR("Failed to start SimpleLink Device");
while(1);
}
DisplayAppBanner(APPLICATION_NAME, APPLICATION_VERSION);
SetClientIdNamefromMacAddress();
security_params.Key = (signed char*)SECURITY_KEY;
security_params.KeyLen = strlen(SECURITY_KEY);
security_params.Type = SECURITY_TYPE;
ret = Network_IF_ConnectAP(SSID_NAME, security_params);
if(ret < 0){
LOG_ERROR("Connection to an AP failed");
}
else{
SlWlanSecParams_t securityParams;
securityParams.Type = SECURITY_TYPE;
securityParams.Key = (signed char*)SECURITY_KEY;
securityParams.KeyLen = strlen((const char *)securityParams.Key);
ret = sl_WlanProfileAdd((signed char*)SSID_NAME, strlen(SSID_NAME), 0, &securityParams, NULL, 7, 0);
if(ret < 0){
LOG_ERROR("failed to add profile %s", SSID_NAME);
}
else{
LOG_INFO("profile added %s", SSID_NAME);
}
}
return ret;
}
void MQTTPublish(char * topic, char * payload){
struct msgQueue queueElement;
queueElement.event = APP_MQTT_PUBLISH;
queueElement.topic = topic;
queueElement.payload = payload;
int res = mq_send(appQueue, (const char*)&queueElement, sizeof(struct msgQueue), 0);
}
// void MQTTSubscribe(char* topic, void *cb(char* topic, char* payload)){
// uint8_t ret = MQTT_IF_Subscribe(0, topic, MQTT_QOS_2, cb);
// }
void MQTTTask(void * args){
int32_t ret;
UART_Handle uartHandle;
struct msgQueue queueElement;
uartHandle = InitTerm();
UART_control(uartHandle, UART_CMD_RXDISABLE, NULL);
SPI_init();
ret = ti_net_SlNet_initConfig();
if(0 != ret)
{
LOG_ERROR("Failed to initialize SlNetSock");
}
mq_attr attr;
attr.mq_maxmsg = 10;
attr.mq_msgsize = sizeof(struct msgQueue);
appQueue = mq_open("appQueue", O_CREAT, 0, &attr);
if(((int)appQueue) <= 0){
while(1);
}
ret = WifiInit();
if(ret < 0){
while(1);
}
ret = MQTT_IF_Init(mqttInitParams);
if(ret < 0){
while(1);
}
#ifdef MQTT_SECURE_CLIENT
setTime();
#endif
MQTTClient_Handle mqttClientHandle;
/*
* In case a persistent session is being used, subscribe is called before connect so that the module
* is aware of the topic callbacks the user is using. This is important because if the broker is holding
* messages for the client, after CONNACK the client may receive the messages before the module is aware
* of the topic callbacks. The user may still call subscribe after connect but have to be aware of this.
*/
ret = 0;
ret |= MQTT_IF_Subscribe(mqttClientHandle, "ems20/handshake/0964590/reply", MQTT_QOS_2, &MQTTCB_reply);
ret |= MQTT_IF_Subscribe(mqttClientHandle, "ems20/handshake/0971472/request", MQTT_QOS_2, &MQTTCB_request);
if(ret < 0){
LOG_ERROR("Faild to Subscribed to topics\r\n");
while(1);
}
else{
LOG_INFO("Subscribed to all topics successfully\r\n");
}
mqttClientHandle = MQTT_IF_Connect(mqttClientParams, mqttConnParams, MQTT_EventCallback);
if(mqttClientHandle < 0){
while(1);
}
// wait for CONNACK
while(connected == 0);
// GPIO_enableInt(CONFIG_GPIO_BUTTON_0);
while(1){
mq_receive(appQueue, (char*)&queueElement, sizeof(struct msgQueue), NULL);
if(queueElement.event == APP_MQTT_PUBLISH){
LOG_TRACE("APP_MQTT_PUBLISH");
MQTT_IF_Publish(mqttClientHandle,
queueElement.topic,
queueElement.payload,
strlen(queueElement.payload),
MQTT_QOS_2);
}
else if(queueElement.event == APP_MQTT_CON_TOGGLE){
LOG_TRACE("APP_MQTT_CON_TOGGLE %d", connected);
if(connected){
ret = MQTT_IF_Disconnect(mqttClientHandle);
if(ret >= 0){
connected = 0;
}
}
else{
mqttClientHandle = MQTT_IF_Connect(mqttClientParams, mqttConnParams, MQTT_EventCallback);
if((int)mqttClientHandle >= 0){
connected = 1;
}
}
}
else if(queueElement.event == APP_BTN_HANDLER){
LOG_TRACE("APP_BTN_HANDLER: does nothing");
// struct msgQueue queueElement;
// ret = detectLongPress();
// if(ret == 0){
// LOG_TRACE("APP_BTN_HANDLER SHORT PRESS\r\n");
// queueElement.event = APP_MQTT_CON_TOGGLE;
// }
// else{
// LOG_TRACE("APP_BTN_HANDLER LONG PRESS\r\n");
// queueElement.event = APP_MQTT_DEINIT;
// }
// ret = mq_send(appQueue, (const char*)&queueElement, sizeof(struct msgQueue), 0);
// if(ret < 0){
// LOG_ERROR("msg queue send error %d", ret);
// }
}
}
}
//*****************************************************************************
//
// Close the Doxygen group.
//! @}
//
//*****************************************************************************