2022-06-30 14:27:42 +00:00
# include <bitset>
# include <string>
// #include <ArduinoJson.h>
# include <WiFi.h>
# include "settings.h"
# ifdef WIFI_ENTERPRISE_ENABLED
// Ref https://github.com/martinius96/ESP32-WPA2-enterprise/blob/master/ESP32_WPA2enterprise.ino
# include "esp_wpa2.h"
# include "esp_wifi.h"
# endif
# ifdef MQTT_NO_TLS
# include <WiFiClient.h>
# else
# include <WiFiClientSecure.h>
# endif
2022-06-30 15:01:26 +00:00
# include <PubSubClient.h>
2022-06-30 14:27:42 +00:00
// These libraries need installing in the Arduino IDE Library Manager (if you install the BME280 one it should prompt for the unified sensor library automatically)
# include <Adafruit_Sensor.h>
# include <Adafruit_BME280.h>
// WAS D5 D6 D7
# define MULTIPLEX_PINA 17
# define MULTIPLEX_PINB 16
# define MULTIPLEX_PINC 4
// WAS A0
# define ANALOG_PIN 34
/*
000 0
001 1
010 2
011 3
100 4
101 5
110 6
111 7
*/
# define SOIL_A 0
# define SOIL_B 6
# define WATER_LEVEL_A 2
# define WATER_LEVEL_B 4
# define REFERENCE_VOLTAGE 3.3
// Ref https://stackoverflow.com/a/523737/1460422
# define CHECK_BIT(var,pos) ((var) & (1<<(pos)))
2022-07-04 15:47:10 +00:00
# ifdef MQTT_NO_TLS
2022-06-30 14:27:42 +00:00
WiFiClient transport ;
2022-07-04 15:47:10 +00:00
# else
WiFiClientSecure transport ;
2022-06-30 14:27:42 +00:00
# endif
PubSubClient mqtt ;
Adafruit_BME280 bme ; // I2C
void connect_wifi ( ) {
# ifndef WIFI_ENTERPRISE_ENABLED
Serial . print ( " personal " ) ;
WiFi . begin ( WIFI_SSID , WIFI_PASSWORD ) ;
# else
Serial . print ( " enterprise " ) ;
// Ref https://github.com/martinius96/ESP32-WPA2-enterprise/blob/master/ESP32_WPA2enterprise.ino
// For ESP32 ONLY! For esp8266, see the code with the esp8266-last tag, which is the last commit that supports the esp8266.
WiFi . disconnect ( true ) ;
WiFi . mode ( WIFI_STA ) ;
const char * user = WIFI_ENTERPRISE_USERNAME ;
const char * pass = WIFI_ENTERPRISE_PASSWORD ;
// 'esp_wifi_sta_wpa2_ent_set_identity' was not declared in this scope :-(
2022-06-30 15:01:26 +00:00
esp_wpa2_config_t config = WPA2_CONFIG_INIT_DEFAULT ( ) ;
2022-06-30 14:27:42 +00:00
esp_wifi_sta_wpa2_ent_set_identity ( ( uint8_t * ) user , strlen ( user ) ) ;
esp_wifi_sta_wpa2_ent_set_username ( ( uint8_t * ) user , strlen ( user ) ) ;
esp_wifi_sta_wpa2_ent_set_password ( ( uint8_t * ) pass , strlen ( pass ) ) ;
2022-06-30 15:01:26 +00:00
esp_wifi_sta_wpa2_ent_enable ( & config ) ;
2022-06-30 14:27:42 +00:00
// esp_wpa2_config_t config = WPA2_CONFIG_INIT_DEFAULT();
// esp_wifi_sta_wpa2_ent_enable(&config);
WiFi . begin ( WIFI_SSID ) ;
# endif
}
float read_analog ( int channel ) {
const char * bin = std : : bitset < 8 > ( channel ) . to_string ( ) . c_str ( ) ;
bool b0 = bin [ 7 ] = = u ' 1 ' ;
bool b1 = bin [ 6 ] = = u ' 1 ' ;
bool b2 = bin [ 5 ] = = u ' 1 ' ;
digitalWrite ( MULTIPLEX_PINA , b2 ) ;
digitalWrite ( MULTIPLEX_PINB , b1 ) ;
digitalWrite ( MULTIPLEX_PINC , b0 ) ;
int rawValue = analogRead ( ANALOG_PIN ) ;
float parsedValue = ( ( float ) rawValue ) / 1024.0 * REFERENCE_VOLTAGE ;
return parsedValue ;
}
2022-07-04 15:47:10 +00:00
void connect_mqtt ( ) {
if ( ! mqtt . connect (
( " autoplant_ " + String ( random ( 0 , 999999 ) ) ) . c_str ( ) ,
MQTT_USERNAME , MQTT_PASSWORD )
) {
/* Ref https://pubsubclient.knolleary.net/api#state
- 4 : MQTT_CONNECTION_TIMEOUT - the server didn ' t respond within the keepalive time
- 3 : MQTT_CONNECTION_LOST - the network connection was broken
- 2 : MQTT_CONNECT_FAILED - the network connection failed
- 1 : MQTT_DISCONNECTED - the client is disconnected cleanly
0 : MQTT_CONNECTED - the client is connected
1 : MQTT_CONNECT_BAD_PROTOCOL - the server doesn ' t support the requested version of MQTT
2 : MQTT_CONNECT_BAD_CLIENT_ID - the server rejected the client identifier
3 : MQTT_CONNECT_UNAVAILABLE - the server was unable to accept the connection
4 : MQTT_CONNECT_BAD_CREDENTIALS - the username / password were rejected
5 : MQTT_CONNECT_UNAUTHORIZED - the client was not authorized to connect
*/
int error_code = mqtt . state ( ) ;
Serial . println ( " failed, error code " + String ( error_code ) ) ;
while ( true ) delay ( 10000 ) ;
}
Serial . println ( " ok " ) ;
}
2022-07-13 01:01:31 +00:00
void check_mqtt ( bool reset = false ) {
2022-07-04 15:47:10 +00:00
if ( mqtt . connected ( ) = = 0 ) {
2022-07-13 01:01:31 +00:00
if ( reset ) {
Serial . print ( " MQTT reconnect: " ) ;
connect_mqtt ( ) ;
delay ( 2000 ) ;
if ( mqtt . connected ( ) = = 0 ) {
Serial . println ( " failed! rebooting. \n \n " ) ;
ESP . restart ( ) ;
}
}
else {
Serial . print ( " MQTT reconnect: " ) ;
connect_mqtt ( ) ;
}
2022-07-04 15:47:10 +00:00
}
else {
Serial . println ( " MQTT: connection ok " ) ;
}
}
2022-06-30 14:27:42 +00:00
bool send_mqtt ( String id , String sensor , float value ) {
// StaticJsonDocument<96> data;
//
// data["id"] = id;
// data["sensor"] = sensor;
// data["value"] = value;
String payload = " { \" id \" : \" " + id + " \" , \" sensor \" : \" " + sensor + " \" , \" value \" : " + String ( value ) + " } " ;
// int length = measureJson(&data);
// char* payload = new char[length]();
// serializeJson(data, payload, length);
2022-07-13 01:01:31 +00:00
check_mqtt ( false ) ;
check_mqtt ( true ) ;
2022-06-30 14:27:42 +00:00
bool result = mqtt . publish ( " sensors/data " , payload . c_str ( ) ) ;
// delete[] payload;
return result ;
}
void setup ( ) {
Serial . begin ( 9600 ) ;
delay ( 1000 ) ;
Serial . println ( " \n Analogue Soil Sensor Test " ) ;
Serial . println ( " ========================= " ) ;
Serial . print ( " PIN MODES: " ) ;
pinMode ( MULTIPLEX_PINA , OUTPUT ) ;
pinMode ( MULTIPLEX_PINB , OUTPUT ) ;
pinMode ( MULTIPLEX_PINC , OUTPUT ) ;
Serial . println ( " ok " ) ;
// Enterprise WiFi example:
// https://gist.github.com/Matheus-Garbelini/2cd780aed2eddbe17eb4adb5eca42bd6
// TODO Add support for enterprise WiFi here so we can connect to eduroam
Serial . print ( " WIFI: " ) ;
connect_wifi ( ) ;
int attempts = 0 ;
while ( WiFi . status ( ) ! = WL_CONNECTED ) {
delay ( 500 ) ;
Serial . print ( " . " ) ;
attempts + + ;
if ( attempts > 25 )
break ;
}
if ( WiFi . status ( ) = = WL_CONNECTED ) {
Serial . print ( " ok, IP: " ) ;
Serial . println ( WiFi . localIP ( ) ) ;
}
else {
// Ref https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html#check-return-codes
Serial . print ( " failed, error code " ) ;
Serial . println ( WiFi . status ( ) ) ;
}
2022-07-04 15:26:53 +00:00
Serial . print ( " MQTT: " ) ;
# ifdef MQTT_NO_TLS
Serial . print ( " notls " ) ;
# else
Serial . print ( " tls " ) ;
transport . setInsecure ( ) ; Serial . print ( " . " ) ;
# endif
// mqtt.setBufferSize(1000);
mqtt . setClient ( transport ) ; Serial . print ( " . " ) ;
mqtt . setServer ( MQTT_SERVER , MQTT_PORT ) ; Serial . print ( " . " ) ;
2022-07-04 15:47:10 +00:00
mqtt . setKeepAlive ( INTERVAL / 2 ) ;
2022-07-04 15:26:53 +00:00
// Serial.print(MQTT_SERVER);
// Serial.print(":");
// Serial.print(MQTT_PORT);
// Serial.print(".");
2022-07-04 15:47:10 +00:00
connect_mqtt ( ) ;
2022-06-30 14:27:42 +00:00
Serial . print ( " BME280: " ) ;
if ( ! bme . begin ( 0x76 ) ) {
Serial . println ( " failed! " ) ;
}
else {
Serial . println ( " ok " ) ;
}
}
void loop ( ) {
float soil_a = read_analog ( SOIL_A ) ;
float soil_b = read_analog ( SOIL_B ) ;
float water_level_a = read_analog ( WATER_LEVEL_A ) ;
float water_level_b = read_analog ( WATER_LEVEL_B ) ;
float temp = bme . readTemperature ( ) ;
float humidity = bme . readHumidity ( ) ;
float pressure = bme . readPressure ( ) / 100.0F ;
// StaticJsonDocument<96> data;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-a " ,
" soil " ,
soil_a
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-a " ,
" water-level " ,
water_level_a
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-b " ,
" soil " ,
soil_b
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-b " ,
" water-level " ,
water_level_b
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-a " ,
" temperature " ,
temp
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-a " ,
" humidity " ,
humidity
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
2022-07-04 15:26:53 +00:00
if ( ! send_mqtt (
2022-06-30 14:27:42 +00:00
" autoplant-a " ,
" pressure " ,
pressure
) ) Serial . println ( " [mqtt] Failed to send message " ) ;
// data["id"] = "autoplant-a";
// data["sensor"] = "soil";
// data["value"] = soil_a;
// if(!send_mqtt(&data)) Serial.println("[mqtt] Failed to send message");
//
// data["sensor"] = "water-level";
// data["value"] = water_level_a;
// if(!send_mqtt(&data)) Serial.println("[mqtt] Failed to send message");
//
// data["id"] = "autoplant-b";
// data["value"] = water_level_a;
// if(!send_mqtt(&data)) Serial.println("[mqtt] Failed to send message");
//
// data["sensor"] = "soil";
// data["value"] = soil_a;
// if(!send_mqtt(&data)) Serial.println("[mqtt] Failed to send message");
Serial . print ( " SOIL_A \t " ) ;
Serial . println ( soil_a ) ;
Serial . print ( " SOIL_B \t " ) ;
Serial . println ( soil_b ) ;
Serial . print ( " WATER_LEVEL_A \t " ) ;
Serial . println ( water_level_a ) ;
Serial . print ( " WATER_LEVEL_B \t " ) ;
Serial . println ( water_level_b ) ;
Serial . println ( " \n \n \n \n \n " ) ;
delay ( INTERVAL ) ;
}