Last active
July 7, 2023 07:07
-
-
Save kebman/0d624a9d22c754658b6eee53eab951b2 to your computer and use it in GitHub Desktop.
A small script that alerts the user of lightning if it strikes within 16 km (10 miles) of your home in the Nordics, based on observations from The Norwegian Meteorological Institute.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python3 | |
from sseclient import SSEClient | |
import json | |
from math import sqrt | |
import winsound # NOTE: Windows only | |
from datetime import datetime, timezone, timedelta | |
''' | |
Version 2.1 (2023-07-07): A small script that alerts the user of lightning if it strikes within 16 km (10 miles) of your home position in the Nordics. | |
Based on lightning observations broadcast as SSE from The Norwegian Meteorological Institute, https://www.met.no/. | |
Updated to adhere to the new version of the SSE broadcasts from lyn.met.no. | |
''' | |
# MEASURING UNIT | |
# The latitude and longitude of your home or installation | |
# IMPORTANT: Edit this to reflect your actual situation | |
# home = (59.916817, 10.728491) | |
# old home Casa Lugubre home = (59.91804305609393, 10.741815212302594) | |
# new home Jernbaneveien 103 | |
home = (59.906744, 10.599598) | |
# If you hear an alert (a short boop), go to https://lyn.met.no/ to see it in action, | |
# or better yet, turn off your electrical peripherals, and pull the plug out of the socket, until the lighning storm passes. | |
# The more lighnings that are detected within your security zone, the more boops you'll hear. | |
# Wait at least 20 minutes after the storm has passed to turn things on again. | |
def tzFix(timestamp): | |
# Create a UTC datetime object from the timestamp | |
utc_datetime = datetime.utcfromtimestamp(timestamp).replace(tzinfo=timezone.utc) | |
# Define the GMT+02:00 timezone offset with DST for Oslo | |
offset = timedelta(hours=1) # GMT+02:00 without DST | |
# Oslo offset: Check if the datetime falls within the DST period (last Sunday of March to last Sunday of October) | |
dst_start = datetime(utc_datetime.year, 3, 31, 1, tzinfo=timezone.utc) | |
dst_end = datetime(utc_datetime.year, 10, 31, 1, tzinfo=timezone.utc) | |
if dst_start <= utc_datetime < dst_end: | |
offset += timedelta(hours=1) # Adjust offset for DST | |
# Create a timezone object with the calculated offset | |
tz = timezone(offset) | |
# Convert the UTC datetime object to the wanted timezone | |
return utc_datetime.astimezone(tz) | |
# measure the Euclidean distance between two points | |
# note: the served data is metric | |
def measureDist(x, y): | |
km = 100 | |
return sqrt((x - home[0]) ** 2 + (y - home[1]) ** 2) * km | |
# check if the distance is within the safety radius of your home or installation | |
def proxAlert(dist): | |
r = 16 # km ≈ 10 miles | |
if (dist <= r): | |
return True | |
else: | |
return False | |
# alert the user if a lightning is detected within the radius of the security perimeter | |
def distance_alert(x, y, t): | |
distance = measureDist(x, y) | |
km = "{:.2f}".format(distance) | |
alert = proxAlert(distance) | |
if (alert): | |
# play alert | |
winsound.Beep(250, 250) # NOTE: Windows only | |
# print('\a') # Beep on most systems | |
print("🚨⚡ %a, Lat/Lon: %a,%a Lighning detected %a km away!" % (t, x, y, km)) | |
else: | |
print("⚡ %a, Lat/Lon: %a,%a" % (t, x, y)) | |
# SSE STREAM of detected lightnings from The Norwegian Meteorological Institute, http://www.met.no | |
# get the stream | |
thundercloud = SSEClient('https://lyn.met.no/events') | |
# keep checking for new lighning strikes | |
for array in thundercloud: | |
try: | |
#t = tzFix(lightning[0]).strftime("%Y-%m-%d %H:%M:%S") # Oslo TZ | |
if(array.data != ''): | |
# thunder through the data | |
for lightning in json.loads(array.data): | |
x = lightning[2] | |
y = lightning[1] | |
t = tzFix(lightning[0]).strftime("%Y-%m-%d %H:%M:%S") # Oslo TZ | |
distance_alert(x, y, t) | |
else: | |
t = datetime.now().strftime("%Y-%m-%d %H:%M:%S") | |
print(": heartbeat %a" % t) | |
except json.JSONDecodeError as e: | |
print(f"Error decoding JSON: {e}") | |
''' | |
Known bugs: | |
Currently the script will need to be restarted if you lose internet access, or the computer goes to sleep while the script is running. | |
Known quirks: | |
The audio library will only work on Windows. | |
If you're on another system, you'll have to change the winsound library to something else, for instance `print('\a')`. | |
Hidden features: | |
If you copy the numbers after 'Lat/Lon:', you can paste it into Google, and it'll show you where the lightning struck. | |
''' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I did contemplate using a Haversine function instead, but it doesn't make much difference when it's such a short distance. If you for some reason want to measure distances beyond 10 miles you may consider it tho.