At first, I simply wanted to connect the NEO-6M GPS module to my Raspberry Pi 4, but obtaining coordinates without their further use seemed uninteresting. Therefore, below is the process of connecting the module, as well as Python scripts for querying the openweathermap weather service API, receiving weather forecasts from it, and sending them via a Telegram bot.
Connecting the GPS module
For this we have a scheme:
We install the necessary packages:
sudo pip install pynmea2
sudo apt-get install gpsd gpsd-clients gpsd-tools minicom
Then we modify the configuration after saving the current one:
sudo cp /boot/cmdline.txt /boot/cmdline.txt.bak
sudo nano /boot/cmdline.txt
Replace the settings with the following ones:
sudo nano /boot/config.txt
Add to the end of the file:
dtparam=spi=on
dtoverlay=pi3-disable-bt
core_freq=250
enable_uart=1
force_turbo=1
init_uart_baud=9600
Reboot the mini-computer:
sudo reboot now
Configure the GPS module to a baud rate of 9600:
stty -F /dev/ttyAMA0 9600
Kill all gpsd processes and add the device to the configuration:
sudo killall gpsd
sudo nano /etc/default/gpsd
We are interested in the DEVICES parameter.
DEVICES="/dev/ttyAMA0"
Restart the software:
sudo systemctl enable gpsd.socket
sudo systemctl start gpsd.socket
sudo cgps -s
We should get something like this:
Note that for the first time, the GPS module may take up to 20 minutes to acquire coordinates from satellites; subsequent acquisition times will be faster.
Script for obtaining coordinates from the GPS module
Now we need to write a Python script that will read latitude and longitude from the GPS module. We will expand it further later. Initially, it will look something like this:
#! /usr/bin/python
from gps import *
import time
import subprocess
import sys
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)
while True:
report = gpsd.next()
if report['class'] == 'TPV':
print(str(getattr(report,'lat',0.0)))
print(str(getattr(report,'lon',0.0)))
time.sleep(3)
Result:
Script for obtaining weather forecast through the openweathermap.org API
To begin with, register on openweathermap.org, go to the API keys section of your account, and generate a new key. Alternatively, you can use the default key.
First, let’s learn how to simply retrieve weather data from the API using our key:
import requests
api_url = 'https://api.openweathermap.org/data/2.5/onecall?'
params = dict(
lat=YOUR_LATITUDE,
lon=YOUR_LONGITUDE,
appid='YOUR_API_KEY',
units='metric',
exclude='minutely,daily',
lang='ua'
)
resp = requests.get(url=api_url, params=params)
print(resp.json())
Creating a chatbot in Telegram
As I have detailed this step in the previous project ‘Raspberry Pi + OpenCV: object recognition and notifications via Telegram bot‘ I won’t repeat it here. You can simply refer to the relevant section on Setting up a Telegram bot for Raspberry Pi. The main thing at this step is to create a chatbot and obtain the token and chat ID.
Let’s put everything together
Well, we have some simplified versions of scripts that query the GPS module to obtain coordinates. Additionally, we have a separate script for fetching weather information based on coordinates from the weather service API, and we also have a chatbot. Now it’s time to expand the functionality of these scripts and integrate everything into a cohesive whole.
The workflow algorithm will be as follows:
- Run the main script:
1.1. Obtain coordinates from the GPS module.
1.2. Launch the next script and pass the coordinates to it. - The next script receives coordinates from the previous one and:
2.1. Makes an API request to the weather service with the coordinates.
2.2. Parses the received response.
2.3. Sends the parsed response to Telegram.
Taking into account the described algorithm above, the main script might look like this:
from gps import *
import time
import sys
gpsd = gps(mode=WATCH_ENABLE|WATCH_NEWSTYLE)
while True:
report = gpsd.next()
if report['class'] == 'TPV':
latitude = str(getattr(report,'lat',0.0))
longitude = str(getattr(report,'lon',0.0))
os.system("python api_forecast.py " + latitude + " " + longitude)
sys.exit()
time.sleep(3)
As evident from the code, the script stores coordinates in variables and passes them as arguments when launching the next script. The sys
module is used to execute the next script. After the successful execution of the subsequent script, the main script terminates its operation using the sys.exit()
method.
Now let’s consider the next script:
import requests
import datetime
import sys
TOKEN = "TELEGRAM_BOT_TOKEN"
chat_id = "CHAT_ID"
api_url = 'https://api.openweathermap.org/data/2.5/onecall?'
params = dict(
lat=sys.argv[1],
lon=sys.argv[2],
appid='YOUR_API_KEY',
units='metric',
exclude='minutely,daily',
lang='uk'
)
resp = requests.get(url=api_url, params=params)
data = resp.json()
forecast = ''
limit = 12
index = 0
for dt in data["hourly"]:
forecast += "Час: " + datetime.datetime.fromtimestamp(dt["dt"]).strftime('%d-%m %H:%M') + "\nTemperature: " + str(dt["temp"]) + "\N{DEGREE SIGN}C." + " Description: " + dt["weather"][0]["description"] + "\n\n"
if index == limit:
break
index+=1
message = "Current weather:\n" + "Time: " + datetime.datetime.fromtimestamp(data["current"]["dt"]).strftime('%d-%m %H:%M') + "\nTemperature: " + str(data["current"]["temp"]) + "\N{DEGREE SIGN}C." + " Description: " + data["current"]["weather"][0]["description"] + "\n\n" + "Today's wheather forcast:\n" + forecast
url = f"https://api.telegram.org/bot{TOKEN}/sendMessage?chat_id={chat_id}&text={message}"
requests.get(url).json()
The described script fetches the current weather from the weather service and provides an hourly forecast for the next 12 hours. It compiles this information into a message and sends it to Telegram. To read the arguments from the main script, the sys.argv
method is utilized. The Telegram message looks like this:
You can further enhance this script to run regularly, for example, every day at 9 AM. This way, you’ll receive the current weather and the day’s forecast directly to your Telegram regularly 🙂
I found the folloving materials very helpful:
1. https://github.com/FranzTscharf/Python-NEO-6M-GPS-Raspberry-Pi
2. https://openweathermap.org/api/one-call-api
3. https://ozzmaker.com/using-python-with-a-gps-receiver-on-a-raspberry-pi/