The IrcBot class can connect to a channel on an IRC network. Users on the same network can send messages to the bot that are parsed by message handlers. The included handlers read digital/analog inputs and write digital outputs or echo messages back to the command sender/channel. Users can write their own message handlers inheriting from the MessageHandler class to perform different actions.
Revision 1:cf586c9bbb52, committed 2014-08-02
- Comitter:
- NickRyder
- Date:
- Sat Aug 02 12:17:28 2014 +0000
- Parent:
- 0:b8fb2df56652
- Child:
- 2:e4c74eb20586
- Commit message:
- Renaming files.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IrcBot.cpp Sat Aug 02 12:17:28 2014 +0000 @@ -0,0 +1,169 @@ +#include "IrcBot.h" + +IrcMessage::IrcMessage(char * f, char * t, char * m) { + sprintf(from, "%s", f); + sprintf(to, "%s", t); + sprintf(msg, "%s", m); +} + +IrcMessage::IrcMessage() { + from[0] = '\0'; + to[0] = '\0'; + msg[0] = '\0'; +} + +Irc::Irc(char * nick, char * net, int p, char * chan) : + pc(USBTX, USBRX), sock(), port(p), ident(false), connected(false), + setup(false), joined(false), parseindex(0) +{ + sprintf(nickname, "%s", nick); + sprintf(password, "%s", ""); + sprintf(network, "%s", net); + sprintf(channel, "%s", chan); + pc.printf("Created Irc obj for %s.\n", nickname); +} + +void Irc::identify(char * pass) { + ident = true; + sprintf(password, "%s", pass); +} + +void Irc::join(char * chan) { + char cmd[64]; + sprintf(cmd, ":source JOIN :%s\r\n", chan); + send(cmd); +} + +void Irc::connect() { + pc.printf("Connecting to %s:%d...\n", network, port); + sock.connect(network, port); + pc.printf("Done.\n"); + connected = true; +} + +void Irc::disconnect() { + if (connected) { + pc.printf("Disconnecting.\n"); + sock.close(); + connected = false; + } +} + +void Irc::add(MessageHandler * handler) { + handlers.push_back(handler); +} + +bool Irc::read() { + if (!connected) return 0; + int ret = sock.receive(readbuffer, sizeof(readbuffer) - 1); + bool parsed = false; + if (ret >= 0) { + readbuffer[ret] = '\0'; + pc.printf("Received %d chars: ---%s--\n", ret, readbuffer); + for (int i = 0; i < ret; i++) { + parsebuffer[parseindex] = readbuffer[i]; + parseindex++; + if (readbuffer[i] == '\n') { + parsebuffer[parseindex] = '\0'; + parse(); + parsed = true; + parseindex = 0; + } + } + } + return parsed; +} + +void Irc::send(char * cmd) { + if (!connected) return; + int i = 0; + bool ok = true; + while (cmd[i] != '\0') { + i++; + if (i > 512) { + ok = false; + break; + } + } + if (!ok) return; + pc.printf("Sending: ---%s---\n", cmd); + sock.send_all(cmd, i); +} + +void Irc::handle(IrcMessage msg) { + pc.printf("Handling message from %s, to %s: %s\n", msg.from, msg.to, msg.msg); + for (int i = 0; i < handlers.size(); i++) { + IrcMessage out = handlers.at(i)->handle(msg); + if (out.to[0] != '\0') { + sprintf(out.from, "%s", nickname); + pc.printf("Need to send: ---%s--- from %s to %s.\n", out.msg, out.from, out.to); + char cmd[512]; + sprintf(cmd, "PRIVMSG %s :%s\r\n", out.to, out.msg); + send(cmd); + } + } +} + +void Irc::parse() { + pc.printf("Parsing: --%s--\n", parsebuffer); + if (setup && (!joined)) { + char cmd[256]; + sprintf(cmd, ":source JOIN :%s\r\n", channel); + send(cmd); + joined = true; + return; + } + if (!setup) { + char cmd[256]; + sprintf(cmd, "NICK %s\r\nUSER %s 0 * :Lester\r\n", nickname, nickname); + send(cmd); + setup = true; + return; + } + char * c = NULL; + c = strstr(parsebuffer, "PING"); + if (c != NULL) { + char cmd[] = "PONG\r\n"; + send(cmd); + } + c = strstr(parsebuffer, "PRIVMSG"); + if (c != NULL) { + char f[32]; + char t[32]; + char m[256]; + int i; + for (i = 1; i < 32; i++) { + if (parsebuffer[i] == '!') { + f[i - 1] = '\0'; + break; + } + f[i - 1] = parsebuffer[i]; + } + int nspace = 0; + bool inmsg = false; + int toindex = 0, msgindex = 0; + for (; i < sizeof(parsebuffer); i++) { + if (parsebuffer[i] == '\r') break; + if (parsebuffer[i] == '\n') break; + if (parsebuffer[i] == '\0') break; + if (parsebuffer[i] == ' ') { + nspace++; + } + if ((nspace == 2) && (parsebuffer[i] != ' ')) { + t[toindex] = parsebuffer[i]; + toindex++; + } + if (inmsg) { + m[msgindex] = parsebuffer[i]; + msgindex++; + } + if ((parsebuffer[i] == ':') && (!inmsg)) { + inmsg = true; + } + } + t[toindex] = '\0'; + m[msgindex] = '\0'; + IrcMessage msg(f, t, m); + handle(msg); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IrcBot.h Sat Aug 02 12:17:28 2014 +0000 @@ -0,0 +1,48 @@ +#ifndef __mbed_irc_h__ +#define __mbed_irc_h__ + +#include "mbed.h" +#include "EthernetInterface.h" +#include <vector> + +class IrcMessage { + public: + IrcMessage(); + IrcMessage(char *, char *, char *); + char from[32], to[32], msg[256]; +}; + +class MessageHandler { + public: + MessageHandler() {}; + virtual IrcMessage handle(IrcMessage msg) {return IrcMessage();} +}; + +class Irc { + public: + Irc(char *, char *, int, char *); + void connect(); + void disconnect(); + void add(MessageHandler *); + void identify(char *); + void join(char *); + bool read(); + private: + void handle(IrcMessage); + void parse(); + void send(char *); + Serial pc; + TCPSocketConnection sock; + char network[64]; + char channel[64]; + int port; + char nickname[64]; + char password[64]; + bool ident, connected, setup, joined; + char readbuffer[512]; + char parsebuffer[512]; + int parseindex; + vector<MessageHandler *> handlers; +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IrcMessageHandlers.cpp Sat Aug 02 12:17:28 2014 +0000 @@ -0,0 +1,113 @@ +#include "IrcMessageHandlers.h" + +DigitalOutHandler::DigitalOutHandler(char * n, PinName p, bool v) : + pin(p), verbose(v) +{ + sprintf(name, "%s", n); + pin = 0; +} + +IrcMessage DigitalOutHandler::handle(IrcMessage msg) { + IrcMessage reply; + if (verbose) { + if (msg.to[0] == '#') { + strcpy(reply.to, msg.to); + } else { + strcpy(reply.to, msg.from); + } + } + char required[64]; + sprintf(required, "WRITE %s", name); + char * c = NULL; + c = strstr(msg.msg, required); + if (c != NULL) { + c = strstr(msg.msg, "ON"); + if (c != NULL) { + pin = 1; + if (verbose) { + sprintf(reply.msg, "SET %s ON", name); + } + } + c = strstr(msg.msg, "OFF"); + if (c != NULL) { + pin = 0; + if (verbose) { + sprintf(reply.msg, "SET %s OFF", name); + } + } + } + return reply; +} + +DigitalInHandler::DigitalInHandler(char * n, PinName p) : + pin(p) +{ + sprintf(name, "%s", n); +} + +IrcMessage DigitalInHandler::handle(IrcMessage msg) { + IrcMessage reply; + if (msg.to[0] == '#') { + strcpy(reply.to, msg.to); + } else { + strcpy(reply.to, msg.from); + } + char required[64]; + sprintf(required, "READ %s", name); + char * c = NULL; + c = strstr(msg.msg, required); + if (c != NULL) { + if (pin) { + sprintf(reply.msg, "%s is ON", name); + } else { + sprintf(reply.msg, "%s is OFF", name); + } + } + return reply; +} + +AnalogInHandler::AnalogInHandler(char * n, PinName p) : + pin(p), scaleval(1.0) +{ + sprintf(name, "%s", n); + sprintf(unit, ""); +} + +void AnalogInHandler::scale(float s, char * u) { + scaleval = s; + sprintf(unit, "%s", u); +} + +IrcMessage AnalogInHandler::handle(IrcMessage msg) { + IrcMessage reply; + if (msg.to[0] == '#') { + strcpy(reply.to, msg.to); + } else { + strcpy(reply.to, msg.from); + } + char required[64]; + sprintf(required, "READ %s", name); + char * c = NULL; + c = strstr(msg.msg, required); + if (c != NULL) { + float v = pin * scaleval; + sprintf(reply.msg, "%s = %f %s", name, v, unit); + } + return reply; +} + +IrcMessage EchoHandler::handle(IrcMessage msg) { + IrcMessage reply; + char * c = NULL; + c = strstr(msg.msg, "ECHO "); + if (c != NULL) { + strcpy(reply.from, msg.to); + if (msg.to[0] == '#') { + strcpy(reply.to, msg.to); + } else { + strcpy(reply.to, msg.from); + } + strcpy(reply.msg, c + 5); + } + return reply; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IrcMessageHandlers.h Sat Aug 02 12:17:28 2014 +0000 @@ -0,0 +1,42 @@ +#ifndef __mbed_irc_handlers_h__ +#define __mbed_irc_handlers_h__ +#include "IrcBot.h" + +class DigitalOutHandler : private MessageHandler { + public: + DigitalOutHandler(char *, PinName, bool); + IrcMessage handle(IrcMessage); + private: + DigitalOut pin; + char name[32]; + bool verbose; +}; + +class DigitalInHandler : private MessageHandler { + public: + DigitalInHandler(char *, PinName); + IrcMessage handle(IrcMessage); + private: + DigitalIn pin; + char name[32]; +}; + +class AnalogInHandler : private MessageHandler { + public: + AnalogInHandler(char *, PinName); + void scale(float, char *); + IrcMessage handle(IrcMessage); + private: + AnalogIn pin; + char name[32]; + char unit[32]; + float scaleval; +}; + +class EchoHandler : private MessageHandler { + public: + EchoHandler(){}; + IrcMessage handle(IrcMessage msg); +}; + +#endif \ No newline at end of file
--- a/handlers.cpp Sat Aug 02 12:09:10 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,113 +0,0 @@ -#include "handlers.h" - -DigitalOutHandler::DigitalOutHandler(char * n, PinName p, bool v) : - pin(p), verbose(v) -{ - sprintf(name, "%s", n); - pin = 0; -} - -IrcMessage DigitalOutHandler::handle(IrcMessage msg) { - IrcMessage reply; - if (verbose) { - if (msg.to[0] == '#') { - strcpy(reply.to, msg.to); - } else { - strcpy(reply.to, msg.from); - } - } - char required[64]; - sprintf(required, "WRITE %s", name); - char * c = NULL; - c = strstr(msg.msg, required); - if (c != NULL) { - c = strstr(msg.msg, "ON"); - if (c != NULL) { - pin = 1; - if (verbose) { - sprintf(reply.msg, "SET %s ON", name); - } - } - c = strstr(msg.msg, "OFF"); - if (c != NULL) { - pin = 0; - if (verbose) { - sprintf(reply.msg, "SET %s OFF", name); - } - } - } - return reply; -} - -DigitalInHandler::DigitalInHandler(char * n, PinName p) : - pin(p) -{ - sprintf(name, "%s", n); -} - -IrcMessage DigitalInHandler::handle(IrcMessage msg) { - IrcMessage reply; - if (msg.to[0] == '#') { - strcpy(reply.to, msg.to); - } else { - strcpy(reply.to, msg.from); - } - char required[64]; - sprintf(required, "READ %s", name); - char * c = NULL; - c = strstr(msg.msg, required); - if (c != NULL) { - if (pin) { - sprintf(reply.msg, "%s is ON", name); - } else { - sprintf(reply.msg, "%s is OFF", name); - } - } - return reply; -} - -AnalogInHandler::AnalogInHandler(char * n, PinName p) : - pin(p), scaleval(1.0) -{ - sprintf(name, "%s", n); - sprintf(unit, ""); -} - -void AnalogInHandler::scale(float s, char * u) { - scaleval = s; - sprintf(unit, "%s", u); -} - -IrcMessage AnalogInHandler::handle(IrcMessage msg) { - IrcMessage reply; - if (msg.to[0] == '#') { - strcpy(reply.to, msg.to); - } else { - strcpy(reply.to, msg.from); - } - char required[64]; - sprintf(required, "READ %s", name); - char * c = NULL; - c = strstr(msg.msg, required); - if (c != NULL) { - float v = pin * scaleval; - sprintf(reply.msg, "%s = %f %s", name, v, unit); - } - return reply; -} - -IrcMessage EchoHandler::handle(IrcMessage msg) { - IrcMessage reply; - char * c = NULL; - c = strstr(msg.msg, "ECHO "); - if (c != NULL) { - strcpy(reply.from, msg.to); - if (msg.to[0] == '#') { - strcpy(reply.to, msg.to); - } else { - strcpy(reply.to, msg.from); - } - strcpy(reply.msg, c + 5); - } - return reply; -}
--- a/handlers.h Sat Aug 02 12:09:10 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,39 +0,0 @@ -#include "irc.h" - -class DigitalOutHandler : private MessageHandler { - public: - DigitalOutHandler(char *, PinName, bool); - IrcMessage handle(IrcMessage); - private: - DigitalOut pin; - char name[32]; - bool verbose; -}; - -class DigitalInHandler : private MessageHandler { - public: - DigitalInHandler(char *, PinName); - IrcMessage handle(IrcMessage); - private: - DigitalIn pin; - char name[32]; -}; - -class AnalogInHandler : private MessageHandler { - public: - AnalogInHandler(char *, PinName); - void scale(float, char *); - IrcMessage handle(IrcMessage); - private: - AnalogIn pin; - char name[32]; - char unit[32]; - float scaleval; -}; - -class EchoHandler : private MessageHandler { - public: - EchoHandler(){}; - IrcMessage handle(IrcMessage msg); -}; -
--- a/irc.cpp Sat Aug 02 12:09:10 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,169 +0,0 @@ -#include "irc.h" - -IrcMessage::IrcMessage(char * f, char * t, char * m) { - sprintf(from, "%s", f); - sprintf(to, "%s", t); - sprintf(msg, "%s", m); -} - -IrcMessage::IrcMessage() { - from[0] = '\0'; - to[0] = '\0'; - msg[0] = '\0'; -} - -Irc::Irc(char * nick, char * net, int p, char * chan) : - pc(USBTX, USBRX), sock(), port(p), ident(false), connected(false), - setup(false), joined(false), parseindex(0) -{ - sprintf(nickname, "%s", nick); - sprintf(password, "%s", ""); - sprintf(network, "%s", net); - sprintf(channel, "%s", chan); - pc.printf("Created Irc obj for %s.\n", nickname); -} - -void Irc::identify(char * pass) { - ident = true; - sprintf(password, "%s", pass); -} - -void Irc::join(char * chan) { - char cmd[64]; - sprintf(cmd, ":source JOIN :%s\r\n", chan); - send(cmd); -} - -void Irc::connect() { - pc.printf("Connecting to %s:%d...\n", network, port); - sock.connect(network, port); - pc.printf("Done.\n"); - connected = true; -} - -void Irc::disconnect() { - if (connected) { - pc.printf("Disconnecting.\n"); - sock.close(); - connected = false; - } -} - -void Irc::add(MessageHandler * handler) { - handlers.push_back(handler); -} - -bool Irc::read() { - if (!connected) return 0; - int ret = sock.receive(readbuffer, sizeof(readbuffer) - 1); - bool parsed = false; - if (ret >= 0) { - readbuffer[ret] = '\0'; - pc.printf("Received %d chars: ---%s--\n", ret, readbuffer); - for (int i = 0; i < ret; i++) { - parsebuffer[parseindex] = readbuffer[i]; - parseindex++; - if (readbuffer[i] == '\n') { - parsebuffer[parseindex] = '\0'; - parse(); - parsed = true; - parseindex = 0; - } - } - } - return parsed; -} - -void Irc::send(char * cmd) { - if (!connected) return; - int i = 0; - bool ok = true; - while (cmd[i] != '\0') { - i++; - if (i > 512) { - ok = false; - break; - } - } - if (!ok) return; - pc.printf("Sending: ---%s---\n", cmd); - sock.send_all(cmd, i); -} - -void Irc::handle(IrcMessage msg) { - pc.printf("Handling message from %s, to %s: %s\n", msg.from, msg.to, msg.msg); - for (int i = 0; i < handlers.size(); i++) { - IrcMessage out = handlers.at(i)->handle(msg); - if (out.to[0] != '\0') { - sprintf(out.from, "%s", nickname); - pc.printf("Need to send: ---%s--- from %s to %s.\n", out.msg, out.from, out.to); - char cmd[512]; - sprintf(cmd, "PRIVMSG %s :%s\r\n", out.to, out.msg); - send(cmd); - } - } -} - -void Irc::parse() { - pc.printf("Parsing: --%s--\n", parsebuffer); - if (setup && (!joined)) { - char cmd[256]; - sprintf(cmd, ":source JOIN :%s\r\n", channel); - send(cmd); - joined = true; - return; - } - if (!setup) { - char cmd[256]; - sprintf(cmd, "NICK %s\r\nUSER %s 0 * :Lester\r\n", nickname, nickname); - send(cmd); - setup = true; - return; - } - char * c = NULL; - c = strstr(parsebuffer, "PING"); - if (c != NULL) { - char cmd[] = "PONG\r\n"; - send(cmd); - } - c = strstr(parsebuffer, "PRIVMSG"); - if (c != NULL) { - char f[32]; - char t[32]; - char m[256]; - int i; - for (i = 1; i < 32; i++) { - if (parsebuffer[i] == '!') { - f[i - 1] = '\0'; - break; - } - f[i - 1] = parsebuffer[i]; - } - int nspace = 0; - bool inmsg = false; - int toindex = 0, msgindex = 0; - for (; i < sizeof(parsebuffer); i++) { - if (parsebuffer[i] == '\r') break; - if (parsebuffer[i] == '\n') break; - if (parsebuffer[i] == '\0') break; - if (parsebuffer[i] == ' ') { - nspace++; - } - if ((nspace == 2) && (parsebuffer[i] != ' ')) { - t[toindex] = parsebuffer[i]; - toindex++; - } - if (inmsg) { - m[msgindex] = parsebuffer[i]; - msgindex++; - } - if ((parsebuffer[i] == ':') && (!inmsg)) { - inmsg = true; - } - } - t[toindex] = '\0'; - m[msgindex] = '\0'; - IrcMessage msg(f, t, m); - handle(msg); - } -} \ No newline at end of file
--- a/irc.h Sat Aug 02 12:09:10 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#ifndef __mbed_irc_h__ -#define __mbed_irc_h__ - -#include "mbed.h" -#include "EthernetInterface.h" -#include <vector> - -class IrcMessage { - public: - IrcMessage(); - IrcMessage(char *, char *, char *); - char from[32], to[32], msg[256]; -}; - -class MessageHandler { - public: - MessageHandler() {}; - virtual IrcMessage handle(IrcMessage msg) {return IrcMessage();} -}; - -class Irc { - public: - Irc(char *, char *, int, char *); - void connect(); - void disconnect(); - void add(MessageHandler *); - void identify(char *); - void join(char *); - bool read(); - private: - void handle(IrcMessage); - void parse(); - void send(char *); - Serial pc; - TCPSocketConnection sock; - char network[64]; - char channel[64]; - int port; - char nickname[64]; - char password[64]; - bool ident, connected, setup, joined; - char readbuffer[512]; - char parsebuffer[512]; - int parseindex; - vector<MessageHandler *> handlers; -}; - -#endif \ No newline at end of file