Snippets

Pete Matthews H801 code with MQTT and Wifi onboarding

Created by Pete Matthews last modified
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
/*
 * This bespoke "hack" code is for the H801 (LIXADA) control module. 
 * The H801 module is based on an ESP8266 and can drive a RGB LED strip of lights. 
 * This code responds to MQTT commands
 * 
 * N.B. You have to solder 6 header pins on the H801 - this is so you can connect a cheap FDTI USB for programming.
 * N.B. You have to store your network SSID and password in the code variables *ssid and *pass (see below in code)
 * 
 * When all is done and the module connected and powered up for the first time, a new Wifi AP point will be created
 * for IP 192.168.4.1. If you signon to this using "password", you can set:
 * - SSID to be used 
 * - SSID password
 * - MQTT IP address
 * - MQTT port (usually 1883)
 * Once all is set - send hex values to MQTT topic ESP_RGB_1 e.g. ffffff or 000000
 */
#include <FS.h>                   //this needs to be first, or it all crashes and burns...

#include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino

//needed for library
#include <DNSServer.h>
#include <ESP8266WebServer.h>
#include <PubSubClient.h>
#include <WiFiManager.h>          //https://github.com/tzapu/WiFiManager

#include <ArduinoJson.h>          //https://github.com/bblanchon/ArduinoJson

void LED_RED();
void LED_GREEN();
void LED_BLUE();
void change_LED();
int convertToInt(char upper,char lower);

#define PWM_VALUE 63
int gamma_table[PWM_VALUE+1] = {
    0, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 8, 9, 10,
    11, 12, 13, 15, 17, 19, 21, 23, 26, 29, 32, 36, 40, 44, 49, 55,
    61, 68, 76, 85, 94, 105, 117, 131, 146, 162, 181, 202, 225, 250,
    279, 311, 346, 386, 430, 479, 534, 595, 663, 739, 824, 918, 1023
};


// RGB FET
#define redPIN    15 //12
#define greenPIN  13 //15
#define bluePIN   12 //13

// onboard green LED D1
#define LEDPIN    5
// onboard red LED D2
#define LED2PIN   1

// note 
// TX GPIO2 @Serial1 (Serial ONE)
// RX GPIO3 @Serial    


#define LEDoff digitalWrite(LEDPIN,HIGH)
#define LEDon digitalWrite(LEDPIN,LOW)

#define LED2off digitalWrite(LED2PIN,HIGH)
#define LED2on digitalWrite(LED2PIN,LOW)

int led_delay_red = 0;
int led_delay_green = 0;
int led_delay_blue = 0;
#define time_at_colour 1000 
unsigned long TIME_LED_RED = 0;
unsigned long TIME_LED_GREEN = 0;
unsigned long TIME_LED_BLUE = 0;
int RED, GREEN, BLUE; 
int RED_A = 0;
int GREEN_A = 0; 
int BLUE_A = 0;


//define your default values here, if there are different values in config.json, they are overwritten.
//length should be max size + 1 
char mqtt_server[40] = "192.168.1.5";
char mqtt_port[6] = "1083";
//char blynk_token[33] = "YOUR_BLYNK_TOKEN";
//default custom static IP
char static_ip[16] = "192.168.1.123";
char static_gw[16] = "192.168.1.1";
char static_sn[16] = "255.255.255.0";

WiFiClient espClient;
PubSubClient client(espClient);
long lastMsg = 0;
char msg[50];
int value = 0;

//flag for saving data
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () {
  Serial1.println("Should save config");
  shouldSaveConfig = true;
}


void callback(char* topic, byte* payload, unsigned int length) {
  LEDon;
  Serial1.print("Message arrived [");
  Serial1.print(topic);
  Serial1.print("] ");
  for (int i = 0; i < length; i++) {
    Serial1.print((char)payload[i]);
  }
  Serial1.println();

//       String hexRGB =(char)payload[0,1];
         String hexRGB = String((char*)payload);      
        // convert HEX to RGB
  Serial1.println();
  Serial1.print(hexRGB);
  Serial1.println();
        hexRGB.toUpperCase();
        char c[6];
        hexRGB.toCharArray(c,7);
        long r = convertToInt(c[0],c[1]); //red
        long g = convertToInt(c[2],c[3]); //green
        long b = convertToInt(c[4],c[5]); //blue 
 //Serial1.println(r);      Serial1.println(g);     Serial1.println(b);     
        // set value of RGB controller
        int red = map(r,0,255,0,PWM_VALUE); 
        red = constrain(red,0,PWM_VALUE);
        int green = map(g,0,255,0,PWM_VALUE);
        green = constrain(green, 0, PWM_VALUE);
        int blue = map(b,0,255,0,PWM_VALUE);
        blue = constrain(blue,0,PWM_VALUE);
      
        RED = gamma_table[red];
        GREEN = gamma_table[green];
        BLUE = gamma_table[blue];
 //       Serial1.println(RED);      Serial1.println(GREEN);     Serial1.println(BLUE);    
        change_LED();

 while ((RED != RED_A) or (GREEN != GREEN_A) or (BLUE != BLUE_A)) {
  if(millis() - TIME_LED_RED >= led_delay_red){
    TIME_LED_RED = millis();
    LED_RED();
  };
//  }else{
  
  if(millis() - TIME_LED_GREEN >= led_delay_green){
    TIME_LED_GREEN = millis();
    LED_GREEN();
  };
//  }else{
  
  if(millis() - TIME_LED_BLUE >= led_delay_blue){
    TIME_LED_BLUE = millis();
    LED_BLUE();
  };
//  }}};
//  delayMicroseconds(200);

  };
  
    LEDoff;

//        Serial1.println(RED_A);      Serial1.println(GREEN_A);     Serial1.println(BLUE_A);  

  LEDoff;
}

void reconnect() {
  // Loop until we're reconnected
  while (!client.connected()) {
    LEDon; 
    LED2on;
    Serial1.print("Attempting MQTT connection...");
    // Attempt to connect
    if (client.connect("ESP8266Client")) {
      Serial1.println("connected");
      // Once connected, publish an announcement...
      client.publish("outTopic", "ESP_RGB_1 is now connected!");
      // ... and resubscribe
      client.subscribe("ESP_RGB_1");
      LEDoff;
      LED2on;
    } else {
      Serial1.print("failed, rc=");
      Serial1.print(client.state());
      Serial1.println(" try again in 5 seconds");
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

void setup() {
  LEDon;
  LED2on;
  // put your setup code here, to run once:
  pinMode(LEDPIN, OUTPUT);  
  pinMode(LED2PIN, OUTPUT);  
  pinMode(redPIN, OUTPUT);
  pinMode(greenPIN, OUTPUT);
  pinMode(bluePIN, OUTPUT);
  
  
  Serial1.begin(115200);
  Serial1.println();

  LEDoff;
  LED2off;

  //clean FS, for testing
//  SPIFFS.format();                                                   // Comment this out after testing!

  //read configuration from FS json
  Serial1.println("mounting FS...");

  if (SPIFFS.begin()) {
    Serial1.println("mounted file system");
    if (SPIFFS.exists("/config.json")) {
      //file exists, reading and loading
      Serial1.println("reading config file");
      File configFile = SPIFFS.open("/config.json", "r");
      if (configFile) {
        Serial1.println("opened config file");
        size_t size = configFile.size();
        // Allocate a buffer to store contents of the file.
        std::unique_ptr<char[]> buf(new char[size]);

        configFile.readBytes(buf.get(), size);
        DynamicJsonBuffer jsonBuffer;
        JsonObject& json = jsonBuffer.parseObject(buf.get());
        json.printTo(Serial);
        if (json.success()) {
          Serial1.println("\nparsed json");

          strcpy(mqtt_server, json["mqtt_server"]);
          strcpy(mqtt_port, json["mqtt_port"]);
//          strcpy(blynk_token, json["blynk_token"]);

          if(json["ip"]) {
            Serial1.println("setting custom ip from config");
            //static_ip = json["ip"];
            strcpy(static_ip, json["ip"]);
            strcpy(static_gw, json["gateway"]);
            strcpy(static_sn, json["subnet"]);
            //strcat(static_ip, json["ip"]);
            //static_gw = json["gateway"];
            //static_sn = json["subnet"];
            Serial1.println(static_ip);
/*            Serial1.println("converting ip");
            IPAddress ip = ipFromCharArray(static_ip);
            Serial1.println(ip);*/
          } else {
            Serial1.println("no custom ip in config");
          }
        } else {
          Serial1.println("failed to load json config");
        }
      }
    }
  } else {
    Serial1.println("failed to mount FS");
  }
  //end read
  Serial1.println(static_ip);
//  Serial1.println(blynk_token);
  Serial1.println(mqtt_server);


  // The extra parameters to be configured (can be either global or just in the setup)
  // After connecting, parameter.getValue() will get you the configured value
  // id/name placeholder/prompt default length
  WiFiManagerParameter custom_mqtt_server("server", "mqtt server", mqtt_server, 40);
  WiFiManagerParameter custom_mqtt_port("port", "mqtt port", mqtt_port, 5);
//  WiFiManagerParameter custom_blynk_token("blynk", "blynk token", blynk_token, 34);

  //WiFiManager
  //Local intialization. Once its business is done, there is no need to keep it around
  WiFiManager wifiManager;

  //set config save notify callback
  wifiManager.setSaveConfigCallback(saveConfigCallback);

  //set static ip
  IPAddress _ip,_gw,_sn;
  _ip.fromString(static_ip);
  _gw.fromString(static_gw);
  _sn.fromString(static_sn);

  wifiManager.setSTAStaticIPConfig(_ip, _gw, _sn);
  
  //add all your parameters here
  wifiManager.addParameter(&custom_mqtt_server);
  wifiManager.addParameter(&custom_mqtt_port);
//  wifiManager.addParameter(&custom_blynk_token);

  //reset settings - for testing
//  wifiManager.resetSettings();                                                      // Comment this out after testing!

  //set minimu quality of signal so it ignores AP's under that quality
  //defaults to 8%
  wifiManager.setMinimumSignalQuality();
  
  //sets timeout until configuration portal gets turned off
  //useful to make it all retry or go to sleep
  //in seconds
  //wifiManager.setTimeout(120);

  //fetches ssid and pass and tries to connect
  //if it does not connect it starts an access point with the specified name
  //here  "AutoConnectAP"
  //and goes into a blocking loop awaiting configuration
  LEDon;
  LED2off;
  if (!wifiManager.autoConnect("AutoConnectAP", "password")) {
    Serial1.println("failed to connect and hit timeout");
    delay(3000);
    //reset and try again, or maybe put it to deep sleep
    ESP.reset();
    delay(5000);
  }

  //if you get here you have connected to the WiFi
  LEDon;
  LED2on;
  Serial1.println("connected...yeey :)");

  //read updated parameters
  strcpy(mqtt_server, custom_mqtt_server.getValue());
  strcpy(mqtt_port, custom_mqtt_port.getValue());
//  strcpy(blynk_token, custom_blynk_token.getValue());

  //save the custom parameters to FS
  if (shouldSaveConfig) {
    Serial1.println("saving config");
    DynamicJsonBuffer jsonBuffer;
    JsonObject& json = jsonBuffer.createObject();
    json["mqtt_server"] = mqtt_server;
    json["mqtt_port"] = mqtt_port;
//    json["blynk_token"] = blynk_token;

    json["ip"] = WiFi.localIP().toString();
    json["gateway"] = WiFi.gatewayIP().toString();
    json["subnet"] = WiFi.subnetMask().toString();

    File configFile = SPIFFS.open("/config.json", "w");
    if (!configFile) {
      Serial1.println("failed to open config file for writing");
    }

    json.prettyPrintTo(Serial);
    json.printTo(configFile);
    configFile.close();
    //end save
  }

  Serial1.println("local ip");
  Serial1.println(WiFi.localIP());
  Serial1.println(WiFi.gatewayIP());
  Serial1.println(WiFi.subnetMask());

  client.setServer(mqtt_server, 1883);
  client.setCallback(callback);

}



void change_LED()
{
  int diff_red = abs(RED-RED_A);
  if(diff_red > 0){
    led_delay_red = time_at_colour / abs(RED-RED_A); 
  }else{
    led_delay_red = time_at_colour / 1023; 
  }
  
  int diff_green = abs(GREEN-GREEN_A);
  if(diff_green > 0){
    led_delay_green = time_at_colour / abs(GREEN-GREEN_A);
  }else{
    led_delay_green = time_at_colour / 1023; 
  }
  
  int diff_blue = abs(BLUE-BLUE_A);
  if(diff_blue > 0){
    led_delay_blue = time_at_colour / abs(BLUE-BLUE_A); 
  }else{
    led_delay_blue = time_at_colour / 1023; 
  }
  
}

void LED_RED()
{
  if(RED != RED_A){
    if(RED_A > RED) RED_A = RED_A - 1;
    if(RED_A < RED) RED_A++;
    analogWrite(redPIN, RED_A);
  }
}

void LED_GREEN()
{
  if(GREEN != GREEN_A){
    if(GREEN_A > GREEN) GREEN_A = GREEN_A - 1;
    if(GREEN_A < GREEN) GREEN_A++;
    analogWrite(greenPIN, GREEN_A);
  }
}
  
void LED_BLUE()
{
  if(BLUE != BLUE_A){
    if(BLUE_A > BLUE) BLUE_A = BLUE_A - 1;
    if(BLUE_A < BLUE) BLUE_A++;
    analogWrite(bluePIN, BLUE_A);
  }
}

int convertToInt(char upper,char lower)
{
  int uVal = (int)upper;
  int lVal = (int)lower;
  uVal = uVal >64 ? uVal - 55 : uVal - 48;
  uVal = uVal << 4;
  lVal = lVal >64 ? lVal - 55 : lVal - 48;
  return uVal + lVal;
}


void loop() {
  // put your main code here, to run repeatedly:


  if (!client.connected()) {
    reconnect();
  }
  client.loop();

//  long now = millis();
//  if (now - lastMsg > 2000) {
//    lastMsg = now;
//    ++value;
//    snprintf (msg, 75, "hello world #%ld", value);
//    Serial1.print("Publish message: ");
//    Serial1.println(msg);
//    client.publish("outTopic", msg);
//  }
}

Comments (0)

HTTPS SSH

You can clone a snippet to your computer for local editing. Learn more.