Difference between revisions of "Modular ESP Firmware - MQTT - Individual Functions"

From The TinkerNet Wiki
Jump to navigation Jump to search
Line 97: Line 97:
 
   MQTT_beacon();
 
   MQTT_beacon();
  
Can also be called once inside <code>setup()</code> just to show connection details at bootup.
+
Also be called once inside <code>setup_mqtt()</code> just to show connection details at bootup.
  
 
<syntaxhighlight lang="cpp" line="1">
 
<syntaxhighlight lang="cpp" line="1">

Revision as of 23:05, 26 December 2020

Main Functions

void setup_mqtt();

Called from inside setup() to configure your MQTT connection.

 1 void setup_mqtt()
 2 {
 3   MQTT_client.setServer(MQTT_broker, 1883);
 4   MQTT_client.setCallback(MQTT_callback);
 5 
 6   //  Build the topic names
 7   strcpy(MQTT_inTopic, "cmnd/"); //  in - Commands
 8   strcat(MQTT_inTopic, MQTT_ClientName);
 9   strcat(MQTT_inTopic, "/#");
10   strcpy(MQTT_teleTopic, "tele/"); // out - Telemetry
11   strcat(MQTT_teleTopic, MQTT_ClientName);
12   strcpy(MQTT_statTopic, "stat/"); // out - Status
13   strcat(MQTT_statTopic, MQTT_ClientName);
14   strcpy(MQTT_outTopic, "noti/"); // out - Notifications
15   strcat(MQTT_outTopic, MQTT_ClientName);
16 
17   MQTT_reconnect();
18   Serial.printf("+---------------------------------------+\n");
19 }

void MQTT_callback(char *topic, byte *payload, int length);

Actually... Called by the libraries built-in client.loop() function.

 1 void MQTT_callback(char *topic, byte *payload, int length)
 2 {
 3 
 4   char MQTT_msg_in[MQTT_BUFFER_SIZE];
 5   char *MQTT_command = strrchr(topic, '/');
 6 
 7 #ifdef DEBUG
 8   Serial.printf("|                                       |\n");
 9   Serial.printf("| Message arrived                       |\n");
10   Serial.printf("| Command: %28s |\n", MQTT_command);
11 #endif
12 
13   if (length < MQTT_BUFFER_SIZE)
14   {
15     for (int i = 0; i < length; i++)
16     {
17       MQTT_msg_in[i] = (char)payload[i];
18       MQTT_msg_in[i + 1] = '\0';
19     }
20 
21 #ifdef DEBUG
22     Serial.printf("| Message: %28s |\n", MQTT_msg_in);
23 #endif
24     /////////////////////////////////////////////////////
25     // Message handling goes here...
26     /////////////////////////////////////////////////////
27     if (strcmp(MQTT_command, "/lights") == 0)
28     {
29       DoLights(MQTT_msg_in);
30     }
31     else if (strcmp(MQTT_command, "/respond") == 0)
32     {
33       DoAnswer(MQTT_msg_in);
34     }
35     else if (strcmp(MQTT_command, "/control") == 0)
36     {
37       DoControl(MQTT_msg_in);
38     }
39     else
40     {
41 #ifdef DEBUG
42       Serial.printf("| Dunno Whatcha want...                 |\n");
43 #endif
44     }
45   }
46   else
47   {
48 #ifdef DEBUG
49     Serial.printf("| But, it's TOO Bloody Big!             |\n");
50 #endif
51   }
52 }

void MQTT_reconnect();

Called from inside loop() to ensure persistent communications.

 if (!MQTT_client.connected())
 {
   MQTT_reconnect();
 }
 MQTT_client.loop();
 MQTT_beacon();

Also be called once inside setup_mqtt() just to show connection details at bootup.

 1 void MQTT_reconnect()
 2 {
 3   // Loop until we're reconnected
 4   while (!MQTT_client.connected())
 5   {
 6     Serial.printf("|                                       |\n");
 7     Serial.printf("| Attempting MQTT connection...         |\n");
 8     // Create a random client ID
 9     String clientId = MQTT_ClientName;
10     clientId += String(random(0xffff), HEX);
11     // Attempt to connect
12     if (MQTT_client.connect(clientId.c_str()))
13     {
14       Serial.printf("| connected to %-24s |\n", MQTT_broker);
15       Serial.printf("| My Name:  %-27s |\n", MQTT_ClientName);
16       // Once connected, publish an announcement...
17       MQTT_client.publish(MQTT_statTopic, "hello world");
18       // ... and resubscribe
19       MQTT_client.subscribe(MQTT_inTopic);
20     }
21     else
22     {
23       Serial.printf("|                                       |\n");
24       Serial.printf("| failed, rc=%d                         |\n", MQTT_client.state());
25       Serial.printf("| trying again in 5 seconds             |\n");
26       // Wait 5 seconds before retrying
27       delay(5000);
28     }
29   }
30 }

void MQTT_beacon();

Called inside loop() to provide reassurance that things are alive.

 1 void MQTT_beacon()
 2 {
 3   /* Beacon signal published at set interval to indicate the device
 4    * is still powered up and actively connected to MQTT...
 5    * A keepalive of sorts
 6    * also updates state within MQTT so it can be captured for
 7    * indicator light elsewhere
 8    */
 9   if (getTimer(beacon_timer, BEACON_INTERVAL))
10   {
11     MQTT_client.publish(MQTT_teleTopic, "boop");
12     blinkLED();
13   }
14 }

Supplimentary Functions

bool getTimer(unsigned long &timer, unsigned long interval);

 1 bool getTimer(unsigned long &timer, unsigned long interval)
 2 /* Global timer function, used a lot
 3  *
 4  * @param unsigned long time - The current timer
 5  * @param unsigned long interval - Length of time to run timer
 6  *
 7  * @return bool True when timer is complete
 8  * @return bool False when timer is counting
 9  */
10 {
11 
12   if (timer < 1)
13   {
14     timer = millis();
15   }
16 
17   if (millis() - timer >= interval)
18   {
19     timer = 0;
20     return true;
21   }
22 
23   return false;
24 }

void blinkLED(); // Just a little function to blink the LED for the beacon function.

Don't forget to set up the LED pin in the setup() function:

 pinMode(LED_BUILTIN, OUTPUT);
 digitalWrite(LED_BUILTIN, HIGH);
 1 void blinkLED() // Just a little function to blink the on-board LED for the beacon function.
 2 {
 3   digitalWrite(LED_BUILTIN, LOW);
 4   delay(10);
 5   digitalWrite(LED_BUILTIN, HIGH);
 6   delay(10);
 7   digitalWrite(LED_BUILTIN, LOW);
 8   delay(10);
 9   digitalWrite(LED_BUILTIN, HIGH);
10 }

Some CMND Handlers

void DoLights(char *WhatToDo); // Turn LED on/off

Don't forget to set up the LED pin in the setup() function:

 pinMode(LED_BUILTIN, OUTPUT);
 digitalWrite(LED_BUILTIN, HIGH);
1 void DoLights(char *WhatToDo) // Turn LED on/off
2 {
3   Serial.printf("[- Lights - %3s                        -]\n", WhatToDo);
4   if (strcmp(WhatToDo, "ON") == 0)
5     digitalWrite(LED_BUILTIN, LOW);
6   if (strcmp(WhatToDo, "OFF") == 0)
7     digitalWrite(LED_BUILTIN, HIGH);
8 }

void DoAnswer(char *WhatToDo); // Send back text

1 void DoAnswer(char *WhatToDo) // Send back text
2 {
3   Serial.printf("[- Responding: %-23s -]\n", WhatToDo);
4   MQTT_client.publish(MQTT_outTopic, WhatToDo);
5 }

void DoControl(char *WhatToDo); // Send MQTT to another device/topic

 1 void DoControl(char *WhatToDo) // Send MQTT to another device/topic
 2 {
 3   /*
 4   Should be something along the lines of,
 5 
 6   MQTT_client.publish(TopicFromMessage, MessageFromMessage);
 7 
 8   Where
 9     TopicFromMessage
10   is an MQTT topic for sending to another device
11   and
12     MessageFromMessage
13   is the message to publish to that topic...
14   */
15 }