Displays a value on an RS display board

Dependencies:   EthernetInterface PCA9635 dispBoB mbed-rtos mbed munin-client-lib

Displaying values retrieved from a munin node on an RS display board. Porting this code to work with an alternative display should be trivial, I have also used an mbed application board's LCD to display the values for example.

Hardware

Software

Most of the work is done by libraries that are freely available on mbed.org. The code uses the lwip based EthernetInterface library. The only code I had to write was submit a command to a munin node and parse it's response.

Testing

The software has currently been running for around 2 weeks without any problems. On a previous run it stopped updating after 4 days.

main.cpp

Committer:
PrzemekWirkus
Date:
2014-04-14
Revision:
5:5c0288a4e2c7
Parent:
4:186148592f35
Child:
6:df775c94a9c8

File content as of revision 5:5c0288a4e2c7:

#include <string>
#include <vector>
#include <sstream>
#include "mbed.h"
#include "EthernetInterface.h"
#include "dispBoB.h"

namespace {
    const char* MUNIN_SERVER_ADDRESS = "172.28.22.45";
    const int MUNIN_SERVER_PORT = 4949;
    char CMD_FETCH_USERS[] = "fetch users\n";
}


/** MuninDisplay class, used to fetch counters from Munin and display them on dispBoB.
* 
* Example:
* @code
* MuninDisplay munin_lcd;
* munin_lcd.dhcp_connection();    // DHCP connection
*
* while(true) {
* while (munin_lcd.socket_connection(MUNIN_SERVER_ADDRESS, MUNIN_SERVER_PORT) < 0) {
*   wait(1);
* }
*
* munin_lcd.socket_recv();
* munin_lcd.socket_send(CMD_FETCH_USERS, sizeof(CMD_FETCH_USERS));
* munin_lcd.socket_recv_all();
* munin_lcd.get_param_value("usercount.value");
*          
* munin_lcd.socket_close();
* wait(3);
* }
* @endcode
*/
class MuninDisplay {
public:
    /** Initialize dispBoB object
    */
    MuninDisplay() : bob_display(p28, p27, p26) {
        bob_display.cls();   
    }

    /** Prints string on LCD
    *
    * @param str Text to be displayed on 'bob' display
    */
    void lcd_print_str(const char *str) {
        bob_display.cls();
        bob_display.printf("%s\n", str);        
    }

    /** Prints integer on LCD
    *
    * @param value Integer to be displayed on 'bob' display
    */
    void lcd_print_int(const int value) {
        bob_display.cls();
        bob_display.printf("%d\n", value);        
    }

    /** Connect to DHCP
    */
    void dhcp_connection() {
        printf("DHCP: Connecting ... ");
        eth.init(); //Use DHCP
        eth.connect();
        printf("%s\r\n", eth.getIPAddress());
    }
    
    /** Create a dispBoB object defined on the I2C master bus
    *
    * @param server Munin server IP / name
    * @param port Munin server port
    */
    int socket_connection(const char *server, const int port) {
        printf("TCP: Connecting ... ");
        int ret = socket.connect(server, port) < 0;
        printf("[OK]\r\n");
        return ret;
    }

    /** Closes socket conenction to Munin server
    */
    void socket_close() {
        socket.close();
    }

    /** Recv data from Munin to buffer 'buf'
    */
    int socket_recv() {
        const int n = socket.receive(buf, sizeof(buf) - 1);
        if (n > 0) {
            buf[n] = '\0';
            printf("RECV: %s\r\n", buf);
        }
        return n;   
    }

    /** Recv data from Munin to buffer 'buf'. Used to fetch reply for Munin command (given counter name)
    */
    int socket_recv_all() {
        const int n = socket.receive_all(buf, sizeof(buf) - 1);
        if (n > 0) {
            buf[n] = '\0';
            printf("RECV: %s\r\n", buf);
        }
        return n;   
    }

    /** Send data using socket to Munin server. Used to send command to Munin server.
    * @param cmd Munin command string, must end with \n
    * @param cmd_size Munin command buffer size
    */    
    int socket_send(char *cmd, const int cmd_size) {
        const int n = socket.send(cmd, cmd_size - 1);
        return n;
    }

    /** Explodes Munin command reply into individual counters divided by '\n'. 
    * Function extract counter value from conunter wirh name param_name.
    * @param param_name counter name 
    */    
    int get_param_value(std::string param_name) {
        // Explode Munin command and creaste separate strings with counters
        std::vector<std::string> s = explode(std::string(buf), '\n');
        
        // For each counter name get its name and if name matches param_name extract and return counter value
        for (std::vector<std::string>::iterator it = s.begin(); it != s.end(); ++it) {
            std::string &param = *it;
            printf("PARAM_RECV: %s\r\n", param.c_str());
            if (!param.compare(0, param_name.size(), param_name)) {
                printf("PARAM_FOUND: %s is '%s' \r\n", param.c_str(), param_name.c_str());
                std::vector<std::string> name_value = explode(param, ' ');
                if (name_value.size() == 2) {
                    const int val = atoi(name_value[1].c_str());
                    printf("DISPLAYING: %s\r\n", name_value[1].c_str());                    
                    return val;
                }
            }
        }
        return 0;
    }

protected:
    EthernetInterface eth;
    TCPSocketConnection socket;
    dispBoB bob_display;
    char buf[256];

    // String explode function
    std::vector<std::string> explode(std::string const &s, char delim)
    {
        std::vector<std::string> result;
        std::istringstream iss(s);
        for (std::string token; std::getline(iss, token, delim); ) {
            result.push_back(token);
        }
        return result;
    }
};

int main() {
    MuninDisplay munin_lcd;
    munin_lcd.dhcp_connection();    // DHCP connection
                
    while(true) {
        while (munin_lcd.socket_connection(MUNIN_SERVER_ADDRESS, MUNIN_SERVER_PORT) < 0) {
            wait(1);
        }

        munin_lcd.socket_recv();
        munin_lcd.socket_send(CMD_FETCH_USERS, sizeof(CMD_FETCH_USERS));
        munin_lcd.socket_recv_all();
        int counter_value = munin_lcd.get_param_value("usercount.value");
        munin_lcd.lcd_print_int(counter_value);
          
        munin_lcd.socket_close();
        wait(3);
    }
}