For an index to all my stories click this text.
This is the second story about NTFY. The first story showed what NTFY is and how it can send notifications and messages to your Android smartphone from a PC dashboard.
This story shows how you can send notifications from your EP8266 or ESP32 in Arduino language (C++) to your phone, and how you can do that with a Raspberry Pi Pico in MicroPython.
So before you go on I recommend reading the previous story which you can find here: https://lucstechblog.blogspot.com/2026/05/notifications-with-ntfy.html
I'll start with sending a message from the Raspberry Pi Pico as a notification to a smartphone.
For your convenience I hereby give you the link to the NTFY website: https://ntfy.sh/
Limits and solution
First I hope you remember that with the free service NTFY there is a limit of 250 messages per day.
The messages remain for 12 hour on the server.
This means that if your phone is off, or has no internet connection, for 13 hours you will miss messages.
There are two solutions for this.
First you can get a paid subscription and then you get a lot more messages each day.
The second solution is to install your own NTFY server. You can do that on a Raspberry Pi (even the humble Zero) and then you can decide how many messages you can send per day and how long they stay on the server.
Mind you: 250 messages per day is about 10 messages per hour which would be more than sufficient for most projects.
Nevertheless I chose the second solution and installed my own server. Maybe something for another story ........................
Sending a message from MicroPython with a Pico
(Scroll down for the ESP32 arduino version)
We are going to do this the easy way. We are going to attach a button to the Pico and simulate that it is a door contact. Everytime the button is pressed the Pico will send a notification to the phone.
We are going to send an alarm with the text:
The door opened X times
The X will alter each time we press the button.
Let's start with the breadboard setup which is really easy.
It is just the Raspberry pi pico with a button attached to GP14. The button has a pull up resistor so the value is high (1) until we press the button. Then it gets low (0).
Here is the complete program.
import machine import network import urequests as requests import time button1 = machine.Pin(14, machine.Pin.IN) dooropen = 0 # Router credentials ssid = "YOUR-ROUTERS-NAME" pw = "YOUR-PASSWORD" print("Connecting to wifi...") # wifi connection wifi = network.WLAN(network.STA_IF) wifi.active(True) wifi.connect(ssid, pw) # wait for connection while not wifi.isconnected(): pass print("Connected. IP: ",str(wifi.ifconfig()[0], "\n")) while True: if button1.value() == 0: dooropen = dooropen + 1 sendstring ="The door opened " + str(dooropen) + " times" requests.post("http://ntfy.sh/lucstechblog", data= sendstring ) print("Data is send. dooropen = "+str(dooropen)) time.sleep(3)
Let's have a look at the program in some detail.
import machine import network import urequests as requests import time
These are the libraries that are needed to get the program running. They are all included in the standard MicroPython distributions. So no need to download libraries.
button1 = machine.Pin(14, machine.Pin.IN) dooropen = 0
The button is attached to GP14 and defined as a variable with the name button1. An extra variable with the name dooropen is defined. This will be used to count the number of times you press the button.
# Router credentials ssid = "YOUR-ROUTERS-NAME" pw = "YOUR-PASSWORD" print("Connecting to wifi...") # wifi connection wifi = network.WLAN(network.STA_IF) wifi.active(True) wifi.connect(ssid, pw) # wait for connection while not wifi.isconnected(): pass print("Connected. IP: ",str(wifi.ifconfig()[0], "\n"))
Nothing special here. These are the standard program lines to connect the Pico to your router. Don't forget to replace YOUR-ROUTERS-NAME and YOUR-PASSWORD with the required values for your router.
When the connection is established you will find the Pico's IP number in MicroPython's shell.
while True: if button1.value() == 0: dooropen = dooropen + 1
The while loop is where the actual action takes place.
First the program tests if the button is pressed. If so then the variable dooropen is increased by 1.
sendstring ="The door opened " + str(dooropen) + " times"
In this line we prepare the text that is going to be send.
This is the important line. Here you can fill in any information you like to send. If you would add a digital thermometer and put it's value in the variable temp you could alter the text like like this:
sendstring ="The temperature is now " + str(temp) + " degrees"
On to the next part.
requests.post("http://ntfy.sh/lucstechblog", data= sendstring )
NTFY needs a post request in stead of the get requests which we normally use. We post to the site http://ntfy.sh/ and the topic is lucstechblog.
print("Data is send. dooropen = "+str(dooropen)) time.sleep(3)
Next we print a confirmation in the shell and wait a few seconds to make sure the request is send.
That is all.
The result.
Run the program. Press the button. 
And this is what you'll see in Thonny's shell.
And here is how I got a notification in the top left corner of my phone's screen. My phone also gave an audio signal to draw my attention to the notification.
This is how the notification appeared on my phone's screen
And this is how it looks in the NTFY app on my phone.
At the same time the message appeared in the PC web version of NTFY.
Sending a message with an ESP32 in Arduino language (C++)
Just like we did with the Pico and MicroPython, we are going to do this the easy way. We are going to attach a button to the ESP32 and everytime the button is pressed the ESP32 will send a notification to the phone.
We are going to send an alarm with the text:
The button attached to the ESP32 was pressed X times.
The X will alter each time we press the button.
Let's start with the breadboard setup which is really easy.
It is just the ESP32 with a button attached to D22. The button has a pull up resistor so the value is high (1) until we press the button. Then it gets low (0).
Here is the complete program.
#include <WiFi.h> #include <HTTPClient.h> const char* ssid = "YOUR-ROUTERS-NAME"; const char* password = "PASSWORD"; //Where to send the notification const char* ntfyurl = "http://ntfy.sh/lucstechblog"; const int buttonPin = 23; int butpress = 0; void setup() { pinMode(buttonPin, INPUT); Serial.begin(115200); WiFi.begin(ssid, password); Serial.println("Connecting"); while(WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(""); Serial.print("Connected to WiFi network with IP Address: "); Serial.println(WiFi.localIP()); } void loop() { if (digitalRead(buttonPin) == LOW) { butpress = butpress + 1; if(WiFi.status()== WL_CONNECTED) { WiFiClient client; HTTPClient http; // Your Domain name with URL path or IP address with path http.begin(client, ntfyurl); http.addHeader("Content-Type", "text/plain"); // Build the text to send with HTTP POST: // The button attached to the ESP32 was pressed X times. String httpRequestData = "The button attached to the ESP32 was pressed "; httpRequestData = httpRequestData + butpress; httpRequestData = httpRequestData + " times"; // Send HTTP POST request int httpResponseCode = http.POST(httpRequestData); Serial.print("The response we got : "); Serial.println(httpResponseCode); // Close connection http.end(); // Wait before the next round delay (3); } } }
Lets look at some details in the program.
#include <WiFi.h> #include <HTTPClient.h> const char* ssid = "YOUR-ROUTERS-NAME"; const char* password = "PASSWORD"; //Where to send the notification const char* nyfyurl = "http://ntfy.sh/lucstechblog"; const int buttonPin = 23; int butpress = 0;
Nothing special here. The necessary libraries are loaded and The variables are defined. The variable ntfyurl is defined as http://ntfy.sh/lucstechblog which is the address of the NTFY server and the topic.
The setup() has nothing unusual.
The loop() is where the fun begins.
if (digitalRead(buttonPin) == LOW) { butpress = butpress + 1; if(WiFi.status()== WL_CONNECTED) { WiFiClient client; HTTPClient http;
The program continually tests if the button is pressed. If so the butpress variable is increased by 1 and the wifi and http clients are activated.
// Your Domain name with URL path or IP address with path http.begin(client, ntfyurl); http.addHeader("Content-Type", "text/plain");
The http communication with the NTFY server is started with the previous defined ntfyurl. A header is sent first that identifies the data we are going to send as plain text.
// Build the text to send with HTTP POST: // The button attached to the ESP32 was pressed X times. String httpRequestData = "The button attached to the ESP32 was pressed "; httpRequestData = httpRequestData + butpress; httpRequestData = httpRequestData + " times";
The text "The button attached to the ESP32 was pressed X times." is build here by combining several parts. One of the parts that is added is butpress which is the variable that counts how many times the button was pressed.
// Send HTTP POST request int httpResponseCode = http.POST(httpRequestData); Serial.print("The response we got : "); Serial.println(httpResponseCode); // Close connection http.end();
The request is send as a http POST request with the previous defined httpRequestData. The request receives a response with an indication if it has succeeded. The response is then printed in the serial monitor. After sending the request the connection is closed.
// Wait before the next round delay (3);
The program then waits for 3 seconds. This time can be shortened but a short delay is preferred to prevent detecting a bouncing button as a button press.
It is obvious that this code can easily be adapted to send sensor readings etc. etc. etc.
This is what the Serial Monitor shows. As you can see there are 4 responses with the number 200 that means that the request was received ok.
And here are the notifications I received. As you can see I subscribed to 6 topics. The topics were made just for testing.
Expansion
In this example I use the same topic all the time: lucstechblog. It is of course possible to create multiple topics. So a single Pico or ESP can send notifications to several topics. However you can also have multiple microcontrollers sending data to several topics.
In the above examples we send notifications with just one line of text. You can send notifications with multiple lines of text. The documentation of NTFY shows how to do this. You can find the documentation here: https://docs.ntfy.sh/
Even better: you can attach files to a notification. These can be text files but also pictures !! I have successfully experimented with sending pictures from C++ and from MicroPython. I can see a chat program coming up...........
You can have the Pico's and ESP's send notifications to several NTFY servers.
On the NTFY documents pages there is a list of public NFTY servers. You can find the docs and that list here: https://docs.ntfy.sh/integrations/
You can start your own private server. A Raspberry Pi is sufficient. Even a humble Raspberry Pi Zero will do.
Using your own private server does not expose your topics (if someone finds them) and their data to a general audience. It restricts the information to those you have given the information about the server and it's topics.
On a private server you can expand the lifetime of the messages from 12 hour to any timelimit that suits you. And the number of messages you can send per day can be limitless !!!
Not only can you send notifications but using the right API call you can also get all notifications that have been send with a certain topic from the server. This way you can have two-way conversation between microcontrollers. A microcontroller can retrieve the messages on a certain topic from the server, and can act on that, and then send a notification with the same or a different topic. You do need a private server for this.
If you want a story on sending multiple line notifications, sending a textfile or a picture with the notification, starting your own server on a Raspberry Pi or retrieving notifications from your private server please send me an email.
I can see loads of possibilities with NTFY and therefore already installed my own private server.
Till next time.
Have fun
Luc Volders