├── Readme.md └── esp_sketch └── esp_sketch.ino /Readme.md: -------------------------------------------------------------------------------- 1 | #Readme ESP8266 2 | This Project is for those who want to speak MQTT with a microcontroller that has no WiFi capabilities. You will speak serial to an ESP8266 and the ESP will handle all the WiFi and MQTT stuff for you. 3 | 4 | ## Compile/Install 5 | 6 | I used arduino IDE just from the arduino website and configured it in a way that it is possible to programm EPS's with it. Once thats done(Please refer to https://github.com/esp8266/Arduino for exact informatin) you have to download the PubSubClient library from knolleary (https://github.com/knolleary/pubsubclient). You can just download and extract it to your arduino installation library folder. In my case it was ~/Downloads/arduino1.6.8/libraries. Once thats done you need the ESP8266Wifi library but this should be available automatically if you follow the instructions for the esp8266-arduino IDE. Once you have all that in place you can open a new sketch and copy & paste the contents of esp_sketch/esp_sketch.ino. If you have everything installed and running you can use the following commands to communicate with the ESP: 7 | 8 | ## Usage of the UART Interface 9 | 10 | The Task of the ESP is to be an MQTT2UART-Gateway. After you flashed the code you should be confronted with the following Message 11 | 12 | ``` 13 | need to be configured. 14 | Config me like this: 15 | ``` 16 | 17 | ### How to config 18 | You can choose any "delimiter"-character which ist not '\r'. Choose one that does not appear within the IP-address, WLAN-passphrase or the topics. The program uses the first character it receives as the delimiter. Put the IP-adress between the first and second occurence of the delimiter, the WLAN-SSID between the second and the third, the password between third and the fourth and after that you can list all topics you want to subscribe to delimited by the delimiter. Do not put the delimiter at the end of the config String. The string has to end with '\r' (carriage return). 19 | 20 | **Example** 21 | 22 | If you want to attach to an MQTT Server at Port 1883 (this is hardcoded for simplicity) at the IP 10.0.0.1, SSID: klausdieter and password: brunhildebrigitte and you want to subscribe to the topics /lotto /gluecksspirale /bingo you have to use the following configstring 23 | 24 | `%10.0.0.1%klausdieter%brunhildebrigitte%/lotto%/gluecksspirale%aktionmensch\r` 25 | 26 | The response should look like this: 27 | 28 | ``` 29 | System configured. Here is your config: 30 | MQTT-Server: 10.0.0.1 31 | SSID: klausdieter 32 | pw: brunhildebrigitte 33 | You subscribed to 3 topics. 34 | /lotto 35 | /gluecksspirale 36 | /bingo 37 | Attempting MQTT connection... 38 | MQTT Connected 39 | 40 | ``` 41 | 42 | ### Some things to say about the Output 43 | As you may have seen every line that says nothing about a subscribed topic starts with ``. If a line says something about a subscribed topic the output follows this syntax: 44 | `:\r` 45 | ### Publish over UART 46 | Once the ESP is configured you can publish messages over UART using the following input: 47 | 48 | `\r` 49 | -------------------------------------------------------------------------------- /esp_sketch/esp_sketch.ino: -------------------------------------------------------------------------------- 1 | // Dreist geklaut. Bei Ihm hier: https://github.com/ItKindaWorks/ESP8266 2 | #include 3 | #include 4 | 5 | // Der ESP wird als Ausgabe entweder und darauf folgende Debuggingmessages ausgeben 6 | // oder /topic/subtopic:message. 7 | // Server 8 | String s_mqtt_server = ""; 9 | const char* mqtt_server; 10 | // SSID 11 | String s_ssid = ""; 12 | const char* ssid; 13 | // WLAN passwd 14 | String s_pw = ""; 15 | const char* password; 16 | // The Topics to subscribe to 17 | const char* subTopics[255]; 18 | String s_subTopics[255]; 19 | int topics = 0; 20 | // von Beginn an ist der ESP erst einmal nicht konfiguriert. 21 | boolean configured = false; 22 | // Diese Funktion wird aufgerufen wenn etwas neues an ein abonniertes 23 | // Thema gesendet wird. 24 | void callback(char* topic, byte* payload, unsigned int length) { 25 | Serial.print(topic); 26 | Serial.print(":"); 27 | // Einmal die ganze Payload durcharbeiten... 28 | for(int i = 0; i < length; i++) { 29 | // und Seriell ausgeben 30 | Serial.print((char)payload[i]); 31 | } 32 | // Am ende Newline. 33 | Serial.println(""); 34 | } 35 | 36 | WiFiClient wifiClient; 37 | PubSubClient client(mqtt_server, 1883, callback, wifiClient); 38 | 39 | void setup() { 40 | // Output auf 115200 baud 41 | Serial.begin(115200); 42 | // Konfiguration starten. 43 | configure(); 44 | } 45 | 46 | void loop() { 47 | // wenn WLAN und MQTT nicht verbunden dann neue connecten 48 | if (!client.connected() && WiFi.status() == 3) { 49 | reconnect(); 50 | } 51 | // Hier kommt man erst hin wenn die Verbindung steht und wenn man hier ankommt 52 | // dann einfach nur die Verbindung halten. 53 | client.loop(); 54 | // Dieses warten braucht der ESP anscheinend fuer die WLAN-Verwaltung. 55 | delay(20); 56 | 57 | // maybe someone wants to publish something so lets check the serial line: 58 | serial_publish(); 59 | } 60 | 61 | 62 | 63 | void reconnect() { 64 | // Wenn nicht verbunden dann wieder verbinden 65 | if(WiFi.status() != WL_CONNECTED){ 66 | Serial.print(" Connecting to "); 67 | Serial.println(ssid); 68 | // Das verbinden geschieht durch simples warten 69 | while (WiFi.status() != WL_CONNECTED) { 70 | delay(500); 71 | } 72 | 73 | //print out some more debug once connected 74 | Serial.println(" WLAN connected"); 75 | Serial.print(" IP address: "); 76 | Serial.println(WiFi.localIP()); 77 | } 78 | 79 | // Wenn wir verbunden sind dann soll es losgehen mit dem herstellen der 80 | // MQTT Verbindung 81 | if(WiFi.status() == WL_CONNECTED){ 82 | Serial.print(" Attempting MQTT connection to: "); 83 | Serial.println(mqtt_server); 84 | client.setServer(mqtt_server, 1883); 85 | //if connected, subscribe to the topic(s) we want to be notified about 86 | if (client.connect(WiFi.localIP().toString().c_str())) { 87 | Serial.println(" MQTT Connected"); 88 | for(int i = 0; i < topics; i++) { 89 | client.subscribe(subTopics[i]); 90 | } 91 | } 92 | } 93 | } 94 | // this method configures the ESP, once it is done it is never called again. 95 | void configure() { 96 | // Debug Output 97 | Serial.println(" need to be configured."); 98 | Serial.println(" Config me like this:"); 99 | // The whole config string will be collected into this one and after that it will be divided into its subparts 100 | String config = ""; 101 | // just run if you need to 102 | while(configured == false) { 103 | // just read Data if it is available 104 | while(Serial.available()) { 105 | // read in tmpvar 106 | char c = (char) Serial.read(); 107 | // if it is the end of the config (new line), then start parsing, if not just concat( see else branch at the bottom) 108 | if(c=='\r') { 109 | // set configured, so it is not run again 110 | configured = true; 111 | // the delimcount starts at one because the first char has to be one 112 | int delimcount = 1; 113 | // this number tells us the position in the config string where the first char describing topics is 114 | int startOfTopics = 0; 115 | // as i said first char is delim 116 | char delim = config.charAt(0); 117 | // parse every little char start with 1 because 0 is delim 118 | for(int i = 1; i < config.length(); i++) { 119 | // either it is the delim 120 | if(config.charAt(i) == delim) { 121 | // increment the delims 122 | delimcount++; 123 | // after for delims every char belongs to a topicname 124 | if(delimcount == 4) { 125 | startOfTopics = i + 1; 126 | } 127 | // or it is something else 128 | } else { 129 | // between 1 and to append to the ip 130 | if(delimcount == 1) { 131 | s_mqtt_server.concat(config.charAt(i)); 132 | } // between 2 and three to the ssid 133 | if(delimcount == 2) { 134 | s_ssid.concat(config.charAt(i)); 135 | } // and between 3 and for to the pw 136 | if(delimcount == 3) { 137 | s_pw.concat(config.charAt(i)); 138 | } 139 | } 140 | } 141 | // write pointers. 142 | mqtt_server=s_mqtt_server.c_str(); 143 | ssid=s_ssid.c_str(); 144 | password=s_pw.c_str(); 145 | 146 | 147 | // the amount of topics is the delimiters - 3 for ip, ssid and pw 148 | topics = delimcount - 3; 149 | if(topics < 1) { // you need to subscribe to at least one topic or 150 | Serial.println(" Sorry you subscribed to no topic."); 151 | // the esp will reboot 152 | abort(); 153 | } 154 | // parsing of the topics 155 | // array of stringbuffers 156 | // start at topic zero 157 | int topiccounter = 0; 158 | // for all chars starting at "startOfTopics" 159 | for(int i = startOfTopics; i < config.length(); i++) { 160 | // if delim 161 | if(config.charAt(i) == delim) { 162 | // write to array 163 | subTopics[topiccounter] = s_subTopics[topiccounter].c_str(); 164 | // and use next index 165 | topiccounter++; 166 | 167 | } else { 168 | // if ordinary char just append 169 | s_subTopics[topiccounter].concat(config.charAt(i)); 170 | } 171 | } 172 | // last one has to be done manually because there is no delim behind it. 173 | subTopics[topics - 1] = s_subTopics[topics - 1].c_str(); 174 | // Print a bunch of debug stuff 175 | Serial.println(" System configured. Here is your config: "); 176 | Serial.print(" MQTT-Server: "); 177 | Serial.println(mqtt_server); 178 | Serial.print(" SSID: "); 179 | Serial.println(ssid); 180 | Serial.print(" pw: "); 181 | Serial.println(s_pw); 182 | Serial.print(" You subscribed to "); 183 | Serial.print(topics); 184 | Serial.println(" topics."); 185 | for(int i = 0; i < topics; i++) { 186 | Serial.print(" "); 187 | Serial.println(subTopics[i]); 188 | } 189 | 190 | // WLAN anschalten und verbinden 191 | WiFi.disconnect(true); 192 | WiFi.begin(ssid, password); 193 | WiFi.mode(WIFI_STA); 194 | delay(2000); 195 | reconnect(); 196 | // if the current char was not '\r' just concat the char and move on. 197 | } else { 198 | config.concat(c); 199 | } 200 | } 201 | } 202 | } 203 | void serial_publish() { 204 | if(Serial.available()) { 205 | 206 | // create Buffer: 207 | String buf = ""; 208 | String topic = ""; 209 | String message = ""; 210 | char delim; 211 | // get the whole line 212 | while(Serial.available()) { 213 | // append 214 | char c = Serial.read(); 215 | // process the lne after return 216 | if(c == '\r') { 217 | // delim is char 0 218 | char delim = buf.charAt(0); 219 | int delimcount = 1; 220 | // process the whole message 221 | for(int i = 1; i < buf.length(); i++) { 222 | // if delim 223 | if(buf.charAt(i) == delim) { 224 | // inc delimcount 225 | delimcount++; 226 | } 227 | else { 228 | //if topic part 229 | if(delimcount == 1) { 230 | topic.concat(buf.charAt(i)); 231 | } else { 232 | // everything else belongs to the message 233 | message.concat(buf.charAt(i)); 234 | 235 | } 236 | } 237 | } 238 | // do a loop and publish 239 | if(client.loop() && client.publish(topic.c_str(), message.c_str())) { 240 | Serial.println(" Successfully sent your message."); 241 | } else { 242 | Serial.println(" Sorry, wasn't able to send your message."); 243 | } 244 | } 245 | // if char != return concat to buffer 246 | else { 247 | buf.concat(c); 248 | } 249 | delay(1); 250 | } 251 | } 252 | } 253 | --------------------------------------------------------------------------------