Files
0x6f736f646f 3b38242554 💄 Spacing the code
2020-08-28 01:06:43 +03:00

456 lines
13 KiB
Arduino

// defining the GSM module before importations
#define TINY_GSM_MODEM_SIM800
// IMPORTATION OF NECESSARY HEADER FILES
#include <DHT.h> // DHT library
#include <TinyGsmClient.h> // GSM library
#include <Countdown.h>
#include <IPStack.h>
#include <MQTTClient.h> // MQTT client library
#include <MQTTPacket.h> // MQTT library to send data as packets
#include <Arduino.h>
#include <U8x8lib.h>
#include "./config.h"
#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif
// DEFINITION OF VARIABLES
#define DHTTYPE DHT11
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// Set serial for AT commands (to the module)
#define SerialAT Serial2
// Define the serial console for debug prints, if needed
#define TINY_GSM_DEBUG SerialMon
// Define how you're planning to connect to the internet
#define TINY_GSM_USE_GPRS true
#define TINY_GSM_USE_WIFI false
// The GSM module power is at PB15 and needs to be set HIGH for 3 seconds then LOW once
#define GSM_POWER_KEY PB15
// time before another iteration of the loop
int loop_time = 5000;
// short delay time
int delay_time = 2000;
// where the DHT data pin is located
const int DHT_PIN = PA6;
// where the Soil Moisture sensor data pin is located
const int soilMoisturePin = PB1;
// where the Light Dependent Resistor data pin is located
const int ldrPin = PB0;
// where the Solid state relay data pin is located
#define relayPin PA7
// Your GPRS credentials, if any
const char apn[] = SAF_APN;
const char gprsUser[] = "";
const char gprsPass[] = "";
// Buffer to stop messages when formating before publishing or printing
char buffer[100];
// Default return code
int returnCode = 0;
// BEGIN MQTT CONFIG
const char mqttUsername[] = MQTT_CREDENTIALS;
const char mqttPassword[] = DEVICE_GROUP_PASSWORD;
const char mqttDeviceID[] = DEVICE_ID;
// birth topic - This is a topic that the device publishes to when it makes the first MQTT Connection
// will topic - This is a topic that the device should publish to when it disconnects.
const char *birthTopic = TOPIC_PREFIX "birth";
const char *willTopic = TOPIC_PREFIX "will";
const char *humidityTopic = TOPIC_PREFIX "humidity";
const char *soilMoistureTopic = TOPIC_PREFIX "moisture";
const char *temperatureTopic = TOPIC_PREFIX "temperature";
const char *relayTopic = TOPIC_PREFIX "relay";
const char *lightIntensityTopic = TOPIC_PREFIX "light";
const char birthMessage[] = "CONNECTED";
const char willMessage[] = "DISCONNECTED";
char brokerAddress[] = BROKER_ADDRESS;
int brokerPort = BROKER_PORT;
// END MQTT CONFIG
// Variables to store sensor values before publishing to the broker
float humidity, temperature, soilMoistureValue, ldrValue;
// iterator variable
int r;
DHT dht(DHT_PIN, DHTTYPE);
TinyGsm modem(SerialAT);
TinyGsmClient tinyGSMClient(modem);
IPStack ipstack(tinyGSMClient);
MQTT::Client<IPStack, Countdown, 128, 2> mqttClient = MQTT::Client<IPStack, Countdown, 128, 2>(ipstack);
// The complete list is available here: https://github.com/olikraus/u8g2/wiki/u8x8setupcpp
// Please update the pin numbers according to your setup. Use U8X8_PIN_NONE if the reset pin is not connected
U8X8_SSD1306_128X64_NONAME_SW_I2C u8x8(/* clock=*/ PB8, /* data=*/ PB9, /* reset=*/ U8X8_PIN_NONE); // OLEDs without Reset of the Display
// DECLARATION OF FUNCTIONS
float readTemp(void);
float readHum(void);
float readSoilMoisture(void);
float readLightIntensity(void);
void connectGSM(void);
void connectMqtt(void);
void publishMessage(char *payload, const char *topic);
void sendTemperature(void);
void sendHumidity(void);
void sendSoilMoisture(void);
void sendLightIntensity(void);
void incomingMessageHandler(MQTT::MessageData &messageData);
void pre(void);
void print_on_oled(char* topic, float data);
void setup()
{
// Start the OLED display
u8x8.begin();
u8x8.setPowerSave(0);
// Start serial monitors
SerialMon.begin(115200);
delay(delay_time);
SerialAT.begin(115200);
delay(delay_time);
// Declare the sensor pins as input pins
pinMode(soilMoisturePin, INPUT);
pinMode(ldrPin, INPUT);
// Declare the actuator pins as output pins
pinMode(GSM_POWER_KEY, OUTPUT);
pinMode(relayPin, OUTPUT);
// GSM ON
digitalWrite(GSM_POWER_KEY, 1);
delay(delay_time);
digitalWrite(GSM_POWER_KEY, 0);
connectGSM();
connectMqtt();
delay(delay_time);
dht.begin();
}
void loop()
{
pre();
u8x8.print("AFRICASTALKING");
u8x8.setCursor(0,2);
u8x8.print("HACKATHON");
delay(delay_time);
sendTemperature();
delay(delay_time);
sendHumidity();
delay(delay_time);
sendSoilMoisture();
delay(delay_time);
sendLightIntensity();
// Fill the display for refreshing
pre();
u8x8.fillDisplay();
for( r = 0; r < u8x8.getRows(); r++ )
{
u8x8.clearLine(r);
delay(delay_time);
}
delay(delay_time);
delay(loop_time);
// Wait for a few seconds to loop again
}
float readHum(void)
{
// This functions reads the humidity as returns the value as float
humidity = dht.readHumidity();
// Check if reads failed and exit
if (humidity == NULL){
Serial.println("Failed to read from DHT");
exit;
}
print_on_oled("Humidity: ", humidity);
return humidity;
}
float readTemp(void)
{
// This functions reads temperature in Celsius(default) the value as float
temperature = dht.readTemperature();
// Check if reads failed and exit
if (temperature == NULL){
Serial.println("Failed to read from DHT");
exit;
}
print_on_oled("Temperature: ", temperature);
return temperature;
}
float readSoilMoisture(void)
{
// This functions reads the soil moisture as returns the value as float
soilMoistureValue = analogRead(soilMoisturePin);
soilMoistureValue = map(soilMoistureValue, 0, 4095, 0, 100);
// Map value : 0 will be 0 and 4095 will be 1000
print_on_oled("Soil moisture: ", soilMoistureValue);
return soilMoistureValue;
}
float readLightIntensity(void)
{
// This functions reads the light intensity as returns the value as float
ldrValue = analogRead(ldrPin);
ldrValue = map(ldrValue, 0, 4095, 100, 0);
// Map value : 0 will be 100 and 4095 will be 0
print_on_oled("Light intensity: ", ldrValue);
return ldrValue;
}
void connectGSM(void)
{
// This function connects to GSM
SerialMon.println("Getting the modem ready");
modem.init();
String name = modem.getModemName();
String modemInfo = modem.getModemInfo();
SerialMon.print("Name: ");
SerialMon.println(name);
SerialMon.print("Modem info: ");
SerialMon.println(modemInfo);
SerialMon.println("Initializing GSM network registration");
if (!modem.waitForNetwork())
{
SerialMon.println("Unable to initialize registration. Reset and try again.");
// Restart takes quite some time To skip it, call init() instead of restart()
modem.restart();
while (true)
{
;
}
}
if (modem.isNetworkConnected()) {
SerialMon.println("Network connected");
pre();
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
u8x8.setCursor(0,4);
u8x8.print("Network: ");
u8x8.setCursor(0,5);
u8x8.print("connected");
}
SerialMon.println("GSM OK");
// GPRS connection parameters are usually set after network registration
SerialMon.println("Attempting to establish GPRS connection");
if (!modem.gprsConnect(apn, gprsUser, gprsPass))
{
SerialMon.println("Unable to connect to APN. Reset and try again");
while (true)
{
;
}
}
if(modem.isGprsConnected())
{
SerialMon.println("GPRS status: connected" );
pre();
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
u8x8.setCursor(0,4);
u8x8.print("GPRS: ");
u8x8.setCursor(0,5);
u8x8.print("connected");
}
String ccid = modem.getSimCCID();
SerialMon.print("CCID: ");
SerialMon.println(ccid);
String imei = modem.getIMEI();
SerialMon.print("IMEI: ");
SerialMon.println(imei);
String imsi = modem.getIMSI();
SerialMon.print("IMSI: ");
SerialMon.println(imsi);
String cop = modem.getOperator();
SerialMon.print("Operator: ");
SerialMon.println(cop);
IPAddress local = modem.localIP();
SerialMon.print("Local IP: ");
SerialMon.println(local);
int csq = modem.getSignalQuality();
SerialMon.print("Signal quality: ");
SerialMon.println(csq);
}
void connectMqtt(void)
{
// Connects to MQTT
MQTT::Message mqttMessage;
snprintf(buffer, sizeof(buffer), "Connecting to %s on port %u\n", brokerAddress, brokerPort);
SerialMon.println(buffer);
returnCode = ipstack.connect(brokerAddress, brokerPort);
if (returnCode != 1)
{
SerialMon.println("Unable to connect to TCP Port.");
}
else
{
SerialMon.println("TCP port open");
}
delay(delay_time);
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
data.MQTTVersion = 4;
data.clientID.cstring = (char *)mqttDeviceID;
data.username.cstring = (char *)mqttUsername;
data.password.cstring = (char *)mqttPassword;
data.keepAliveInterval = 60;
data.cleansession = 1;
data.will.message.cstring = (char *)willMessage;
data.will.qos = MQTT::QOS1;
data.will.retained = 0;
data.will.topicName.cstring = (char *)willTopic;
returnCode = mqttClient.connect(data);
if (returnCode != 0)
{
snprintf(buffer, sizeof(buffer), "Code %i. Unable to contact the broker. Is it up? Reset and try again \r\n", returnCode);
SerialMon.print(buffer);
while (true)
{
;
}
}
mqttMessage.qos = MQTT::QOS1;
mqttMessage.retained = false;
mqttMessage.dup = false;
mqttMessage.payload = (void *)birthMessage;
mqttMessage.payloadlen = strlen(birthMessage) + 1;
returnCode = mqttClient.publish(birthTopic, mqttMessage);
snprintf(buffer, sizeof(buffer), "Birth topic publish return code %i \n", returnCode);
SerialMon.println(buffer);
returnCode = mqttClient.subscribe(relayTopic, MQTT::QOS1, incomingMessageHandler);
if (returnCode != 0)
{
snprintf(buffer, sizeof(buffer), "Unable to subscribe to relay topic \n");
SerialMon.print(buffer);
while (true)
{
;
}
}
SerialMon.println("Successfully connected to the broker");
pre();
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
u8x8.setCursor(0,4);
u8x8.print("Broker: ");
u8x8.setCursor(0,5);
u8x8.print("connected");
}
void publishMessage(char *payload, const char *topic)
{
// Publishes messages to the broker
MQTT::Message message;
message.qos = MQTT::QOS1;
message.payload = (void *)payload;
message.payloadlen = strlen(payload) + 1;
returnCode = mqttClient.publish(topic, message);
snprintf(buffer, sizeof(buffer), "%s topic publish return code %i", topic, returnCode);
SerialMon.println(buffer);
}
void sendHumidity(void)
{
// Sends humidity data to the broker
humidity = readHum();
snprintf(buffer, sizeof(buffer), "%.3f", humidity);
publishMessage(buffer, humidityTopic);
}
void sendTemperature(void)
{
// Sends temperature data to the broker
temperature = readTemp();
snprintf(buffer, sizeof(buffer), "%.3f", temperature);
publishMessage(buffer, temperatureTopic);
}
void sendLightIntensity(void)
{
// Sends light intensity data to the broker
ldrValue = readLightIntensity();
snprintf(buffer, sizeof(buffer), "%.3f", ldrValue);
publishMessage(buffer, lightIntensityTopic);
}
void sendSoilMoisture(void)
{
// Sends soil moisture data to the broker
soilMoistureValue = readSoilMoisture();
snprintf(buffer, sizeof(buffer), "%.3f", soilMoistureValue);
publishMessage(buffer, soilMoistureTopic);
}
void incomingMessageHandler(MQTT::MessageData &messageData)
{
// Handler for incomming messages
MQTT::Message &message = messageData.message;
MQTTString topic = messageData.topicName;
snprintf(buffer, sizeof(buffer), "%s", messageData.topicName);
if (buffer == relayTopic)
{
snprintf(buffer, sizeof(buffer), "%s", messageData.message.payload);
if (buffer == "on")
{
digitalWrite(relayPin, 1);
}
else if (buffer == "off")
{
digitalWrite(relayPin, 0);
}
else
{
SerialMon.print("Unknown LED Command: ");
SerialMon.println(buffer);
}
}
else
{
SerialMon.print("Unknown Topic: ");
SerialMon.println(buffer);
}
}
void pre(void)
{
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
u8x8.clear();
u8x8.inverse();
u8x8.print(" SMART FARM ");
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.noInverse();
u8x8.setCursor(0,1);
}
void print_on_oled(char* topic, float data)
{
// prints data on oled screen
sprintf(buffer, "%.2f", data);
SerialMon.print(topic);
SerialMon.println(buffer);
pre();
u8x8.setFont(u8x8_font_amstrad_cpc_extended_f);
u8x8.drawString(0, 2, topic);
u8x8.draw2x2String(0, 5, buffer);
}