Example project to publish messages to a MQTT-SN broker using the u-blox SARA-N200 NB-IoT modem

Dependencies:   MQTTSNPacket X-NUCLEO-SARA-N200

main.cpp

Committer:
KeystoneElectronic
Date:
2018-08-23
Revision:
12:9a2dab9b927d
Parent:
7:ab32680de141

File content as of revision 12:9a2dab9b927d:

#include <stdio.h>
#include <Serial.h>

#include "mbed.h"
#include "sara_n2.h"
#include "MQTTmbed.h"
#include "MQTTSNUDP.h"
#include "MQTTSNClient.h"

Serial pc(SERIAL_TX, SERIAL_RX, 115200);
DigitalOut myled(LED1);
InterruptIn button(USER_BUTTON);
UARTSerial sara(PA_9, PA_10, 9600);
DigitalOut sara_reset(D7);

//#define INFO_TRACE(_class, _string, ...)    printf( "%8s: " _string, _class, ##__VA_ARGS__)
#undef TRACE
#define TRACE(_string, ...)    INFO_TRACE( "MQTT", _string,  ##__VA_ARGS__ )

float led_flash_rate = 0.5;

void messageArrived(MQTTSN::MessageData& md)
{
    MQTTSN::Message &message = md.message;
    TRACE("Message arrived: qos %d, retained %d, dup %d, packetid %d\n",
    		message.qos,
			message.retained,
			message.dup,
			message.id);
    char *payload = (char*)message.payload;
    payload[message.payloadlen] = 0;

    TRACE("Payload %s\n", payload);
    char *ptr;
    float new_rate = strtof((const char*)payload, &ptr);
    if(new_rate > 0)
    {
    	TRACE("New rate %f\n", new_rate);
    	led_flash_rate = new_rate;
    }
}

enum eMQTTstates
{
	MQTT_SOCKET_DISCONNECTED,
	MQTT_SOCKET_CONNECTED,
	MQTT_CLIENT_CONNECTED,
	MQTT_CLIENT_PUBLISH,
	MQTT_CLIENT_SUBSCRIBED
}mMQTTstate;


SARA_N2 sara_mdm(&sara, &sara_reset);
MQTTSNUDP ipsocket = MQTTSNUDP(&sara_mdm);
MQTTSNPacket_connectData data = MQTTSNPacket_connectData_initializer;
MQTTSN_topicid topicid;
MQTTSN::QoS grantedQoS;
char topicString[64];
char publishMessage[32];
bool buttonPressed = false;
int aliveCount = 0;
int colorIndex = 0;
char sendBuffer[512];

char *colorNames[] =
{
		"red",
		"green",
		"yellow",
		"blue",
		"grey"
};

void fillMessage(char *msg)
{
	char temp[64];

	sprintf(msg, "{\"IMEA\":\"%s\",", sara_mdm.getIMEA());
	sprintf(temp, "\"SIM\":\"%s\",",  sara_mdm.getSIMserial());
	strcat(msg, temp);
	sprintf(temp, "\"message\":\"%s\",", publishMessage);
	strcat(msg, temp);
	sprintf(temp, "\"color\":\"%s\",", colorNames[colorIndex]);
	strcat(msg, temp);
	sprintf(temp, "\"alive\":%d}", aliveCount);
	strcat(msg, temp);
}

void mqtt_fsm(MQTTSN::Client<MQTTSNUDP, Countdown> *client)
{
	static int pub_count = 0;
	switch(mMQTTstate)
	{
	case MQTT_SOCKET_DISCONNECTED:
	{
		const char* hostname = MBED_CONF_APP_MQTT_SN_HOST;
		int port = MBED_CONF_APP_MQTT_SN_PORT;
		TRACE("Connecting to %s:%d\n", hostname, port);
		int socket  = ipsocket.connect((char*)hostname, port);
		if(socket >= 0)
		{
			TRACE("Socket connected - %d\n", socket);
			mMQTTstate = MQTT_SOCKET_CONNECTED;
		}
	}
	break;

	case MQTT_SOCKET_CONNECTED:
	{
		data.clientID.cstring = (char*)"NUCLEO_NB-IoT";
		data.duration = 100;
		int rc = client->connect(data);
		TRACE("Connect - %d\n", rc);
		if(rc == MQTTSN::SUCCESS)
		{
			printf("Client Connected\n");
			mMQTTstate = MQTT_CLIENT_CONNECTED;
		}
	}
	break;
	case MQTT_CLIENT_CONNECTED:
	{
		topicid.type = MQTTSN_TOPIC_TYPE_NORMAL;
		topicid.data.long_.name = topicString;
		topicid.data.long_.len = strlen(topicString);
		int rc = client->subscribe(topicid, MQTTSN::QOS1, grantedQoS, messageArrived);
		TRACE("Subscribe - %d\n", rc);
		if(rc == MQTTSN::SUCCESS)
		{
			printf("Client Subscribed\n");
			mMQTTstate = MQTT_CLIENT_PUBLISH;
		}
	}
	break;
	case MQTT_CLIENT_PUBLISH:
		{
			pub_count = 0;

			fillMessage(sendBuffer);

			MQTTSN::Message message;
			message.qos = MQTTSN::QOS0;
			message.retained = false;
			message.dup = false;
			message.payload = (void*)sendBuffer;
			message.payloadlen = strlen(sendBuffer);
			int rc = client->publish(topicid, message);
			if(rc == MQTTSN::SUCCESS)
			{
				TRACE("Publishes %s\n", sendBuffer);
			}

			mMQTTstate = MQTT_CLIENT_SUBSCRIBED;
		}
		break;
	case MQTT_CLIENT_SUBSCRIBED:
	{
		client->yield(100);

		if(buttonPressed)
		{
			buttonPressed = false;
			mMQTTstate = MQTT_CLIENT_PUBLISH;

			sprintf(publishMessage, "Color changed");
			if(++colorIndex > 4)
				colorIndex = 0;
		}

		if(pub_count++ > 100)
		{
			mMQTTstate = MQTT_CLIENT_PUBLISH;
			sprintf(publishMessage, "X-Nucleo is alive");

			aliveCount++;
		}

	}
	break;
	}
}

void pressedEvent()
{
	buttonPressed = true;
}

int main(void)
{
	printf("\n\nNUCLEO_X_SARA-N200 HelloMQTT-SN\n");
	printf("Version: 0x%08X\n", MBED_CONF_APP_VERSION);
	printf("mbed-os: %d.%d.%d\n", MBED_MAJOR_VERSION, MBED_MINOR_VERSION, MBED_PATCH_VERSION);

	strcpy(topicString, MBED_CONF_APP_TOPIC);
	sprintf(publishMessage, "NUCLEO NB-IoT online");
	MQTTSN::Client<MQTTSNUDP, Countdown> client = MQTTSN::Client<MQTTSNUDP, Countdown>(ipsocket);

	button.fall(&pressedEvent);

	while(1)
	{
		wait(led_flash_rate);
		myled = 1;
		wait(led_flash_rate);
		myled = 0;

		sara_mdm.fsm();
		mqtt_fsm(&client);
	}


	return 0;
}