I have spoken to many Lifely users who use our Lifely Agrumino Lemon device and many would like to receive(ONLY) critical alerts via pop-up messages on their Smartphone, such as "The plant needs to be watered!" or " Need to recharge the battery".
This I present to you is a good FREE solution that can send and receive these alerts. is a good FREE solution that can send and receive these alerts.
The firmware is ready to burn, you have to edit some data inside the code.
I'll explain everything right now....
Create Pushbullet accountgo to www.pushbullet.com and Sign up ( I use my Google account)
I choose my account
Ok, this is a Main Pushbullet, now you need to have a Pushbullet Token, click Settings.
Click "Create Access Token"
Here, this is your token, copy it and never share it with anyone ;-)
https://www.pushbullet.com/apps
Go to Playstore and Install official APP (login with your data)
You need to grant permissions for notifications.
- Connect Life Agrumino Lemon with usb cable into your PC
You already know how :-)
Firmware, complete.Next let's see the details
/*LifelyAgruminoLemonPushbullet-
Created by Gabriele Foddis on 04/2023
gabriele.foddis@lifely.cc
This firmware has been developed to send only important notifications for the irrigation and battery status, maximum attention to energy saving.
I used pushbullet excellent platform to send and receive notifications. Ppossible to have a free or premium account at a very low cost. Visit https://www.pushbullet.com/
the device sends messages only when necessary according to the configuration thresholds.
You need to use pushbullet app,available for different platforms
Find Lifely Agrumino Lemon (REV4 AND REV5) in www.lifely.cc */
#include <Arduino.h>
#include <Agrumino.h>
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
#define DEBUG_MSG_INFO true
#define DEBUG_INFO_MSG if(DEBUG_MSG_INFO)Serial
#define DEBUG_MSG_WARNING true
#define DEBUG_WARNING_MSG if(DEBUG_MSG_WARNING)Serial
#define MIN_TO_MS (1000000 * 60)
#define BAUD_RATE 115200
unsigned int SLEEP_TIME_MIN = 60; ///Max 60 minutes
const char* networkName = "PlumCake";
const char* networkPassword = "ImVeryHappy";
const char* apiPushbullet = "api.pushbullet.com";
const char* yourTokenForPushbullet = "o.NvLgQzsDvGAmGlSJzBYAZg"; //From your https://www.pushbullet.com/ account
int soilMoisture, batteryLevel, tryConnect;
float temperature, lux, batteryVoltage;
bool isBatteryCharging ;
String agruminoName, msgDynamic, qD;
const char* thumbPrint = "D7:60:F4:84:EF:C4:25:4E:14:B7:5A:4B:4C:2E:F6:FD:53:5E:BF:8E";
String pushBulletV2 = "/v2/pushes";
int soilMoistureWarning = 30; ///set your value
int batteryWarning = 25; //set your value
int maxConnAttempts= 100; ///maximum connection attempts
const int securePort = 443;
Agrumino agrumino;
void readDataFromDevice(){
DEBUG_INFO_MSG.println("...read data");
agruminoName = "Agrumino-"+String(ESP.getChipId());
isBatteryCharging = agrumino.isBatteryCharging();
temperature = agrumino.readTempC();
soilMoisture = agrumino.readSoil();
lux = agrumino.readLux();
batteryVoltage = agrumino.readBatteryVoltage();
batteryLevel = agrumino.readBatteryLevel();
delay(200);
DEBUG_INFO_MSG.println("...END data");
}
void checkData(){
if (soilMoisture<soilMoistureWarning && batteryLevel>batteryWarning){
msgDynamic=msgWarningSoilM;
DEBUG_WARNING_MSG.println("Warning soilMoisture");
}
else if(soilMoisture<soilMoistureWarning && batteryLevel<batteryWarning){
msgDynamic=msgBatterySoilM;
DEBUG_WARNING_MSG.println("Warning soilMoisture and battery");
}
else if(soilMoisture>soilMoistureWarning && batteryLevel<batteryWarning){
msgDynamic=msgBatteryWarning;
DEBUG_WARNING_MSG.println("Warning battery");
}
else{ ESP.deepSleep(MIN_TO_MS * SLEEP_TIME_MIN);
DEBUG_INFO_MSG.println("No warning");
}
}
void setup() {
Serial.begin(BAUD_RATE);
agrumino.setup();
agrumino.turnBoardOn();
delay(500);
Serial.println();
readDataFromDevice();
checkData();
DEBUG_INFO_MSG.print("I'm try to connect with ");
DEBUG_INFO_MSG.println(networkName);
WiFi.mode(WIFI_STA);
WiFi.begin(networkName, networkPassword);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
tryConnect++;
if (tryConnect > maxConnAttempts){
DEBUG_WARNING_MSG.print("..problem with the connection, I will try again in "+ String(SLEEP_TIME_MIN)+" minutes");
ESP.deepSleep(MIN_TO_MS * SLEEP_TIME_MIN);
}
}
DEBUG_INFO_MSG.println("");
DEBUG_INFO_MSG.println("WiFi connected");
DEBUG_INFO_MSG.println("IP address: ");
DEBUG_INFO_MSG.println(WiFi.localIP());
WiFiClientSecure AgruminoPushClient;
AgruminoPushClient.setInsecure(); //don't move
DEBUG_INFO_MSG.print("Connecting to ");
DEBUG_INFO_MSG.println(apiPushbullet);
if (!AgruminoPushClient.connect(apiPushbullet, securePort)) {
DEBUG_WARNING_MSG.println("Failed to connect");
return;
}
if (AgruminoPushClient.verify(thumbPrint, apiPushbullet)) {
DEBUG_INFO_MSG.println("The certificate matches, great");
} else {
DEBUG_WARNING_MSG.println("The certificate does not match, check it");
}
DEBUG_INFO_MSG.println("Dynamic message is: " + msgDynamic);
qD = "\""; //I need this to semplify escape sequence and add Dynamic title and body from var(Escape sequence for double quote)
String popUpMessage = "{\"type\": \"note\", \"title\":" ;
popUpMessage += qD + agruminoName +qD +"," + qD+"body"+qD +":"+qD+msgDynamic+qD+"}\r\n";
DEBUG_INFO_MSG.println(popUpMessage);
DEBUG_INFO_MSG.print("Send data in URL: ");
DEBUG_INFO_MSG.println(pushBulletV2);
AgruminoPushClient.print(String("POST ") + pushBulletV2 + " HTTP/1.1\r\n" +
"Host: " + apiPushbullet + "\r\n" +
"Authorization: Bearer " + yourTokenForPushbullet + "\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: " +
String(popUpMessage.length()) + "\r\n\r\n");
AgruminoPushClient.print(popUpMessage);
DEBUG_INFO_MSG.println("Request send....");
while (AgruminoPushClient.available() == 0);
while (AgruminoPushClient.available()) {
String line = AgruminoPushClient.readStringUntil('\n');
DEBUG_INFO_MSG.println(line);
}
}
void loop() {
WiFi.disconnect();
DEBUG_INFO_MSG.println("End loop and sleep");
ESP.deepSleep(MIN_TO_MS * SLEEP_TIME_MIN);
}
Firmware, some details.- Debug (true/false)print if you need to show info messages or warning messages.
#define DEBUG_MSG_INFO true
#define DEBUG_INFO_MSG if(DEBUG_MSG_INFO)Serial
#define DEBUG_MSG_WARNING true
#define DEBUG_WARNING_MSG if(DEBUG_MSG_WARNING)Serial
#define MIN_TO_MS (1000000 * 60)
#define BAUD_RATE 115200
unsigned int SLEEP_TIME_MIN = 60; ///Max 60 minutes
- SLEEP_TIME_MIN, the time which the device will sleep
unsigned int SLEEP_TIME_MIN = 60; ///Max 60 minutes
- Parameters for network connection. Please change value for this ourTokenForPushbullet with your token (copied from your account)
const char* networkName = "PlumCake";
const char* networkPassword = "ImVeryHappy";
const char* apiPushbullet = "api.pushbullet.com";
const char* yourTokenForPushbullet = "o.NvLgQzsDvGAmGlSJzBYAZg"; //From your https://www.pushbullet.com/ account
- Read all data from Lifely Agrumino Lemon and assign the name to the device with agruminoName
void readDataFromDevice(){
DEBUG_INFO_MSG.println("...read data");
agruminoName = "Agrumino-"+String(ESP.getChipId());
isBatteryCharging = agrumino.isBatteryCharging();
temperature = agrumino.readTempC();
soilMoisture = agrumino.readSoil();
lux = agrumino.readLux();
batteryVoltage = agrumino.readBatteryVoltage();
batteryLevel = agrumino.readBatteryLevel();
delay(200);
DEBUG_INFO_MSG.println("...END data");
}
- I check the parameters read from device and then decide if I have to connect to send the message, otherwise I go into a deep sleep
void checkData(){
if (soilMoisture<soilMoistureWarning && batteryLevel>batteryWarning){
msgDynamic=msgWarningSoilM;
DEBUG_WARNING_MSG.println("Warning soilMoisture");
}
else if(soilMoisture<soilMoistureWarning && batteryLevel<batteryWarning){
msgDynamic=msgBatterySoilM;
DEBUG_WARNING_MSG.println("Warning soilMoisture and battery");
}
else if(soilMoisture>soilMoistureWarning && batteryLevel<batteryWarning){
msgDynamic=msgBatteryWarning;
DEBUG_WARNING_MSG.println("Warning battery");
}
else{ ESP.deepSleep(MIN_TO_MS * SLEEP_TIME_MIN);
DEBUG_INFO_MSG.println("No warning");
}
}
- The parameters used are humidity threshold and minimum battery threshold. These parameters can be customized based on the type of plant you need to monitor
int soilMoistureWarning = 30; ///set your value
int batteryWarning = 25; //set your value
- If the data read presents anomalies based on our thresholds then the device connect to your WiFi network and send a message with the custom text.
String msgWarningSoilM = "Hi Dear, I need water... NOW!!!!!"; //customize as you like
String msgBatteryWarning = "Hi dear, I need Power, recharge my battery";//customize as you like
String msgBatterySoilM ="Hi Dear, I need water and power for my battery... NOW";//customize as you like
- Create message, push it and you receive in your App (use API POST)
qD = "\""; //I need this to semplify escape sequence and add Dynamic title and body from var(Escape sequence for double quote)
String popUpMessage = "{\"type\": \"note\", \"title\":" ;
popUpMessage += qD + agruminoName +qD +"," + qD+"body"+qD +":"+qD+msgDynamic+qD+"}\r\n";
DEBUG_INFO_MSG.println(popUpMessage);
DEBUG_INFO_MSG.print("Send data in URL: ");
DEBUG_INFO_MSG.println(pushBulletV2);
AgruminoPushClient.print(String("POST ") + pushBulletV2 + " HTTP/1.1\r\n" +
"Host: " + apiPushbullet + "\r\n" +
"Authorization: Bearer " + yourTokenForPushbullet + "\r\n" +
"Content-Type: application/json\r\n" +
"Content-Length: " +
String(popUpMessage.length()) + "\r\n\r\n");
AgruminoPushClient.print(popUpMessage);
DEBUG_INFO_MSG.println("Request send....");
while (AgruminoPushClient.available() == 0);
while (AgruminoPushClient.available()) {
String line = AgruminoPushClient.readStringUntil('\n');
DEBUG_INFO_MSG.println(line);
After custom you need to burn it in your device.
Received pop up messages look like thisIf there is a condition, you show like this
or this (in Desktop version)
If you find errors, don't worry I'm human and not aChatGPT ;-)
But I'll be happy to correct any mistakes.
Support other projects with a simple like in the left
Comments
Please log in or sign up to comment.