simple-mqtt-msp432-example/simple-mqtt-msp432-example.ino

272 lines
7.1 KiB
C++

#define MQTTCLIENT_QOS2 1
// LEDS
#define RED RED_LED
#define GRE GREEN_LED
#define BLU BLUE_LED
// msp432P401R specific pins for second led and right and left buttons
#define ERRORLED 78
#define LEFT 74
#define RIGHT 73
#include <SPI.h>
#include <WiFi.h>
#include <WifiIPStack.h>
#include <Countdown.h>
#include <MQTTClient.h>
#include <pthread.h>
// Network Config - REPLACE WITH SSID
char ssid[] = "wifiSSid";
// Network Password - REPLACE WITH REAL PASSWORD
char password[] = "realpass";
// MQTT Server info - REPLACE WITH REAL HOST NAME
char hostname[] = "host name!";
const int port = 1883;
const int serialbaud = 115200;
char printbuf[100];
int arrivedcount = 0;
int connectionErrors = 0;
// Simple logging of recevied messages on serial port
void logMessage(MQTT::Message& message)
{
sprintf(printbuf, "Message %d arrived: qos %d, retained %d, dup %d, packetid %d\n",
++arrivedcount, message.qos, message.retained, message.dup, message.id);
Serial.print(printbuf);
sprintf(printbuf, "Payload %s\n", (char*)message.payload);
Serial.print(printbuf);
}
// Callback when a request to change led color has arrived from broker
void colorArrived(MQTT::MessageData& md)
{
MQTT::Message &message = md.message;
logMessage(message);
// Consider only messages with 3 characters - one for each of RGB
if (message.payloadlen == 3) {
bool red = ((char*)message.payload)[0] - '0';
bool green = ((char*)message.payload)[1] - '0';
bool blue = ((char*)message.payload)[2] - '0';
digitalWrite(RED, red ? HIGH : LOW);
digitalWrite(GRE, green ? HIGH : LOW);
digitalWrite(BLU, blue ? HIGH : LOW);
} else {
sprintf(printbuf, "Bad payload: %s\n", (char*)message.payload);
Serial.print(printbuf);
}
}
// Callback when a request to disable error notification led has arrived from broker
void errorOverrideArrived(MQTT::MessageData& md) {
MQTT::Message &message = md.message;
logMessage(message);
fixError();
}
WifiIPStack ipstack;
MQTT::Client<WifiIPStack, Countdown> client = MQTT::Client<WifiIPStack, Countdown>(ipstack);
// Topics used - publishing to sensors and subscribing to controls
char* ledControlTopic = "devices/red/controls/led";
char* errorControlTopic = "devices/red/controls/error";
char* leftSensorTopic = "devices/red/sensors/left";
char* rightSensorTopic = "devices/red/sensors/right";
char* wifiSensorTopic = "devices/red/sensors/wifi";
// Counter for conection errors to turn on error notification led
void onConnectionError() {
connectionErrors++;
if (connectionErrors >= 3) {
// Light up red LED
digitalWrite(ERRORLED, HIGH);
} else {
// Keep LED off
digitalWrite(ERRORLED, LOW);
}
}
// Clear error notification led
void fixError() {
connectionErrors = 0;
// Keep LED off
digitalWrite(ERRORLED, LOW);
}
// Connection to MQTT broker
void connect()
{
sprintf(printbuf, "Connecting to %s:%d\n", hostname, port);
Serial.print(printbuf);
int rc = ipstack.connect(hostname, port);
if (rc != 1)
{
sprintf(printbuf, "rc from TCP connect is %d\n", rc);
Serial.print(printbuf);
onConnectionError();
}
Serial.println("MQTT connecting");
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.MQTTVersion = 3;
data.clientID.cstring = (char*)"red";
rc = client.connect(data);
if (rc != 0)
{
sprintf(printbuf, "rc from MQTT connect is %d\n", rc);
Serial.print(printbuf);
onConnectionError();
}
Serial.println("MQTT connected");
// Subscribe to controls
rc = client.subscribe(ledControlTopic, MQTT::QOS2, colorArrived);
if (rc != 0)
{
sprintf(printbuf, "rc from MQTT subscribe is %d\n", rc);
Serial.print(printbuf);
onConnectionError();
}
rc = client.subscribe(errorControlTopic, MQTT::QOS2, errorOverrideArrived);
if (rc != 0)
{
sprintf(printbuf, "rc from MQTT subscribe is %d\n", rc);
Serial.print(printbuf);
onConnectionError();
}
Serial.println("MQTT subscribed");
}
// create the light listener - just waiting for controls
void *listen(void* ptr)
{
while(1) {
client.yield(1000);
delay(50);
}
}
// create the wifi publisher - publishing current wifi rssi every 5 seconds to /wifi topic
void *publish_wifi(void* ptr)
{
while(1) {
char buf[100];
MQTT::Message message;
message.qos = MQTT::QOS0;
message.retained = false;
message.dup = false;
sprintf(buf, "%d", WiFi.RSSI());
Serial.println(buf);
message.payload = (void*)buf;
message.payloadlen = strlen(buf)+1;
int rc = client.publish(wifiSensorTopic, message);
delay(5000);
}
}
// listen for button presses - debounces for 500ms after releasing - publishes to /left or /right depending on which button was pressed
void *listen_button(void* btn)
{
bool pressed = false;
while(1) {
char buf[100];
int btnNum = (int)btn;
int state = digitalRead(btnNum);
MQTT::Message message;
message.qos = MQTT::QOS0;
message.retained = false;
message.dup = false;
if (pressed) {
if (state == HIGH) {
pressed = false;
delay(500);
}
} else {
if (state == LOW) {
pressed = true;
sprintf(buf, "PRESSED");
Serial.println(buf);
message.payload = (void*)buf;
message.payloadlen = strlen(buf)+1;
int rc = client.publish(btnNum == LEFT ? leftSensorTopic : rightSensorTopic, message);
client.yield(100);
}
}
// Small delay to allow other threads to jump in
delay(10);
}
}
void setup()
{
// initialize leds as output
pinMode(RED, OUTPUT);
pinMode(BLU, OUTPUT);
pinMode(GRE, OUTPUT);
pinMode(ERRORLED, OUTPUT);
// initialize buttons
pinMode(LEFT, INPUT_PULLUP);
pinMode(RIGHT, INPUT_PULLUP);
// Initialize serial
Serial.begin(serialbaud);
Serial.print("Attempting to connect to Network named: ");
Serial.println(ssid);
// Connect to network
WiFi.begin(ssid, password);
while ( WiFi.status() != WL_CONNECTED) {
// print dots while we wait to connect
Serial.print(".");
delay(300);
}
Serial.println("\nYou're connected to the network");
Serial.println("Waiting for an ip address");
while (WiFi.localIP() == INADDR_NONE) {
// print dots while we wait for an ip addresss
Serial.print(".");
delay(300);
}
Serial.println("\nIP Address obtained");
// We are connected and have an IP address.
Serial.println(WiFi.localIP());
connect();
// create the threads
pthread_t thread1, thread2, thread3, thread4;
int thr = 1;
// start the listener thread
pthread_create(&thread1, NULL, *listen, (void*) thr);
// start wifi RSSI publisher thread
pthread_create(&thread2, NULL, *publish_wifi, (void*) thr);
// Start the left and right button listeners
pthread_create(&thread3, NULL, *listen_button, (void*) LEFT);
pthread_create(&thread4, NULL, *listen_button, (void*) RIGHT);
}
void loop()
{
// Reconnect if needed
if (!client.isConnected())
connect();
// Don't spam
delay(5000);
}