This RSS provides an xml with the last 30 registrations of earthquakes and other seismo-acoustic sources in and around the Netherlands.
I ended up adapting the script I started with ( from https://www.domoticz.com/forum/viewtopic.php?t=41380) to parse the XML of this RSS feed. Below is the result.
Functionality:
- Runs every 5 minutes and gets the most recent earthquakes.
- Updates alert device only when info has changed.
- It gives date, time, place, magintude, depth and distance (from your location), as well as a link for location on google maps and also a link for the more detailed source info at KNMI.
- It sets the alert color based on configurable distance ranges. I now use 0-100 km = RED; 100-200 km = ORANGE; 200-300 km = YELLOW; >300 km = GREY.
- It sends email when the distance is closer.
Result:
NB. I make use of the 'global_data' setup where scripts centrally store persistent data and where central helper functions are placed.
I give my entire 'global_data' script. You may or may not want to use the logging function. If not, you have also to modify corresponding lines in the script that call this function. Save this script as 'global_data', or take the used functions in your existing script.
t-Earthquake-KNMI
Code: Select all
-- 07-05-2024 script by Jan Peppink, https://ict.peppink.nl
-- Based on earlier script found on https://www.domoticz.com/forum/viewtopic.php?t=41380
-- Missed Dutch earthquakes. Modified script to get info from KNMI Aardbevingen RSS
-- Parse XML result to get info from the most recent of 30 in the list.
-- URL = https://cdn.knmi.nl/knmi/map/page/seismologie/GQuake_KNMI_RSS.xml
--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local alertIdx = n -- Set to the idx of the Virtual Alert sensor you have to create for this script
local mailto = '[email protected]' -- Set E-mail adres to sent notification to.
local knmiURL = 'https://cdn.knmi.nl/knmi/map/page/seismologie/GQuake_KNMI_RSS.xml'
-- Define distance for ALERTLEVEL colors
-- From dClose to the maxRadius we get: ALERTLEVEL_GREY
local dClose = 300 -- From distance dCloser to dClose: ALERTLEVEL_YELLOW
local dCloser = 200 -- From distance dClosest to dCloser: ALERTLEVEL_ORANGE (+ eMail notification)
local dClosest = 100 -- From distance 0 to closest: ALERTLEVEL_RED (+ eMail notification)
-- loging level 0 = NO logging, 1 = INFO, 2 = DEBUG, 3 = ERROR or 4 = FORCE
local debug_level = 0
return {
on = {
timer = {
'every 5 minutes',
},
httpResponses = { 'knmi-rss' } -- matches callback string below
},
logging = {
level = domoticz.LOG_INFO,
marker = 'KNMI-',
},
execute = function(domoticz, triggeredItem)
-- Set Local environment=================
local _u = domoticz.utils -- Holds subset of handy utilities.
local _h = domoticz.helpers -- Holds the global functions.
local _d = domoticz.globalData -- Holds the global data.
-- Set your loccation coordinates from Domoticz settings =================
local yourLatitude = domoticz.settings.location.latitude
local yourLongitude = domoticz.settings.location.longitude
-- Set your alert device index to store the result.
local alertLevel = domoticz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
local alertText = ''
local lastalertText = domoticz.devices(alertIdx).text -- Holds string of the previous round.
local lTimediff = 0 -- Calculate diff in seconds between UTC and local time of this event.
local delString = "" -- Holds (sub) string to delete.
-- Local Functions go here =============
-- Calculate distance using Haversine formula
local function calculateDistance(lat1, lon1, lat2, lon2)
local R = 6371 -- Earth radius in kilometers
local dLat = math.rad(lat2 - lat1)
local dLon = math.rad(lon2 - lon1)
local a = math.sin(dLat / 2) * math.sin(dLat / 2) + math.cos(math.rad(lat1)) * math.cos(math.rad(lat2)) * math.sin(dLon / 2) * math.sin(dLon / 2)
local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))
local distance = R * c
return distance
end
-- Now start to do something ============
if (triggeredItem.isTimer) then
_h.logthis( domoticz, debug_level, knmiURL )
domoticz.openURL({
url = knmiURL,
method = 'GET',
callback = 'knmi-rss'
})
elseif (triggeredItem.isHTTPResponse) then
if (triggeredItem.ok and triggeredItem.isXML) then
-- We have something, which looks like this:
--<rss xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:georss="http://www.georss.org/georss" version="2.0">
-- <channel>
-- <copyright>Copyright KNMI</copyright>
-- <description>KNMI - de laatste 30 registraties van aardbevingen en andere seismo-akoestische bronnen in en rondom Nederland</description>
-- <title>KNMI - de meest recente registraties van aardbevingen en andere seismo-akoestische bronnen in en rondom Nederland</title>
-- <item>
-- <title>2024-05-05, 't Zandt, M=0.3</title>
-- <description>2024-05-05, 19:14:45, Lat = 53.357, Lon = 6.783, Diepte = 3.0 km, M = 0.3, Plaats = 't Zandt, Author = KNMI, Type = Geinduceerd, Analyse = Reviewed</description>
-- <geo:lat>53.357</geo:lat>
-- <geo:lon>6.783</geo:lon>
-- <georss:point>53.357 6.783</georss:point>
-- <link>http://www.knmi.nl/nederland-nu/seismologie/aardbevingen/knmi2024ivvz</link>
-- <guid>knmi2024ivvz</guid>
-- </item>
local result_table = triggeredItem.xml
if type( result_table ) == "table" then
-- Get only the info from the first item.
-- Get link to page with details.
_h.logthis( domoticz, debug_level, result_table.rss.channel.item[1].link )
local qUrl = tostring( triggeredItem.xml.rss.channel.item[1].link )
-- The complete description to split up. Put is in a table.
_h.logthis( domoticz, debug_level, result_table.rss.channel.item[1].description )
local description_table = _u.stringSplit( result_table.rss.channel.item[1].description, ',' )
-- Get time (= UTC time) from the description_table.
-- Record 1 = 2024-05-05; Record 2 = 19:14:45 (strip the seconds)
local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 1, 6 )
atUTCtime = domoticz.time.dateToDate( atUTCtime, 'yyyy-mm-dd hh:MM', 'dd-mm-yyyy hh:MM', 0 )
_h.logthis( domoticz, debug_level, 'atUTCtime = ' .. atUTCtime )
-- Calculate the Local time.
local qUnixtime = domoticz.time.dateToTimestamp( atUTCtime, 'dd-mm-yyyy hh:MM' )
lTimediff = _h.getUTCtimediffseconds( qUnixtime )
local atLocalTime = domoticz.time.timestampToDate( qUnixtime, 'dd-mm-yyyy hh:MM', lTimediff )
_h.logthis( domoticz, debug_level, 'atLocalTime = ' .. atLocalTime )
-- Record 3 = Lat = 53.357
delString = "Lat = "
local qLat = tostring(description_table[3]):gsub( delString, "" )
_h.logthis( domoticz, debug_level, 'qLat = ' .. qLat )
-- Record 4 = Lon = 6.783
delString = "Lon = "
local qLon = tostring(description_table[4]):gsub( delString, "" )
_h.logthis( domoticz, debug_level, 'qLon = ' .. qLon )
-- Record 5 = Diepte = 3.0 km
delString = "Diepte = "
local qDepth = tostring(description_table[5]):gsub( delString, "" )
_h.logthis( domoticz, debug_level, 'qDepth = ' .. qDepth )
-- Record 6 = M = 0.3
delString = "M = "
local qMag = tostring( description_table[6]):gsub( delString, "" )
_h.logthis( domoticz, debug_level, 'qMag = ' .. qMag )
-- Record 7 = Plaats = 't Zandt
delString = "Plaats = "
local qPlace = tostring(description_table[7]):gsub( delString, "" )
_h.logthis( domoticz, debug_level, 'qPlace = ' .. qPlace )
-- Record 8 = Author = KNMI
local qAuthor = description_table[8]
-- Record 9 = Type = Geinduceerd
local qType = description_table[9]
-- Record 10 = Analyse = Reviewed
-- Calculate distance from home location.
local distance = calculateDistance( yourLatitude, yourLongitude, qLat, qLon )
-- Round the distance to the nearest kilometer
local roundedDistance = _u.round( distance, 0 )
--Set Alertlevel color based on distance.
if roundedDistance < dClosest then
alertLevel = domoticz.ALERTLEVEL_RED
elseif roundedDistance >= dClosest and roundedDistance < dCloser then
alertLevel = domoticz.ALERTLEVEL_ORANGE
elseif roundedDistance >= dCloser and roundedDistance < dClose then
alertLevel = domoticz.ALERTLEVEL_YELLOW
else
alertLevel = domoticz.ALERTLEVEL_GREY
end
--Set and format the new alertText
local alertText = tostring( atLocalTime .. ' uur in ' .. qPlace .. '\n' .. 'Magnitude: ' .. qMag .. '. Diepte: ' .. qDepth .. '. Afstand: ' .. roundedDistance ..' km.\n' .. '<a href="https://maps.google.com/?q=' .. qLat .. ',' .. qLon .. '" target="_blank">Toon locatie</a>' .. ' - ' .. '<a href="' .. qUrl .. '" target="_blank">Toon bron</a>' )
-- Only update and send mail when info has changed. and
if alertText ~= lastalertText then
-- We have new information, so update the device.
domoticz.devices(alertIdx).updateAlertSensor(alertLevel, alertText)
-- Only send email when it comes closer then dCloser
if roundedDistance <= dCloser then
--Set and format the new mail message
local message = tostring('Plaats: ' .. qPlace .. '<br>' ..
'Magnitude: ' .. qMag .. '<br>' ..
'Diepte: ' .. qDepth .. '.<br>' ..
'Lokale Tijd: ' .. atLocalTime .. ' uur.<br>' ..
'UTC Tijd: ' .. atUTCtime .. ' uur.<br>' ..
'Afstand: ' .. roundedDistance .. 'km.<br>'..
'Coördinaten: ' .. qLat .. ','.. qLon .. '<br>' ..
qAuthor .. '<br>' ..
qType .. '<br>' ..
'<a href="https://maps.google.com/?q=' .. qLat .. ',' .. qLon .. '">Toon locatie</a>' .. '<br>' ..
'<a href="' .. qUrl .. '">Toon bron</a>' .. '<br>')
domoticz.email( 'Aardbeving ' .. qPlace, message, mailto )
end
end
else
_h.logthis( domoticz, debug_level, 'No result_table found' )
end
else
_h.logthis( domoticz, debug_level, 'Item or XML - NOT OK' )
end
else
_h.logthis( domoticz, debug_level, 'Failed to fetch info' )
end
end
}
-- That's All --------------------------------------------------
global_data
Code: Select all
-- 05-01-2023: Script created by Jan peppink, https://ict.peppink.nl
-- This scripts holds all the globally persistent variables and helper functions
-- See the documentation in the wiki
-- NOTE: THERE CAN BE ONLY ONE global_data SCRIPT in your Domoticz install.
-- 26-03-2024: renamed variables; added: avgForcastwindspeed
-- 07-05-2024: Added function getUTCtimediffseconds
return {
-- Global persistent data
data = {
-- Used in t-Alarmeringen for Alarmeringen.nl.
lastAlarmNotification = {},
-- Used in t-OpenMeteo-Air, d-OpenMeteo-Wind and d-StookwijzerLokaal.
avgForcastLKI = { initial = 0 },
avgForcastwindspeed = { initial = 0 },
forcastHours = { initial = 0 },
},
-- Global helper functions
helpers = {
getUTCtimediffseconds = function(qUnixtime)
local timezone = os.date('%z', qUnixtime) -- "+0200"
local signum, hours, minutes = timezone:match '([+-])(%d%d)(%d%d)'
local lTimediff = (tonumber(signum..hours)*3600 + tonumber(signum..minutes)*60)
return lTimediff
end,
logthis = function( domoticz, debug_level, log_string )
-- Call this function with domoticz.helpers.logthis( domoticz, debug_level, 'string to log')
-- The function gives the option to log or not to log under certain conditions.
-- You then have only to set debug_level once in a script to change the logging level (or skip logging).
debug_level = debug_level or 0
if debug_level ~= 0 then
if debug_level == 1 then
log_level = domoticz.LOG_INFO
elseif debug_level == 2 then
log_level = domoticz.LOG_DEBUG
elseif debug_level == 3 then
log_level = domoticz.LOG_ERROR
elseif debug_level == 4
then log_level = domoticz.LOG_FORCE
else
return
end
-- Function. Creates a logging entry in the Domoticz log but respects the log level settings.
-- domoticz.LOG_INFO, domoticz.LOG_DEBUG, domoticz.LOG_ERROR or domoticz.LOG_FORCE
-- In Domoticz settings you can set the log level for dzVents.
-- For optional log_level the default is LOG_INFO
if log_string ~= "" then
-- domoticz.log(message, [level])
domoticz.log( log_string, log_level )
else
return
end
end
end,
}
}
-- That's All --------------------------------------------------