Table of Contents
Our country is overwhelmed right now. Covid vaccines are in short supply. Although there are ways to book a slot, we first need to know that slots are available. It is a lot of manual effort. Hence I decided to create and show a way how to do that automatically. The Covid Vaccine Availability Notifier runs on AWS Lambda and check for slots every two hours. If a slot is available, it will automatically send an email.
The application is based on Python3.8.
This entire Covid Vaccine Availability Notifier project is broken down into two parts:
- We will first create a python script to ping the API available to get the data and then see how to send an email notification.
- In part two of this tutorial, we will configure AWS Lambda so that it runs without manual efforts and keeps checking periodically – a true Covid Vaccine Availability Notifier
This project requires basic knowledge of python. With that, you will be able to customize the application as per your needs.
Even if you do not know basic python, you can install python, install the libraries and follow through the post. You will be able to do it.
Let’s get started then.
Import Necessary Libraries
We need a few libraries to help us achieve it. Following are the libraries required:
import requests # to send GET requests to the server from datetime import date # to create the date string import json #to parse the json response from server
Function to check for slots
We will now create a function that will do the following:
- Ping the URL
- Parse the data
- Check for available slots and create a message
- Enter information in the message if the slot is available
- Return the message
Let us have a look at the function.
def checkStatus(): today = date.today() #get today's date from system target_date = str(today.day) + "-" + str(today.month) +"-" + str(today.year) payload = {'district_id':'8','date':target_date} #payload with district ID and date headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'} byDistrict_URL = "https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByDistrict" data = requests.get(byDistrict_URL,headers=headers,params = payload) # Send a GET request with the defined payload json_data= data.json() message = '' ###Loop through the data### for i in range(len(json_data['centers'])): #loop for all centers center = 'center : ' + (json_data['centers'][i]['name']) + '<br />' + "District : " + json_data['centers'][i]['district_name'] + '<br />'+ 'address : ' + (json_data['centers'][i]['address']) for j in range(len(json_data['centers'][i]['sessions'])): #loop for all sessions in a center capacity = json_data['centers'][i]['sessions'][j]['available_capacity'] #available capacity minAge = json_data['centers'][i]['sessions'][j]['min_age_limit'] #minimum age limit for vaccination in this center session if(capacity>0 and minAge == 18): #add to message only if capacity is more than zero available_date = json_data['centers'][i]['sessions'][j]['date'] message = message + center + "<br />" + "Date : " + available_date + "<br />" + "Available Capacity : " + str(capacity) + "<br />" + "Minimum Age : " + str(minAge) + "<br /><br />" return(message)
Let us break down the checkStatus() function:
1. Create a date string:
The API requires the date for which it should check for availability. So, we need to send the date as a parameter in the URL. Past dates are of no use to us. Hence, we will check for today’s date and pass it to the server. To do that, we will read the current date from the system.
today = date.today() target_date = str(today.day) + "-" + str(today.month) +"-" + str(today.year)
2. Create the Header
For pinging the server, we use the “requests” library in python. The library provides a way to send headers. These headers tell the server about the kind of system which is pinging the server. Based on the header, the server decides the kind of response to be returned.
headers={'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36'}
3. Create the URL
There are two parts to it.
The first one is the API that we wish to ping. This can be found in the API Setu portal for Co-Win. For this post, I am using the API that gives data for one week from today, district wise.
byDistrict_URL = "https://cdn-api.co-vin.in/api/v2/appointment/sessions/public/calendarByDistrict"
In the second part, we need to tell the API the district ID and the date. To pass this information, we create a payload dictionary, and, will give this dictionary to the requests library
payload = {'district_id':'8','date':target_date}
These are like information to the URL server that we want to check for the district ID 8 and the date = today’s date
How to find your district ID?
The best and the simplest way is to use the Cowin portal. Follow these steps:
- Open the Co-Win portal in a browser
- From your browser settings, open the Developer tools (chrome) or Web Developer Tools (Firefox)
- Select the “Network” tab
- Select the Option “Search By District” on the website
- Enter the State and the District and click on “Search”
- In the Network tab, it will show the URL that was pinged. It will look something like this:
In the above image, you can find the district ID in the marked area. This is the ID of your district which you need to mention in place of 8 in the code. In the image above, the district_id is 5
Once you get the URL ready for your district, you are ready to move on. In the next step, we will ping the URL.
Ping the URL
The response received from the URL is in JSON format. For this code, I am converting it to a python dictionary for further processing.
data = requests.get(byDistrict_URL,headers=headers, params = payload) #pass the URL, the header to ping the server, and the payload json_data= data.json() #convert the JSON to dict
The data reply from the server is in the following format:
- Centers
- Center-ID 1
- Session 0
- Date = Today
- Min_Age_Lim
- Available Capacity
- Vaccine Name
- Session 1
- Date = Today + 1
- Min_Age_Lim
- Available Capacity
- Vaccine Name
- Session 0
- Center-ID 2
- Center-ID 1
And so on. So, what we will do is to loop through the data.
- Check for each center and for each center, check for all the sessions.
- If there is vaccine available, store the center name, address, date, capacity and minimum age in a string data holder.
- Repeat for all the centers
Finally, when we are done looping through the data, we will return the message. All we have to do now is to call this function.
print(checkStatus())
When you call this function, it is very likely that you don’t get any output. That can happen if there are no slots available for the mentioned minimum age. So, just for test, change the capacity to >= 0 and minAge==45
if(capacity>=0 and minAge == 45): available_date = json_data['centers'][i]['sessions'][j]['date'] message = message + center + "\n" + "Date : " + available_date + "\n" + "Available Capacity : " + str(capacity) + "\n" + "Minimum Age : " + str(minAge) + "\n\n"
Output:
center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 10-05-2021
Available Capacity : 0
Minimum Age : 45
center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 11-05-2021
Available Capacity : 0
Minimum Age : 45
center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 12-05-2021
Available Capacity : 0
Minimum Age : 45
center : Vada Cheepurupalli CVC Site
District : Visakhapatnam
address : Near Main Road Vada Cheepurupali
Date : 13-05-2021
Available Capacity : 0
Minimum Age : 45
At this point, we are able to successfully ping the server and get the vaccine information. We now need to send a notification if the vaccines are available.
Notify
For sending notifications, we will use an email service from AWS – Amazon Simple Email Service (SES). This service allows us to send emails from a verified email ID from a program, in our case, our python code.
To use this service, we need an AWS account and a verified email ID in SES. This post describes how to verify an email ID in SES. There are other SMTP libraries that will allow you to do that, but, they will fail when we move our entire code to cloud.
The notify function that will send an email if vaccines are available. This function takes two inputs
- The message to be sent – This is the message we created earlier after looping through the entire server response.
- The recipient email ID – This ID can be same as the sender email ID. If you want it to be different, you can register the other email ID as well in Amazon SES.
Include Necessary libraries:
To use Amazon SES in python, we need to include the AWS boto3 library. To do that, use the following statements:
from botocore.exceptions import ClientError # AWS communication errors from datetime import date # to create the date string
Create the notify function:
We will now create the notify function.
def notify(message, RECIPIENT): CHARSET = "UTF-8" SUBJECT = "Vaccine available!!" # Create a new SES resource and specify a region. client = boto3.client('ses',region_name=AWS_REGION) # Try to send the email. try: #Provide the contents of the email. response = client.send_email( Destination={ 'ToAddresses': [ RECIPIENT, ], }, Message={ 'Body': { 'Html': { 'Charset': CHARSET, 'Data': message, }, 'Text': { 'Charset': CHARSET, 'Data': message, }, }, 'Subject': { 'Charset': CHARSET, 'Data': SUBJECT, }, }, Source=SENDER, ) # Display an error if something goes wrong. except ClientError as e: print(e.response['Error']['Message']) else: print("Email sent! Message ID:"), print(response['MessageId'])
We will send an HTML message. To have a properly formatted email, the message that we create should be based on HTML. We don’t need anything fancy here. All the texts in the message are fine. It’s only the ‘newline’ character (“\n”) that need to be changed.
The “\n” causes the output to move to a new line. In HTML, the equivalent is “break” or “<br />”
To make this change, replace all the “\n” in the checkStatus() function with “<br />”
Covid Vaccine Availability Notifier – The main code:
This is the part that will execute all the functions we created so far. The comments in this section will explain the statements.
RECIPIENT = "[email protected]" # receivers email ID. Can be same as sender SENDER = "[email protected]" # sender email ID AWS_REGION = "ap-south-1" #Region where the SES email ID is verified. For me it was Mumbai, hence "ap-south-1" BODY_TEXT = ((checkStatus())) # here we ping the server and get the status. The status is then stored in BODY_TEXT if(BODY_TEXT != ''): # if BODY_TEXT is not empty means that there are some slots available. Notify only in that case notify(BODY_TEXT,RECIPIENT) # if slots available, notify
At this point, you should be receiving emails if there are slots based on your criteria. Do not forget to change back the capacity to greater than zero.
Improvements to Covid Vaccine Availability Notifier :
- You can make changes to the code to include more information.
- You can encapsulate the entire code to run in a time loop to check periodically
- Instead of hard-coding the district ID, you can make is a parameter and pass it as argument while calling the function.
This part requires that the computer where this code is running is always ON and always connected to the internet. That is not a very ideal approach. So, in the next part, we will use AWS to run the code on the cloud without manual intervention.
Download the Code:
You can download the code from the github page – Covid Vaccine availability notifier
Hi, I’m Vivek, a Senior Embedded Innovation Specialist. I have been working on Embedded Systems and IoT for the past 11 years. I love to share my knowledge and train those who are interested. Nerdyelectronics.com was started out of this interest. You can read my full profile in this link.