//-----------------------------------------------------------------
//
// Nov-2019 J. Koellermeyer
//
// IFX RGB Shield with remote color mode control based on thingspeak
//
// https://de.mathworks.com/help/thingspeak/mqtt-publish-and-subscribe-with-esp8266.html
//
// board: Wemos D1
//
// requires one thingspeak channel with 4 fields
//
// field1: color id
// field2: heartbeat
// field3: barometric pressure in hPa
// field4: temperature times 10 in Celsius
//
//
//-----------------------------------------------------------------
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <Wire.h>
#include <RGBLEDLighting.h>
#include "WiFiAccess.h"
#include <Dps422.h>
//-----------------------------------------------------------------
#define BUILTIN_LED 2
// make sure the proper MAC address is enabled if connecting to IFX idn
const char* ssid = WIFI_SSID;
const char* password = WIFI_PASSWD;
//-----------------------------------------------------------------
Dps422 Dps422PressureSensor = Dps422();
struct DPSResult {
int temperature;
int pressure;
};
//-----------------------------------------------------------------
const char* server = "mqtt.thingspeak.com";
char mqttUserName[] = "Anything";
char mqttPass[] = "<thingspeak MQTT password>";
long readChannelID = 270552;
char readAPIKey[] = "<thingspeak channel read key>";
long writeChannelID = 270552;
char writeAPIKey[] = "<thingspeak channel write key>";
int fieldsToPublish[8]={0,1,1,1,0,0,0,0}; // Change to allow multiple fields.
int dataToPublish[8];
WiFiClient client;
PubSubClient mqttClient( client );
//-----------------------------------------------------------------
InfineonRGB LEDS;
int changeFlag = 0; // set if MQTT subscribe is triggered
int brightness;
int brightness_change_default = 40;
int brightness_change = 40;
bool brightness_decrease = false;
// trigger to see if device is still alive/online
unsigned long heartbeatIntervall = 5 * 60 * 1000; // 5 minutes
unsigned long lastHeartbeat = 0;
// pressure change
unsigned long lastDebounceTimePressure = 0;
unsigned long debouncePressureDelay = 100;
bool pressureAboveThres = false;
bool lastPressureAboveThres = false;
int pressureRef = 0;
int tempRef = 0;
/*
typedef enum{
White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Aqua, Teal, Blue, Navy, Fuchsia, Purple
}Colours;
*/
//-----------------------------------------------------------------
void setup() {
Serial.begin(9600);
LEDS.begin(); // Cycle and set everything to zero.
delay(10);
//led_test();
pinMode(BUILTIN_LED, OUTPUT);
digitalWrite(BUILTIN_LED, LOW);
WiFi.mode(WIFI_STA);
// mac_address();
// scan_wifi();
// delay(10000);
wificonnect();
mqttClient.setServer( server, 1883 ); // Set the MQTT broker details.
mqttClient.setCallback( mqttSubscriptionCallback ); // Set the MQTT message handler function.
delay(10);
setLEDMode(2);
delay(10);
//-------------------------------------------------------------
Dps422PressureSensor.begin(Wire);
delay(10);
measurePressure();
delay(10);
DPSResult a = measurePressure();
pressureRef = a.pressure;
tempRef = a.temperature;
Serial.print("Reference pressure: ");
Serial.println(pressureRef);
Serial.print("Reference temperature: ");
Serial.println(tempRef/10.0);
delay(10);
//-------------------------------------------------------------
// publish heartbeat to channel 2
dataToPublish[1] = 1;
dataToPublish[2] = pressureRef;
dataToPublish[3] = tempRef;
mqttPublish( writeChannelID, writeAPIKey, fieldsToPublish, dataToPublish );
delay(10);
}
//-------------------------------------------------------------------------------------
void loop() {
wificonnect();
if (!mqttClient.connected()) {
mqttConnect(); // Connect if MQTT client is not connected.
if(mqttSubscribe( readChannelID,1,readAPIKey,0 ) == 1 ){
Serial.println( "MQTT subscribed" );
} else {
Serial.println( "MQTT NOT subscribed" );
}
}
mqttClient.loop(); // Call the loop to maintain connection to the server.
// MQTT value changed
if (changeFlag){
changeFlag = 0;
}
delay(1);
//--------------------------
// heartbeat
if( millis() - lastHeartbeat > heartbeatIntervall ) {
Serial.println("Heartbeat");
lastHeartbeat = millis();
DPSResult a = measurePressure();
pressureRef = a.pressure;
tempRef = a.temperature;
Serial.print("Reference pressure: ");
Serial.println(pressureRef);
Serial.print("Reference temperature: ");
Serial.println(tempRef/10.0);
// publish heartbeat to channel 2
dataToPublish[1] = 1;
dataToPublish[2] = pressureRef;
dataToPublish[3] = tempRef;
mqttPublish( writeChannelID, writeAPIKey, fieldsToPublish, dataToPublish );
}
//--------------------------
// fade in/fade out
brightness = LEDS.I2CREAD(ADDRESS, READ_DIMMINGLEVEL); // Request for brightness level
if( brightness > 0 ) {
//Serial.println(brightness);
if( brightness > 4090 ) {
brightness_decrease = true;
}
if( brightness < (brightness_change + 1) ) {
brightness = 1;
brightness_decrease = false;
}
if( brightness_decrease ) {
brightness = brightness - brightness_change;
} else {
brightness = brightness + brightness_change;
if( brightness > 4090 ) {
brightness = 4095;
}
}
LEDS.SetDimmingLevel(brightness);
}
delay(10);
//------------------------------------------------------
// candle effect - includes debouncing
DPSResult a = measurePressure();
if( (a.pressure - pressureRef) > 2 ) {
pressureAboveThres = true;
}
if( pressureAboveThres && !lastPressureAboveThres ) {
lastDebounceTimePressure = millis();
lastPressureAboveThres = true;
Serial.print("Pust .... ");
Serial.println(a.pressure);
}
if( (millis() - lastDebounceTimePressure > debouncePressureDelay) && lastPressureAboveThres ) {
if( pressureAboveThres ) {
if( brightness > 0 ) {
Serial.println("Off");
LEDS.SetDimmingLevel(0x0000);
} else {
Serial.println("On");
LEDS.SetDimmingLevel(0x0FFF);
}
}
pressureAboveThres = false;
lastPressureAboveThres = false;
}
delay(10);
}
//-------------------------------------------------------------------------------------
void mac_address() {
uint8_t mac[6];
WiFi.macAddress(mac);
Serial.printf( "MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
}
//-------------------------------------------------------------------------------------
void scan_wifi() {
Serial.println("Start Wifi scan");
int n = WiFi.scanNetworks();
if (n == 0) {
Serial.println("No Wifi networks found");
} else {
Serial.println("Networks found:");
for (int i = 0; i < n; ++i) {
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(") ");
Serial.print(" [");
Serial.print(WiFi.channel(i));
Serial.println("] ");
delay(10);
}
}
Serial.println("Scan done");
Serial.println("");
}
//-------------------------------------------------------------------------------------
void led_test() {
Serial.println("LED test start");
LEDS.SetDimmingLevel(0x0FFF); // Maximum Brightness
LEDS.SetIntensityRGB(0x0FFF, 0x0000, 0x0000);
delay(1000);
LEDS.SetIntensityRGB(0x000, 0x0FFF, 0x0000);
delay(1000);
LEDS.SetIntensityRGB(0x0000, 0x0000, 0x0FFF);
delay(1000);
LEDS.SetIntensityRGB(0x0FFF, 0x0000, 0x0000);
delay(1000);
LEDS.SetIntensityRGB(0x000, 0x0FFF, 0x0000);
delay(1000);
LEDS.SetIntensityRGB(0x0000, 0x0000, 0x0FFF);
delay(1000);
LEDS.SetIntensityRGB(0x0FFF, 0x0000, 0x0000);
delay(1000);
LEDS.SetIntensityRGB(0x000, 0x0FFF, 0x0000);
delay(1000);
LEDS.SetIntensityRGB(0x0000, 0x0000, 0x0FFF);
delay(1000);
LEDS.SetDimmingLevel(0x0000);
Serial.println("LED test end");
}
//-------------------------------------------------------------------------------------
/**
* Process messages received from subscribed channel via MQTT broker.
* topic - Subscription topic for message.
* payload - Field to subscribe to. Value 0 means subscribe to all fields.
* mesLength - Message length.
*/
int mqttSubscriptionCallback( char* topic, byte* payload, unsigned int mesLength ) {
char p[mesLength + 1];
memcpy( p, payload, mesLength );
p[mesLength] = NULL;
Serial.print( "Value: ");
Serial.println(String(p) );
setLEDMode( String(p).toInt() );
changeFlag = 1;
}
//-------------------------------------------------------------------------------------
void mqttConnect() {
char clientID[ 9 ];
// Loop until connected.
while ( !mqttClient.connected() ) {
getID(clientID,8);
// Connect to the MQTT broker.
Serial.println( "Attempting MQTT connection..." );
if ( mqttClient.connect( clientID, mqttUserName, mqttPass ) ) {
Serial.println( "Connected with Client ID: '" + String( clientID ) + "', User '"+ String( mqttUserName ) + "', Pwd '"+String( mqttPass ) + "'");
} else {
Serial.println( "failed, rc = " );
// See https://pubsubclient.knolleary.net/api.html#state for the failure code explanation.
Serial.println( mqttClient.state() );
Serial.println( " Will try again in 5 seconds" );
delay(5000);
}
}
}
//-------------------------------------------------------------------------------------
/**
* Build a random client ID.
* clientID - Character array for output
* idLength - Length of clientID (actual length is one character longer for NULL)
*/
void getID(char clientID[], int idLength) {
static const char alphanum[] ="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
// Generate client ID.
for (int i = 0; i < idLength ; i++) {
clientID[ i ] = alphanum[ random( 51 ) ];
}
clientID[ idLength ] = '\0';
}
//-------------------------------------------------------------------------------------
/**
* Subscribe to fields of a channel.
* subChannelID - Channel to subscribe to.
* field - Field to subscribe to. Value 0 means subscribe to all fields.
* readKey - Read API key for the subscribe channel.
* unSub - Set to 1 for unsubscribe.
*/
int mqttSubscribe( long subChannelID, int field, char* readKey, int unsubSub ){
String myTopic;
// There is no field zero, so if field 0 is sent to subscribe to, then subscribe to the whole channel feed.
if (field == 0){
myTopic="channels/"+String( subChannelID )+"/subscribe/json/"+String( readKey );
} else {
myTopic="channels/"+String( subChannelID )+"/subscribe/fields/field"+String( field )+"/"+String( readKey );
}
Serial.println( "Subscribing to " +myTopic );
Serial.println( "State = " + String( mqttClient.state() ) );
if ( unsubSub == 1 ){
return mqttClient.unsubscribe(myTopic.c_str());
}
return mqttClient.subscribe( myTopic.c_str() ,0 );
}
//-------------------------------------------------------------------------------------
/**
* Publish to a channel
* pubChannelID - Channel to publish to.
* pubWriteAPIKey - Write API key for the channel to publish to.
* dataArray - Binary array indicating which fields to publish to, starting with field 1.
* fieldArray - Array of values to publish, starting with field 1.
*/
void mqttPublish(long pubChannelID, char* pubWriteAPIKey, int fieldArray[], int dataArray[]) {
int index = 0;
String dataString = "";
while (index < 8){
// Look at the field array to build the posting string to send to ThingSpeak.
if ( fieldArray[index] > 0 ){
dataString += "&field" + String( index+1 ) + "=" + String( dataArray[index] );
}
index++;
}
//Serial.println( dataString );
// Create a topic string and publish data to ThingSpeak channel feed.
String topicString ="channels/" + String( pubChannelID ) + "/publish/"+String( pubWriteAPIKey );
Serial.println( topicString );
mqttClient.publish( topicString.c_str(), dataString.c_str() );
Serial.println( "Published to channel " + String( pubChannelID ) );
}
//-------------------------------------------------------------------------------------
void setLEDMode( int mode ) {
//typedef enum{
// White, Silver, Gray, Black, Red, Maroon, Yellow, Olive, Lime, Green, Aqua, Teal, Blue, Navy, Fuchsia, Purple
// }Colours;
digitalWrite(BUILTIN_LED, HIGH); // LED on
if( mode == 0 ) {
digitalWrite(BUILTIN_LED, LOW); // LED off
LEDS.SetDimmingLevel(0x0000);
} else if( mode == 1) {
LEDS.SetDimmingLevel(0x0FFF);
LEDS.SetColor(Red);
brightness_change = brightness_change_default;
} else if( mode == 2) {
LEDS.SetDimmingLevel(0x0FFF);
LEDS.SetColor(Green);
brightness_change = brightness_change_default;
} else if( mode == 3) {
LEDS.SetDimmingLevel(0x0FFF);
LEDS.SetColor(Blue);
brightness_change = brightness_change_default;
} else if( mode == 4) {
LEDS.SetDimmingLevel(0x0FFF);
LEDS.SetColor(White);
brightness_change = brightness_change_default;
} else if( mode == 5) {
LEDS.SetDimmingLevel(0x0FFF);
LEDS.SetColor(Yellow);
brightness_change = brightness_change_default;
} else if( mode == 6) {
LEDS.SetDimmingLevel(0x0FFF);
LEDS.SetColor(Fuchsia);
brightness_change = brightness_change_default;
} else if( mode == 7) {
brightness_change = brightness_change * 2;
}
}
//-------------------------------------------------------------------------------------
DPSResult measurePressure() {
float temperature;
float pressure;
int16_t oversampling = 2;
int16_t ret;
DPSResult a;
a.temperature = 0;
a.pressure = 0;
ret = Dps422PressureSensor.measureTempOnce(temperature, oversampling);
if (ret != 0) {
Serial.print("FAIL! ret = ");
Serial.println(ret);
} else {
a.temperature = (int) (temperature * 10);
//Serial.print("Temperature: ");
//Serial.print(temperature);
//Serial.println("C");
}
ret = Dps422PressureSensor.measurePressureOnce(pressure, oversampling);
if (ret != 0) {
Serial.print("FAIL! ret = ");
Serial.println(ret);
} else {
a.pressure = (int)(pressure/100);
//Serial.print("Pressure: ");
//Serial.print((int)(pressure/100));
//Serial.println("hP");
}
return a;
}
//-------------------------------------------------------------------------------------
void wificonnect() {
if( WiFi.status() != WL_CONNECTED ) {
Serial.print("connecting to ");
Serial.print(ssid);
WiFi.begin(ssid, password);
int i = 0;
while (WiFi.status() != WL_CONNECTED && i < 50) {
delay(200);
Serial.print(".");
i++;
}
Serial.print("");
if ( WiFi.status() == WL_CONNECTED ) {
Serial.println("WiFi connected");
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
Serial.print("RSSI: ");
Serial.println(WiFi.RSSI());
} else {
Serial.println("Connection failed");
}
}
}
Comments