Skip to content

Instantly share code, notes, and snippets.

@kebman
Last active July 7, 2023 07:07
Show Gist options
  • Save kebman/0d624a9d22c754658b6eee53eab951b2 to your computer and use it in GitHub Desktop.
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.
#!/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.
'''
@kebman
Copy link
Author

kebman commented Jul 6, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment