Week15. Interface and Application Programming

Group assignment:

   Compare as many tool options as possible

Individual assignment:

   Write an application that interfaces a user with an input &/or output device that you made

Group Assignment My Part

I have compared several programming languages, device interfaces and user interfaces related to Interface and Application Programming

Programming Languages

Python

- Strengths: Simple syntax, extensive libraries for various tasks, rapid prototyping. - Weaknesses: May have performance limitations for highly resource-intensive applications.

Java

- Strengths: Object-oriented, platform-independent, strong community and support. - Weaknesses: Can have higher memory overhead compared to some languages.

C++

- Strengths: High performance, low-level control, suitable for systems programming. - Weaknesses: Complex syntax, longer development time.

JavaScript

- Strengths: Dominant in web development, widely used for front-end and back-end. - Weaknesses: Asynchronous programming can be challenging to manage.

Device Interfaces

USB (Universal Serial Bus)

- Strengths: Widely supported, high data transfer rates, hot-pluggable. - Weaknesses: Limited distance without extensions.

Bluetooth

- Strengths: Wireless, low power consumption, suitable for portable devices. - Weaknesses: Lower data transfer rates compared to some wired interfaces.

Ethernet

- Strengths: High-speed data transfer, long-distance capabilities. - Weaknesses: Requires physical cabling.

SPI (Serial Peripheral Interface)

- Strengths: Fast, simple, used in embedded systems. - Weaknesses: Limited to short distances.

User Interfaces

GUI (Graphical User Interface)

- Strengths: Intuitive, visually appealing, user-friendly interaction. - Weaknesses: Can be resource-intensive, complex to design.

CLI (Command Line Interface)

- Strengths: Efficient for power users, lightweight, suitable for specific tasks. - Weaknesses: Requires some technical knowledge, less accessible for novice users. The choice of programming language, device interface, and user interface depends on the specific requirements of the interface and application being developed, such as performance, power consumption, portability, the nature of the devices being connected, and the target user group.

Individual Assignment

For the individual assignment, I choose to complete a MQTT communication between my computer and xiao ESP32C3 using webpage as user interface.

Research

This is a website I highly recommend to learn about MQTT
  • MQTT Academany
  • Part1. How MQTT Works

    1. MQTT Introduction

    MQTT (formerly MQ Telemetry Transport) is an OASIS standard messaging protocol to connect devices and implement machine-to-machine (M2M) communication. It is commonly used as a standard messaging protocol in the Internet of Things (IoT) and Industrial Internet of Things (IIoT) domains.

    2. MQTT Publisher and Subscriber

    The MQTT publish-subscribe or pub-sub model is a messaging pattern involving clients (devices or applications that establish a connection with the broker) that send or receive messages on topics – without knowing about the existence of clients that sent or received them. At least three parties take part in the MQTT communication:. 2.1 Subscribers –
          Clients that receive messages of interest to them which contain information on a specific topic
    2.2 Publishers –
          Clients that send messages on a chosen topic
    2.3 MQTT broker –
         The centerpiece that receives messages from publishers, processes, and then forwards them to the subscribers of a topic
    Description of image 2.4 Bi-directional communication in MQTT pub-sub
          The communication between clients in an MQTT pub-sub model is bi-directional, meaning publishers can be subscribers and vice versa.
    2.5 A single MQTT client can simultaneously be a publisher and a subscriber.
          To establish the connection, clients use an MQTT library, a software component that handles the MQTT protocol implementation. MQTT libraries provide an interface between clients and the MQTT broker, allowing the clients to communicate with the broker.
    Description of image

    3. MQTT Broker

    The primary responsibilities of the MQTT broker include the following: - Keep track of the the current state of the MQTT system, including which clients are connected, which topics are being published and subscribed to, etc. - Ensure that only authenticated clients have access to the MQTT system. - Ensure that clients can only receive data on topics where they are authorized. - Process all the flags (special MQTT parameters with a true or false value (1 or 0) representing some packet metadata) in the MQTT packet. We will dive deeper into these in the next lesson.b model is bi-directional, meaning publishers can be subscribers and vice versa. Description of image

    4. MQTT packet format

    The MQTT packet format consists of a:

    Fixed header:

          Made up of the packet type, packet flags, and length of the remaining packet. Description of image

    Variable header:

          The content and length of the variable header will vary according to the packet type and includes packet-type specific meta-data.

    Payload:

          The packet-type specific payload data.

    clientID –

          A parameter that identifies each MQTT client connecting to the MQTT broker. If the clientID value is blank, the broker will generate a unique parameter for this client.

    cleanSession –

          a boolean parameter that indicates whether the client intends to establish a persistent session (a broker keeps unsent messages when the connection is interrupted) with the MQTT broker (false) or not (true).

    keepAlive –

          a parameter that identifies the maximum interval in seconds to maintain the MQTT connection without any data transmission from the client.

    Part2 Set up MQTT on my computer (MAC OS)

    For my assignment, I am going to use my computer as a broker and webpage as a publisher and the ESP32C3 as a subscriber to achive the function of the webpage to control the LED on my PCB.

    Setting up Mosquitto (MQTT) and Brew on mac os

    Navigate to homebrew page:
  • BrewPage
  • 2.1 Open terminal and copy following command and follow the instructions
              
        /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
              
            
    Description of image Description of image 2.2 Next, install mosquitto by using brew command
              
                brew install mosquitto
              
            
    Description of image 2.3 Start Mosquitto Service
              
                brew services start mosquitto
              
            
    Description of image 2.4 Check brew services
              
                brew service list
              
            
    2.5 Check the process of mosquitto
              
                ps aux | grep mosquitto
              
            
    Description of image 2.6 Test if the local mosquitto broker works with local pushlisher and subscriber Open two terminals, topic name is "Test" I used the right terminal as the subscriber:
              
                mosquitto_sub -h localhost -t "Test"
              
            
    I used the left terminal as the publisher:
              
                mosquitto_pub -h localhost -t "Test" -m "Hello"
                mosquitto_pub -h localhost -t "Test" -m "How are you doing"
              
            
    And you can see the subscriber successfulky received message from the publisher. Description of image

    Part3 Set up a web page to connect to Mosquitto via WebSocket

    3.1 First you will need to edit the Mosquitto "/opt/homebrew/etc/mosquitto/mosquitto.conf" file. To open the “.config file” with your text editor, execute the following command in your terminal:
        
          open -a textedit /opt/homebrew/etc/mosquitto/mosquitto.conf
        
      
    Description of image 3.2 Search for the “Listeners” section. Within this section, add the following:
          
            listener 1883
            listener 8080
            protocol websockets
            allow_anonymous true
          
        
    Description of image

    Important thing is that to add two listeners, one on 1883 port for the ESP32C3, another 8080 for the webbrowser using websocket protocol.

    3.3 Save and close the file and restart the mosquitto service
          
            brew service restart mosquitto
          
        
    3.4 Restart the Mosquitto service based on the content of the configuration file
          
            sudo lsof -i :1883
          
        
    If you see "Error: Address alread in use", use following command to list all open files and the processes that have them open for the port 1883
          
            sudo kill -9 2751 kill
          
        
    And use following command to kill the running processes, then restart the mosquitto based on the config file.The whole process is in following picture Description of image Last, run command as below to start mosquitto
          
            mosquitto -c /opt/homebrew/etc/mosquitto/mosquitto.conf
          
        

    Part4. Programming Code for WebPage

    4.1 Then I created a web page to interact with an MQTT broker to control an LED. - In the "head" section, it imports the Paho MQTT JavaScript library from a CDN for me. - It contains two buttons: "Turn On LED" and "Turn Off LED" for me to click. - The JavaScript code defines the MQTT broker URL using my computer's ip with port number 1883 "mqtt://192.168.3.67:8080" and the topic"esp32c2/led" for communication. - It creates an MQTT client object with specific settings and attempts to connect to the broker. If the connection is successful, it logs a message for me; otherwise, it logs an error for me. - It also subscribes to the specified topic for me. - There are functions defined for publishing messages. The publishMessage function creates and sends a message to the topic for me. The turnOnLed and turnOffLed functions call publishMessage with the respective messages 'ON' and 'OFF' to control the LED for me.
    
                <!DOCTYPE html>
                <html>
          
                <head>
                  <script src="https://cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.min.js"></script>
                </head>
          
                <body>
          
                  <h2>MQTT Publisher and LED Control</h2>
          
                  <button onclick="turnOnLed()">Turn On LED</button>
                  <button onclick="turnOffLed()">Turn Off LED</button>
          
                  <script>
                    // MQTT Broker configuration
                    const brokerUrl ='mqtt://192.168.3.67:8080';
                    const topic = 'esp32c2/led';
          
                    // Create MQTT client
                    const client = new Paho.MQTT.Client(brokerUrl, {
                      clientId: 'html-client',
                      cleanSession: true,
                      useSSL: false
                    });
          
                    // Connect to MQTT broker
                    client.connect({
                      onSuccess: function () {
                        console.log('Connected to MQTT Broker');
                      },
                      onFailure: function (error) {
                        console.error('Connection failed:', error);
                      }
                    });
          
                    // Subscribe to topic
                    client.subscribe(topic);
          
                    // Publish message
                    function publishMessage(message) {
                      const payload = new Paho.MQTT.Message(message);
                      payload.destinationName = topic;
                      client.send(payload);
                    }
          
                    // Turn on LED
                    function turnOnLed() {
                      publishMessage('ON');
                    }
          
                    // Turn off LED
                    function turnOffLed() {
                      publishMessage('OFF');
                    }
                  </script>
          
                </body>
          
                </html>
              

    It didn't work!

    Description of image

    Then I tried to download the scipt to my computer and put it in the same folder with html

    
        curl -o mqtt.min.js https://cdnjs.cloudflare.com/ajax/libs/mqtt/4.3.7/mqtt.min.js
      
    Description of image

    Changed this line to

    
    
      src="mqtt.min.js"
    
    

    Still, it didn't work and the error is as below :

    Description of image

    The explaination of this error is that

    This error typically indicates that the createConnection method in the mqtt.min.js library is undefined or unavailable. This could be due to the following reasons:

    You can first try changing the version of the mqtt library to see if it resolves the issue.

    Description of image

    Then I tried to find other Jacascript that may be compatible for my mac_homebrew environment

    Changed the html code to be

    
          const mqtt = require('mqtt');
    
          // Configuration for the MQTT Broker
          const brokerUrl ='mqtt://192.168.3.67:8080';
          const topic = 'esp32c2/led';
    
          // Create MQTT Client
          const client = mqtt.connect(brokerUrl);
        

    Still, it didn't work and the error is as below :

    Description of image

    The explaination of this error is that

    Using require directly in HTML may not work properly because the browser environment typically does not support the module system of Node.js. This approach is more suitable for environments that support the Node.js runtime, such as when using a backend template engine to render HTML pages.

    If you need to run in a pure browser environment, you may need to use other methods, such as packaging the code with packaging tools (such as Webpack or Parcel) and handling the import of modules.

    IMPORTANT Import the mqtt library from a CDN using the <script> tag

    Finally, it works! And the code is as below:

    MQTT Publisher and LED Control Code

    
        
        <!DOCTYPE html>
        <html>
    
        <head>
          
          <style>
            body {
              font-family: Arial, sans-serif;
              background-color: #f4f4f4;
              margin: 0;
              padding: 0;
            }
    
            h2 {
              color: #333;
              text-align: center;
              padding: 20px 0;
              background-color: #fff;
              box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            }
    
            button {
              padding: 15px 30px;
              font-size: 18px;
              border: none;
              border-radius: 5px;
              cursor: pointer;
              box-shadow: 0 0 5px rgba(0, 0, 0, 0.2);
              transition: background-color 0.3s ease;
            }
    
            button:hover {
              background-color: #4CAF50;
              color: #fff;
            }
    
            #container {
              width: 50%;
              margin: 0 auto;
              padding: 20px;
              background-color: #fff;
              box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            }
    
            #brightnessValue {
              width: 100px;
              padding: 10px;
              font-size: 18px;
              border-radius: 5px;
              border: 1px solid #ccc;
            }
          </style>
          
          <script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
        </head>
    
        <body>
          <div id="container">
            <h2>MQTT Publisher and LED Control</h2>
            <button onclick="turnOnLed()">TURN ON LED</button>
            <button onclick="turnOffLed()">TURN OFF LED</button>
            <p></p>
            <label for="brightnessValue">Brightness(0-255):</label>
            <input type="number" id="brightnessValue" min="0" max="255" value="128" />
            <button onclick="setLedBrightness()">Set Up Brightness</button>
          </div>
    
          <script>
            
            const brokerUrl ='mqtt://192.168.3.67:8080';
            const topic = 'esp32c2/led';
    
            
            const client = mqtt.connect(brokerUrl);
    
            
            client.on('connect', () => {
              console.log('Connected to MQTT Broker');
            });
    
            
            client.on('error', (error) => {
              console.error('Error:', error);
            });
    
            
            function turnOnLed() {
              client.publish(topic, 'ON');
            }
    
            
            function turnOffLed() {
              client.publish(topic, 'OFF');
            }
    
            
            function setLedBrightness() {
              const brightness = document.getElementById('brightnessValue').value;
              client.publish(topic + '/brightness', brightness);
            }
          </script>
        </body>
    
        </html>
      

    Part5. Programming Code for ESP32C3

    Install the MQTT Libary

    Description of image

    Programming part of ESP32C3 is relatively easier.

    1. First, it includes necessary libraries for WiFi and MQTT functionality. Then, it defines the WiFi network details (SSID and password), MQTT server address and port, and the LED pin. 2. The `callback` function is defined to handle the received MQTT messages. It parses the message payload and takes actions based on the message content and the topic. If the topic is related to LED control (either turning it on/off or adjusting the brightness), it controls the LED accordingly. 3. The `reconnect` function is used to attempt reconnection to the MQTT server if the connection is lost. It keeps trying until a successful connection is established and subscribes to the relevant topics upon connection. 4. The `setup` function initializes the serial communication, sets the LED pin as output, attempts to connect to the WiFi network, and configures the MQTT client with the server details and the callback function. 5. Finally, the `loop` function checks if the MQTT connection is still active. If not, it calls the `reconnect` function. It also ensures the MQTT client keeps processing incoming messages.
    
          #include <WiFi.h>
          #include <PubSubClient.h>
          
          // WiFi configuration
          const char* ssid = "Katherine_Home"; // The name of the WiFi network
          const char* password = "NiuNiu876519"; // The password of the WiFi network
          
          // MQTT server configuration
          const char* mqttServer = "192.168.3.67"; // The address of the MQTT server
          const int mqttPort = 1883; // The port of the MQTT server
          
          // LED pin
          #define LED_PIN D1 // Define the pin for controlling the LED
          
          // Create WiFi client and MQTT client
          WiFiClient espClient;
          PubSubClient client(espClient); // Create MQTT client object and associate with WiFi client
          
          /**
           * MQTT message callback function
           * Called when an MQTT message is received
           * @param topic The topic of the message
           * @param payload The payload (data) of the message
           * @param length The length of the payload
           */
          void callback(char* topic, byte* payload, unsigned int length) {
            String message = ""; 
            for (int i = 0; i < length; i++) {
              message += (char)payload[i];
            }
          
            Serial.print("Message arrived (");
            Serial.print(topic);
            Serial.print(") ");
            Serial.println(message);
          
            // Control the LED based on the received "ON" or "OFF"
            if (strcmp(topic, "esp32c2/led") == 0) {
              if (message == "ON") {
                analogWrite(LED_PIN, 256);
              } else if (message == "OFF") {
                analogWrite(LED_PIN, 0);
              }
            }
            else if (strcmp(topic, "esp32c2/led/brightness") == 0) {
              int brightness = atoi((char*)payload);
              analogWrite(LED_PIN, brightness);
            }
          }
          
          /**
           * Function to reconnect to the MQTT server
           */
          void reconnect() {
            // Loop until reconnection is successful
            while (!client.connected()) {
              Serial.print("Attempting MQTT connection...");
              // Try to connect
              if (client.connect("ESP32Client")) {
                Serial.println("connected");
                // Subscribe to topics
                client.subscribe("esp32c2/led");
                client.subscribe("esp32c2/led/brightness");
              } else {
                Serial.print("failed, rc=");
                Serial.print(client.state());
                Serial.println(" try again in 5 seconds");
                // Wait 5 seconds before retrying
                delay(5000);
              }
            }
          }
          
          /**
           * Setup function, runs once at the beginning
           */
          void setup() {
            Serial.begin(115200);
          
            // Set the LED pin as output
            pinMode(LED_PIN, OUTPUT);
          
            // Connect to WiFi
            WiFi.begin(ssid, password);
            while (WiFi.status()!= WL_CONNECTED) {
              delay(1000);
              Serial.println("Connecting to WiFi...");
            }
          
            client.setServer(mqttServer, mqttPort);
            client.setCallback(callback);
          }
          
          /**
           * Main loop function, runs repeatedly
           */
          void loop() {
            if (!client.connected()) {
              reconnect();
            }
            client.loop();
          }
              
            
    Run the code and terminal,ESP32C3 is succesffly connected Description of image Description of image

    Part6. Final interaction

      KK Rocks!