#include #include // #include #include #include "./lib/pubsubclient/PubSubClient.h" #include "./lib/pubsubclient/PubSubClient.cpp" // 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 #include #include "settings.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))) #ifndef MQTT_NO_TLS WiFiClientSecure transport; #else WiFiClient transport; #endif PubSubClient mqtt; Adafruit_BME280 bme; // I2C #ifdef WIFI_ENTERPRISE_ENABLED // Ref https://gist.github.com/Matheus-Garbelini/2cd780aed2eddbe17eb4adb5eca42bd6 extern "C" { #include "user_interface.h" #include "wpa2_enterprise.h" #include "c_types.h" } #endif void connect_wifi() { #ifndef WIFI_ENTERPRISE_ENABLED Serial.print("personal"); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); #else Serial.print("enterprise"); // Ref https://gist.github.com/Matheus-Garbelini/2cd780aed2eddbe17eb4adb5eca42bd6 // Setting ESP into STATION mode only (no AP mode or dual mode) wifi_set_opmode(STATION_MODE); struct station_config wifi_config; memset(&wifi_config, 0, sizeof(wifi_config)); strcpy((char*)wifi_config.ssid, WIFI_SSID); strcpy((char*)wifi_config.password, WIFI_ENTERPRISE_PASSWORD); wifi_station_set_config(&wifi_config); // wifi_set_macaddr(STATION_IF,target_esp_mac); wifi_station_set_wpa2_enterprise_auth(1); // Clean up to be sure no old data is still inside wifi_station_clear_cert_key(); wifi_station_clear_enterprise_ca_cert(); wifi_station_clear_enterprise_identity(); wifi_station_clear_enterprise_username(); wifi_station_clear_enterprise_password(); wifi_station_clear_enterprise_new_password(); wifi_station_set_enterprise_identity((uint8*)WIFI_ENTERPRISE_USERNAME, strlen(WIFI_ENTERPRISE_USERNAME)); wifi_station_set_enterprise_username((uint8*)WIFI_ENTERPRISE_USERNAME, strlen(WIFI_ENTERPRISE_USERNAME)); wifi_station_set_enterprise_password((uint8*)WIFI_ENTERPRISE_PASSWORD, strlen((char*)WIFI_ENTERPRISE_PASSWORD)); wifi_station_connect(); #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; } 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); bool result = mqtt.publish("sensors/data", payload.c_str()); // delete[] payload; return result; } void setup() { Serial.begin(9600); delay(1000); Serial.println("\nAnalogue 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()); } 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("."); // Serial.print(MQTT_SERVER); // Serial.print(":"); // Serial.print(MQTT_PORT); // Serial.print("."); 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"); 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; if(!send_mqtt( "autoplant-a", "soil", soil_a )) Serial.println("[mqtt] Failed to send message"); if(!send_mqtt( "autoplant-a", "water-level", water_level_a )) Serial.println("[mqtt] Failed to send message"); if(!send_mqtt( "autoplant-b", "soil", soil_b )) Serial.println("[mqtt] Failed to send message"); if(!send_mqtt( "autoplant-b", "water-level", water_level_b )) Serial.println("[mqtt] Failed to send message"); if(!send_mqtt( "autoplant-a", "temperature", temp )) Serial.println("[mqtt] Failed to send message"); if(!send_mqtt( "autoplant-a", "humidity", humidity )) Serial.println("[mqtt] Failed to send message"); if(!send_mqtt( "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); }