Earthquake info from KNMI

In this subforum you can show projects you have made, or you are busy with. Please create your own topic.

Moderator: leecollings

janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

I give it another try.

1. Remove your current script aardbevingen. You mixed everything in there.

2. Open a new DZvents script. Remove the template data and then paste the following in there. It holds the global helper functions.
I cleared it from content that has nothing to do with the current script.
Tip. Never only paste and run code. Read the comments. Try to understand what it does, before it is running FORMAT C: :-)
Save it with the name: 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.

----------------------------------------------------------------------------------
return {
	------------------------------------------
	-- Global persistent data
	data = {
		-- Global variables below here.

	},

	------------------------------------------
	-- Global helper functions
	helpers = {
		------------------------
		-- Used in t-Alarmeringen, t-Earthquake-KNMI,
	   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,
		------------------------
		-- Used in t-Earthquake-KNMI, t-Airplanes,
		calculateDistance = function( lat1, lon1, lat2, lon2)
			-- Calculate distance using Haversine formula
			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,
		------------------------
	}
}
-- That's All --------------------------------------------------
3. Then open a new DZvents script. Remove the template data and then paste the following in there.
A. Change IDX number and Email.
B. Save it as Aarbevingen-KNMI or what you want.

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
-- Function 'getUTCtimediffseconds' expected in global_data.
-- 09-05-2024 Directly make use of dz.log instead of the 'logthis' function in global_data.
-- 10-05-2024 Again some adjustments to the log function.
-- 13-05-2024 Added font color for hyperlinks.
-- 21-05-2024 Sometimes error on local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 2, 6 )
--			bad argument #1 to 'sub' (string expected, got nil); However - Manually never seen.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local alertIdx = 99999		   -- 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)

----------------------------------------------------------------------------------
return {
	on = {
		timer = { 
			--'every 2 minutes',  -- Only for testing.
			'at *:02',
			'at *:07',
			'at *:12',
			'at *:17',
			'at *:22',
			'at *:27',
			'at *:32',
			'at *:47',
			'at *:52',
			'at *:57',
		},
		httpResponses = {
			'knmi-rss'   -- matches callback string below
		}
	},
	logging = {
		-- Level can be domoticz.LOG_INFO, domoicz.LOG_MODULE_EXEC_INFO, domoticz.LOG_DEBUG, domoticz.LOG_ERROR or domoticz.LOG_FORCE
		level = domoticz.LOG_INFO,
		--level = domoticz.LOG_DEBUG,
		marker = 'KNMI-',
	},	
	execute = function( dz, triggeredItem )
		-- Set Local environment=================
		local _u = dz.utils	   -- Holds subset of handy utilities.
		local _h = dz.helpers	 -- Holds the global functions.
		--local _d = dz.globalData  -- Holds the global data.

		-- Set your loccation coordinates from Domoticz settings =================
		local yourLatitude = dz.settings.location.latitude
		local yourLongitude = dz.settings.location.longitude

		-- Use color variable for hyperlink font color
		htmlColor = 'Blue'

		-- Set your alert device index to store the result.
		local alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
		local alertText = ''
		local lastalertText = dz.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
			dz.openURL({
				url = knmiURL,
				method = 'GET',
				callback = 'knmi-rss'
			})	
		end
		
		if (triggeredItem.isHTTPResponse) then
			-- Process the obtained data.
			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
					dz.log( 'result_table: type = ' .. type(result_table), dz.LOG_DEBUG )
					-- Get only the info from the first item.

					-- Get link to page with details.
					dz.log( 'URL details = ' .. result_table.rss.channel.item[1].link, dz.LOG_DEBUG )
					local qUrl = tostring( triggeredItem.xml.rss.channel.item[1].link )

					-- The complete description to split up. Put it in a table.
					dz.log( 'Full description string = ' .. result_table.rss.channel.item[1].description, dz.LOG_DEBUG )
					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)
					dz.log( 'String 1 = "' .. description_table[1] .. '" en String 2 = "' .. description_table[2] .. '"', dz.LOG_DEBUG )
					local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 2, 6 )
					atUTCtime = dz.time.dateToDate( atUTCtime, 'yyyy-mm-dd hh:MM', 'dd-mm-yyyy hh:MM', 0 )
					dz.log( 'atUTCtime = ' .. atUTCtime, dz.LOG_DEBUG )

					-- Calculate the Local time.				
					local qUnixtime = dz.time.dateToTimestamp( atUTCtime, 'dd-mm-yyyy hh:MM' )
					lTimediff = _h.getUTCtimediffseconds( qUnixtime )
					local atLocalTime = dz.time.timestampToDate( qUnixtime, 'dd-mm-yyyy hh:MM', lTimediff )
					dz.log( 'atLocalTime = ' .. atLocalTime, dz.LOG_DEBUG )

					-- Record 3 = Lat = 53.357
					delString = "Lat = "
					local qLat = tostring(description_table[3]):gsub( delString, "" )
					dz.log( 'qLat = ' .. qLat, dz.LOG_DEBUG )
				
					-- Record 4 = Lon = 6.783
					delString = "Lon = "
					local qLon = tostring(description_table[4]):gsub( delString, "" )
					dz.log( 'qLon = ' .. qLon, dz.LOG_DEBUG )
				
					-- Record 5 = Diepte = 3.0 km
					delString = "Diepte = "
					local qDepth = tostring(description_table[5]):gsub( delString, "" )
					dz.log( 'qDepth = ' .. qDepth, dz.LOG_DEBUG )
				
					-- Record 6 = M = 0.3
					delString = "M = "
					local qMag = tostring( description_table[6]):gsub( delString, "" )
					dz.log( 'qMag = ' .. qMag, dz.LOG_DEBUG )
				
					-- Record 7 = Plaats = 't Zandt
					delString = "Plaats = "
					local qPlace = tostring(description_table[7]):gsub( delString, "" )
					dz.log( 'qPlace = ' .. qPlace, dz.LOG_DEBUG )

					-- Record 8 = Author = KNMI
					local qAuthor = description_table[8]
					dz.log( 'qAuthor = ' .. qAuthor, dz.LOG_DEBUG )
					
					-- Record 9 = Type = Geinduceerd
					local qType = description_table[9]
					dz.log( 'qType = ' .. qType, dz.LOG_DEBUG )
					
					-- 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 = dz.ALERTLEVEL_RED
					elseif roundedDistance >= dClosest and roundedDistance < dCloser then
						alertLevel = dz.ALERTLEVEL_ORANGE
					elseif roundedDistance >= dCloser and roundedDistance < dClose then
						alertLevel = dz.ALERTLEVEL_YELLOW
					else
						alertLevel = dz.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"><span style="color: ' ..  htmlColor .. '">Toon locatie</span></a>' .. ' - ' .. '<a href="'  .. qUrl ..  '" target="_blank"><span style="color: ' ..  htmlColor .. '">Toon bron</span></a>' )
					dz.log( 'LastalertText = ' .. lastalertText, dz.LOG_DEBUG )
					dz.log( 'NewalertText = ' .. alertText, dz.LOG_DEBUG )
					
					-- Only update and send mail when info has changed. and 
					if alertText ~= lastalertText then
						-- We have new information, so update the device.
						dz.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>' )
							-- Send the mail
							dz.email( 'Aardbeving ' .. qPlace, message, mailto, 0 )
						end
					end
				else
					dz.log( 'No result_table found', dz.LOG_ERROR )
				end
			else
				dz.log( 'Item or XML - NOT OK', dz.LOG_ERROR )
			end
		end
	end
}
-- That's All --------------------------------------------------
Hope this helps.
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
Fredom
Posts: 160
Joined: Saturday 19 September 2020 21:02
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: Krimpen aan den IJssel
Contact:

Re: Earthquake info from KNMI

Post by Fredom »

janpep wrote: Saturday 06 July 2024 21:05 I give it another try.

1. Remove your current script aardbevingen. You mixed everything in there.

2. Open a new DZvents script. Remove the template data and then paste the following in there. It holds the global helper functions.
I cleared it from content that has nothing to do with the current script.
Tip. Never only paste and run code. Read the comments. Try to understand what it does, before it is running FORMAT C: :-)
Save it with the name: 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.

----------------------------------------------------------------------------------
return {
	------------------------------------------
	-- Global persistent data
	data = {
		-- Global variables below here.

	},

	------------------------------------------
	-- Global helper functions
	helpers = {
		------------------------
		-- Used in t-Alarmeringen, t-Earthquake-KNMI,
	   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,
		------------------------
		-- Used in t-Earthquake-KNMI, t-Airplanes,
		calculateDistance = function( lat1, lon1, lat2, lon2)
			-- Calculate distance using Haversine formula
			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,
		------------------------
	}
}
-- That's All --------------------------------------------------
3. Then open a new DZvents script. Remove the template data and then paste the following in there.
A. Change IDX number and Email.
B. Save it as Aarbevingen-KNMI or what you want.

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
-- Function 'getUTCtimediffseconds' expected in global_data.
-- 09-05-2024 Directly make use of dz.log instead of the 'logthis' function in global_data.
-- 10-05-2024 Again some adjustments to the log function.
-- 13-05-2024 Added font color for hyperlinks.
-- 21-05-2024 Sometimes error on local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 2, 6 )
--			bad argument #1 to 'sub' (string expected, got nil); However - Manually never seen.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local alertIdx = 99999		   -- 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)

----------------------------------------------------------------------------------
return {
	on = {
		timer = { 
			--'every 2 minutes',  -- Only for testing.
			'at *:02',
			'at *:07',
			'at *:12',
			'at *:17',
			'at *:22',
			'at *:27',
			'at *:32',
			'at *:47',
			'at *:52',
			'at *:57',
		},
		httpResponses = {
			'knmi-rss'   -- matches callback string below
		}
	},
	logging = {
		-- Level can be domoticz.LOG_INFO, domoicz.LOG_MODULE_EXEC_INFO, domoticz.LOG_DEBUG, domoticz.LOG_ERROR or domoticz.LOG_FORCE
		level = domoticz.LOG_INFO,
		--level = domoticz.LOG_DEBUG,
		marker = 'KNMI-',
	},	
	execute = function( dz, triggeredItem )
		-- Set Local environment=================
		local _u = dz.utils	   -- Holds subset of handy utilities.
		local _h = dz.helpers	 -- Holds the global functions.
		--local _d = dz.globalData  -- Holds the global data.

		-- Set your loccation coordinates from Domoticz settings =================
		local yourLatitude = dz.settings.location.latitude
		local yourLongitude = dz.settings.location.longitude

		-- Use color variable for hyperlink font color
		htmlColor = 'Blue'

		-- Set your alert device index to store the result.
		local alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
		local alertText = ''
		local lastalertText = dz.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
			dz.openURL({
				url = knmiURL,
				method = 'GET',
				callback = 'knmi-rss'
			})	
		end
		
		if (triggeredItem.isHTTPResponse) then
			-- Process the obtained data.
			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
					dz.log( 'result_table: type = ' .. type(result_table), dz.LOG_DEBUG )
					-- Get only the info from the first item.

					-- Get link to page with details.
					dz.log( 'URL details = ' .. result_table.rss.channel.item[1].link, dz.LOG_DEBUG )
					local qUrl = tostring( triggeredItem.xml.rss.channel.item[1].link )

					-- The complete description to split up. Put it in a table.
					dz.log( 'Full description string = ' .. result_table.rss.channel.item[1].description, dz.LOG_DEBUG )
					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)
					dz.log( 'String 1 = "' .. description_table[1] .. '" en String 2 = "' .. description_table[2] .. '"', dz.LOG_DEBUG )
					local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 2, 6 )
					atUTCtime = dz.time.dateToDate( atUTCtime, 'yyyy-mm-dd hh:MM', 'dd-mm-yyyy hh:MM', 0 )
					dz.log( 'atUTCtime = ' .. atUTCtime, dz.LOG_DEBUG )

					-- Calculate the Local time.				
					local qUnixtime = dz.time.dateToTimestamp( atUTCtime, 'dd-mm-yyyy hh:MM' )
					lTimediff = _h.getUTCtimediffseconds( qUnixtime )
					local atLocalTime = dz.time.timestampToDate( qUnixtime, 'dd-mm-yyyy hh:MM', lTimediff )
					dz.log( 'atLocalTime = ' .. atLocalTime, dz.LOG_DEBUG )

					-- Record 3 = Lat = 53.357
					delString = "Lat = "
					local qLat = tostring(description_table[3]):gsub( delString, "" )
					dz.log( 'qLat = ' .. qLat, dz.LOG_DEBUG )
				
					-- Record 4 = Lon = 6.783
					delString = "Lon = "
					local qLon = tostring(description_table[4]):gsub( delString, "" )
					dz.log( 'qLon = ' .. qLon, dz.LOG_DEBUG )
				
					-- Record 5 = Diepte = 3.0 km
					delString = "Diepte = "
					local qDepth = tostring(description_table[5]):gsub( delString, "" )
					dz.log( 'qDepth = ' .. qDepth, dz.LOG_DEBUG )
				
					-- Record 6 = M = 0.3
					delString = "M = "
					local qMag = tostring( description_table[6]):gsub( delString, "" )
					dz.log( 'qMag = ' .. qMag, dz.LOG_DEBUG )
				
					-- Record 7 = Plaats = 't Zandt
					delString = "Plaats = "
					local qPlace = tostring(description_table[7]):gsub( delString, "" )
					dz.log( 'qPlace = ' .. qPlace, dz.LOG_DEBUG )

					-- Record 8 = Author = KNMI
					local qAuthor = description_table[8]
					dz.log( 'qAuthor = ' .. qAuthor, dz.LOG_DEBUG )
					
					-- Record 9 = Type = Geinduceerd
					local qType = description_table[9]
					dz.log( 'qType = ' .. qType, dz.LOG_DEBUG )
					
					-- 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 = dz.ALERTLEVEL_RED
					elseif roundedDistance >= dClosest and roundedDistance < dCloser then
						alertLevel = dz.ALERTLEVEL_ORANGE
					elseif roundedDistance >= dCloser and roundedDistance < dClose then
						alertLevel = dz.ALERTLEVEL_YELLOW
					else
						alertLevel = dz.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"><span style="color: ' ..  htmlColor .. '">Toon locatie</span></a>' .. ' - ' .. '<a href="'  .. qUrl ..  '" target="_blank"><span style="color: ' ..  htmlColor .. '">Toon bron</span></a>' )
					dz.log( 'LastalertText = ' .. lastalertText, dz.LOG_DEBUG )
					dz.log( 'NewalertText = ' .. alertText, dz.LOG_DEBUG )
					
					-- Only update and send mail when info has changed. and 
					if alertText ~= lastalertText then
						-- We have new information, so update the device.
						dz.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>' )
							-- Send the mail
							dz.email( 'Aardbeving ' .. qPlace, message, mailto, 0 )
						end
					end
				else
					dz.log( 'No result_table found', dz.LOG_ERROR )
				end
			else
				dz.log( 'Item or XML - NOT OK', dz.LOG_ERROR )
			end
		end
	end
}
-- That's All --------------------------------------------------
Hope this helps.

Hi,
It works perfectly now.
Thanks for the script and the clear explanation
Yours sincerely,
Fred

Rasberry Pi 3B+ - Debian Trixie - Domoticz 2025.2
RFLink - RFXCom - Zigbee (CC2531)
P1 Smart Meter - KaKu
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

Great.
And if I am right you got two earthquakes in Middelstum and Loppersum short after your post. :-)
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
Fredom
Posts: 160
Joined: Saturday 19 September 2020 21:02
Target OS: Raspberry Pi / ODroid
Domoticz version: 2025.1
Location: Krimpen aan den IJssel
Contact:

Re: Earthquake info from KNMI

Post by Fredom »

janpep wrote: Sunday 07 July 2024 13:11 Great.
And if I am right you got two earthquakes in Middelstum and Loppersum short after your post. :-)
Yes correct
Yours sincerely,
Fred

Rasberry Pi 3B+ - Debian Trixie - Domoticz 2025.2
RFLink - RFXCom - Zigbee (CC2531)
P1 Smart Meter - KaKu
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

I forgot to update here.
URL only gives old data. It has changed.
Here the updated script with new URL.
A limit can be given. I have set it to 1, because only the most recent one is used.
Change your device idx and e-mail address.

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
-- Function 'getUTCtimediffseconds' expected in global_data.
-- 09-05-2024 Directly make use of dz.log instead of the 'logthis' function in global_data.
-- 10-05-2024 Again some adjustments to the log function.
-- 13-05-2024 Added font color for hyperlinks.
-- 21-05-2024 Sometimes error on local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 2, 6 )
--            bad argument #1 to 'sub' (string expected, got nil); However - Manually never seen.
-- 2025-01-31 URL changed. Can set limit in the URL So, now get only last one. 
--            https://rdsa.knmi.nl/abcws/event/query?format=rss&limit=1


--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local alertIdx = 99999           -- Set to the idx of the Virtual Alert sensor you have to create for this script
local mailto = 'YourEmailAddress'  -- Set to your E-mail adres to sent notification to.
local knmiURL = 'https://rdsa.knmi.nl/abcws/event/query?format=rss&limit=1'

-- 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)

----------------------------------------------------------------------------------
return {
	on = {
		timer = { 
			--'every 2 minutes',  -- Only for testing.
			'at *:02',
			'at *:07',
			'at *:12',
			'at *:17',
			'at *:22',
			'at *:27',
			'at *:32',
			'at *:47',
			'at *:52',
			'at *:57',
        },
		httpResponses = {
            'knmi-rss'   -- matches callback string below
        }
	},
    logging = {
		-- Level can be domoticz.LOG_INFO, domoticz.LOG_STATUS, domoticz.LOG_ERROR or domoticz.LOG_DEBUG
		level = domoticz.LOG_STATUS,
		--level = domoticz.LOG_DEBUG,
    	marker = 'KNMI-',
    },	
	execute = function( dz, triggeredItem )
        -- Set Local environment=================
        local _u = dz.utils       -- Holds subset of handy utilities.
        local _h = dz.helpers     -- Holds the global functions.
        --local _d = dz.globalData  -- Holds the global data.

	    -- Set your loccation coordinates from Domoticz settings =================
		local yourLatitude = dz.settings.location.latitude
		local yourLongitude = dz.settings.location.longitude

        -- Use color variable for hyperlink font color
        htmlColor = 'Blue'

        -- Set your alert device index to store the result.
        local alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
        local alertText = ''
		local lastalertText = dz.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
			dz.openURL({
			    url = knmiURL,
				method = 'GET',
				callback = 'knmi-rss'
			})	
		end
        
		if (triggeredItem.isHTTPResponse) then
            -- Process the obtained data.
			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
                    dz.log( 'result_table: type = ' .. type(result_table), dz.LOG_DEBUG )
                    -- Get only the info from the first item.

                    -- Get link to page with details.
                    dz.log( 'URL details = ' .. result_table.rss.channel.item.link, dz.LOG_DEBUG )
                    local qUrl = tostring( result_table.rss.channel.item.link )

                    -- The complete description to split up. Put it in a table.
                    dz.log( 'Full description string = ' .. result_table.rss.channel.item.description, dz.LOG_DEBUG )
                    local description_table = _u.stringSplit( result_table.rss.channel.item.description, ',' )

                    -- Get time (= UTC time) from the description_table.
                    -- Record 1 = 2024-05-05; Record 2 = 19:14:45 (strip the seconds)
                    dz.log( 'String 1 = "' .. description_table[1] .. '" en String 2 = "' .. description_table[2] .. '"', dz.LOG_DEBUG )
                    local atUTCtime = description_table[1] .. ' ' .. string.sub( description_table[2], 2, 6 )
                    atUTCtime = dz.time.dateToDate( atUTCtime, 'yyyy-mm-dd hh:MM', 'dd-mm-yyyy hh:MM', 0 )
                    dz.log( 'atUTCtime = ' .. atUTCtime, dz.LOG_DEBUG )

                    -- Calculate the Local time.			    
                    local qUnixtime = dz.time.dateToTimestamp( atUTCtime, 'dd-mm-yyyy hh:MM' )
                    lTimediff = _h.getUTCtimediffseconds( qUnixtime )
                    local atLocalTime = dz.time.timestampToDate( qUnixtime, 'dd-mm-yyyy hh:MM', lTimediff )
                    dz.log( 'atLocalTime = ' .. atLocalTime, dz.LOG_DEBUG )

                    -- Record 3 = Lat = 53.357
                    delString = "Lat = "
                    local qLat = tostring(description_table[3]):gsub( delString, "" )
                    dz.log( 'qLat = ' .. qLat, dz.LOG_DEBUG )
			    
                    -- Record 4 = Lon = 6.783
                    delString = "Lon = "
                    local qLon = tostring(description_table[4]):gsub( delString, "" )
                    dz.log( 'qLon = ' .. qLon, dz.LOG_DEBUG )
			    
                    -- Record 5 = Diepte = 3.0 km
                    delString = "Diepte = "
                    local qDepth = tostring(description_table[5]):gsub( delString, "" )
                    dz.log( 'qDepth = ' .. qDepth, dz.LOG_DEBUG )
			    
                    -- Record 6 = M = 0.3
                    delString = "M = "
                    local qMag = tostring( description_table[6]):gsub( delString, "" )
                    dz.log( 'qMag = ' .. qMag, dz.LOG_DEBUG )
			    
                    -- Record 7 = Plaats = 't Zandt
                    delString = "Plaats = "
                    local qPlace = tostring(description_table[7]):gsub( delString, "" )
                    dz.log( 'qPlace = ' .. qPlace, dz.LOG_DEBUG )

                    -- Record 8 = Author = KNMI
                    local qAuthor = description_table[8]
                    dz.log( 'qAuthor = ' .. qAuthor, dz.LOG_DEBUG )
                    
                    -- Record 9 = Type = Geinduceerd
                    local qType = description_table[9]
                    dz.log( 'qType = ' .. qType, dz.LOG_DEBUG )
                    
                    -- 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 = dz.ALERTLEVEL_RED
                    elseif roundedDistance >= dClosest and roundedDistance < dCloser then
                        alertLevel = dz.ALERTLEVEL_ORANGE
                    elseif roundedDistance >= dCloser and roundedDistance < dClose then
                        alertLevel = dz.ALERTLEVEL_YELLOW
                    else
                        alertLevel = dz.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"><span style="color: ' ..  htmlColor .. '">Toon locatie</span></a>' .. ' - ' .. '<a href="'  .. qUrl ..  '" target="_blank"><span style="color: ' ..  htmlColor .. '">Toon bron</span></a>' )
                    dz.log( 'LastalertText = ' .. lastalertText, dz.LOG_DEBUG )
                    dz.log( 'NewalertText = ' .. alertText, dz.LOG_DEBUG )
                    
                    -- Only update and send mail when info has changed. and 
                    if alertText ~= lastalertText then
                        -- We have new information, so update the device.
                        dz.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>' )
                            -- Send the mail
                            dz.email( 'Aardbeving ' .. qPlace, message, mailto, 0 )
                        end
                    end
                else
                    dz.log( 'No result_table found', dz.LOG_ERROR )
                end
	        else
    			dz.log( 'Item or XML - NOT OK', dz.LOG_ERROR )
		    end
		end
	end
}
-- That's All --------------------------------------------------
Aardbeving-JanPep-3.png
Aardbeving-JanPep-3.png (10.22 KiB) Viewed 1630 times
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
HvdW
Posts: 663
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: Earthquake info from KNMI

Post by HvdW »

Here is a new Earthquake script with more robust error handling and a new URL.

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.
-- Modified on 2025-01-21 to use new KNMI API: https://rdsa.knmi.nl/fdsnws/event/1/query

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local alertIdx = 936           -- Aardbevingen Set to the idx of the Virtual Alert sensor you have to create for this script
-- Aardbeving info
local mailto = '[email protected]' -- Set E-mail adres to sent notification to.
local knmiURL = 'https://rdsa.knmi.nl/fdsnws/event/1/query?format=text&minlatitude=50.5&maxlatitude=53.7&minlongitude=3.3&maxlongitude=7.2&limit=5' -- =~ the Netherlands

-- 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 (+ e-Mail notification)

return {
	on = {
		timer = { 
			'every minute',
        },
		httpResponses = {
            'knmi-api'   -- matches callback string below
        }
	},
    logging = {
        level = domoticz.LOG_DEBUG,  -- Tijdelijk op DEBUG voor troubleshooting
        -- level = domoticz.LOG_ERROR,
    	marker = 'KNMI-earthquake',
    },	
	execute = function(domoticz, triggeredItem)
	    
        -- Set Local environment=================
        local _u = domoticz.utils       -- Holds subset of handy utilities.
        local _h = domoticz.helpers     -- Holds the global functions.

	    -- Set your loccation coordinates from Domoticz settings =================
		local yourLatitude = domoticz.settings.location.latitude
		local yourLongitude = domoticz.settings.location.longitude

        -- Controleer of de alert device bestaat
        if not domoticz.devices(alertIdx) then
            domoticz.log('Fout: Alert device met idx ' .. alertIdx .. ' bestaat niet. Maak een Virtual Alert sensor aan met de naam "Aardbevingen".', domoticz.LOG_ERROR)
            return -- Stop de uitvoering
        end

        -- 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 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

		-- Betere split functie die lege velden behoudt
		local function splitPreserveEmpty(str, delimiter)
		    local result = {}
		    local from = 1
		    local delim_from, delim_to = string.find(str, delimiter, from)
		    while delim_from do
		        table.insert(result, string.sub(str, from, delim_from-1))
		        from = delim_to + 1
		        delim_from, delim_to = string.find(str, delimiter, from)
		    end
		    table.insert(result, string.sub(str, from))
		    return result
		end

        -- Now start to do something ============
		if (triggeredItem.isTimer) then
		    domoticz.log('Timer triggered, fetching data from: ' .. knmiURL, domoticz.LOG_DEBUG)
			domoticz.openURL({
			    url = knmiURL,
				method = 'GET',
				callback = 'knmi-api',
				headers = {
				    ['Accept'] = 'text/plain',
				    ['User-Agent'] = 'Domoticz'
				}
			})	
		elseif (triggeredItem.isHTTPResponse) then
		    domoticz.log('HTTP Response ontvangen', domoticz.LOG_DEBUG)
		    domoticz.log('Status: ' .. triggeredItem.statusCode, domoticz.LOG_DEBUG)
		    domoticz.log('OK: ' .. tostring(triggeredItem.ok), domoticz.LOG_DEBUG)
		    
			if (triggeredItem.ok) then
			    -- Controleer of we data hebben, ongeacht het type
			    if triggeredItem.data then
			        domoticz.log('Data ontvangen, lengte: ' .. string.len(triggeredItem.data), domoticz.LOG_DEBUG)
			        domoticz.log('Eerste 500 chars: ' .. string.sub(triggeredItem.data, 1, 500), domoticz.LOG_DEBUG)
			        
			        local responseText = triggeredItem.data
			        
			        -- Split de response in regels
			        local lines = _u.stringSplit(responseText, '\n')
			        domoticz.log('Aantal regels: ' .. #lines, domoticz.LOG_DEBUG)
			        
			        -- Log alle regels voor debugging
			        for i, line in ipairs(lines) do
			            domoticz.log('Regel ' .. i .. ': ' .. line, domoticz.LOG_DEBUG)
			        end
			        
			        -- Controleer of er minstens 2 regels zijn (header + data)
			        if #lines < 2 then
			            domoticz.log('Geen aardbevingsdata gevonden in response', domoticz.LOG_ERROR)
			            return
			        end
			        
			        -- Zoek de eerste data regel (sla header over)
			        local firstDataLine = nil
			        for i = 2, #lines do
			            local line = lines[i]
			            if string.len(line) > 10 and string.sub(line, 1, 1) ~= '#' then
			                firstDataLine = line
			                break
			            end
			        end
			        
			        if not firstDataLine then
			            domoticz.log('Geen geldige data regel gevonden', domoticz.LOG_ERROR)
			            return
			        end
			        
			        domoticz.log('Te verwerken regel: ' .. firstDataLine, domoticz.LOG_DEBUG)
			        
			        -- Verwerk de eerste data regel MET behoud van lege velden
			        local fields = splitPreserveEmpty(firstDataLine, '|')
			        domoticz.log('Aantal velden: ' .. #fields, domoticz.LOG_DEBUG)
			        
			        -- Log alle velden voor debugging
			        for i, field in ipairs(fields) do
			            domoticz.log('Veld ' .. i .. ': [' .. tostring(field) .. ']', domoticz.LOG_DEBUG)
			        end
			        
			        -- Controleer of we voldoende velden hebben
			        if #fields < 14 then
			            domoticz.log('Ongeldig aantal velden in data: ' .. #fields .. ' (verwacht 14)', domoticz.LOG_ERROR)
			            return
			        end
			        
			        -- Parse de velden - nu met correcte indices
			        local eventId = fields[1] or ""
			        local timeUTC = fields[2] or ""
			        local qLat = fields[3] or "0"
			        local qLon = fields[4] or "0"
			        local qDepth = fields[5] or "0"
			        -- fields[6] = Author (leeg)
			        -- fields[7] = Catalog (leeg)
			        local contributor = fields[8] or ""
			        -- fields[9] = ContributorID
			        local magType = fields[10] or ""
			        local magnitude = fields[11] or "0"
			        -- fields[12] = MagAuthor (leeg)
			        local qPlace = fields[13] or "Onbekende locatie"
			        local eventType = fields[14] or "earthquake"
			        
			        -- Vertaal eventType naar Nederlands
			        local eventTypeNL = "aardbeving"
			        if eventType == "induced or triggered event" then
			            eventTypeNL = "triggered event"
			        end
			        
			        domoticz.log('Event: ' .. eventId .. ' op ' .. timeUTC .. ' bij ' .. qPlace, domoticz.LOG_DEBUG)
			        
			        -- Converteer tijd naar leesbaar formaat
			        -- Tijd is in formaat: 2025-09-22T13:18:26.699999
			        local utcTimeFormatted = string.gsub(timeUTC, "T", " ")
			        utcTimeFormatted = string.gsub(utcTimeFormatted, "%.%d+", "")  -- Verwijder milliseconden
			        
			        local atUTCtime = domoticz.time.dateToDate(utcTimeFormatted, 'yyyy-mm-dd hh:MM:SS', 'dd-mm-yyyy hh:MM', 0)
			        domoticz.log('atUTCtime = ' .. atUTCtime, domoticz.LOG_DEBUG)

			        -- Calculate the Local time.			    
			        local qUnixtime = domoticz.time.dateToTimestamp(atUTCtime, 'dd-mm-yyyy hh:MM')
			        if not qUnixtime then
			            domoticz.log('Fout bij converteren tijd: ' .. atUTCtime, domoticz.LOG_ERROR)
			            return
			        end
			        
			        lTimediff = _h.getUTCtimediffseconds(qUnixtime)
			        local atLocalTime = domoticz.time.timestampToDate(qUnixtime, 'dd-mm-yyyy hh:MM', lTimediff)
			        domoticz.log('atLocalTime = ' .. atLocalTime, domoticz.LOG_DEBUG)

			        -- Log de geparseerde data
			        domoticz.log('qLat = ' .. qLat, domoticz.LOG_DEBUG)
			        domoticz.log('qLon = ' .. qLon, domoticz.LOG_DEBUG)
			        domoticz.log('qDepth = ' .. qDepth, domoticz.LOG_DEBUG)
			        domoticz.log('Magnitude = ' .. magnitude, domoticz.LOG_DEBUG)
			        domoticz.log('qPlace = ' .. qPlace, domoticz.LOG_DEBUG)
			        domoticz.log('EventType = ' .. eventType, domoticz.LOG_DEBUG)
					
			        -- Calculate distance from home location.
			        local distance = calculateDistance(yourLatitude, yourLongitude, tonumber(qLat), tonumber(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
			        
			        -- Maak de detail URL (gebruik eventId voor KNMI detail pagina)
			        local qUrl = "https://www.knmi.nl/nederland-nu/seismologie/aardbevingen/" .. eventId
			        
			        --Set and format the new alertText
                    local alertText = tostring(atLocalTime .. ' uur in ' .. qPlace .. '\n' .. 'Magnitude: ' .. string.format("%.1f", tonumber(magnitude)) .. '. Diepte: ' .. qDepth .. ' km. Afstand: ' .. roundedDistance ..' km.\nType: ' .. eventTypeNL .. '\n<a href="https://maps.google.com/?q=' .. qLat .. ',' .. qLon .. '" target="_blank" style="color: blue; text-decoration: underline;">Toon locatie</a>' .. ' - ' .. '<a href="'  .. qUrl ..  '" target="_blank" style="color: blue; text-decoration: underline;">Toon bron</a>')
			        -- Only update and send mail when info has changed. 
			        if alertText ~= lastalertText then
			            domoticz.log('Nieuwe aardbevingsinformatie, update device', domoticz.LOG_DEBUG)
			            -- 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
			                domoticz.log('Aardbeving binnen ' .. dCloser .. ' km, verstuur e-mail', domoticz.LOG_DEBUG)
			                --Set and format the new mail message
			                local message = tostring('Plaats: ' .. qPlace .. '<br>' ..
			                'Magnitude: ' .. string.format("%.1f", tonumber(magnitude)) .. '<br>' ..
			                'Diepte: ' .. qDepth .. ' km.<br>' ..
			                'Lokale Tijd: ' .. atLocalTime .. ' uur.<br>' ..
			                'UTC Tijd: ' .. atUTCtime .. ' uur.<br>' ..
			                'Afstand: ' .. roundedDistance .. ' km.<br>'..
			                'Coördinaten: ' .. qLat .. ','.. qLon .. '<br>' ..
			                'Type: ' .. eventTypeNL .. '<br>' ..
			                '<a href="https://maps.google.com/?q=' .. qLat .. ',' .. qLon .. '">Toon locatie</a>' .. '<br>' ..
			                '<a href="' .. qUrl .. '" style="color: blue; text-decoration: underline;">Toon bron</a>' .. '<br>')
			                domoticz.email('Aardbeving ' .. qPlace, message, mailto)
			            end
			        else
			            domoticz.log('Geen nieuwe aardbevingsinformatie', domoticz.LOG_DEBUG)
			        end
			    else
			        domoticz.log('Geen data in HTTP response', domoticz.LOG_ERROR)
			    end
	        else
    			domoticz.log('HTTP response NOT OK: ' .. triggeredItem.statusCode, domoticz.LOG_ERROR)
                if triggeredItem.data then
                    domoticz.log('Response data: ' .. string.sub(triggeredItem.data, 1, 500), domoticz.LOG_DEBUG)
                end
		    end
		else
			domoticz.log('Onbekende trigger', domoticz.LOG_DEBUG)
		end
	end
}
aardbevingen.png
aardbevingen.png (14.91 KiB) Viewed 185 times
Bugs bug me.
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

HvdW wrote: Monday 06 October 2025 0:28 Here is a new Earthquake script with more robust error handling and a new URL.
That is a very short mention.
Can you say something more about it? Give some explanation? Tell what has been adjusted and where? Put that in the comment with your name on it.? What was the reason for a new URL?
I had already changed the URL to use new URL on 31-01-2025. I still use that same URL and had shown the earthquake in Heerlen in the same way.
What is changed now in the URL and why? What is the advantage?
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
Kedi
Posts: 595
Joined: Monday 20 March 2023 14:41
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Somewhere in NL
Contact:

Re: Earthquake info from KNMI

Post by Kedi »

That would be nice. But just a compare of the scripts makes it visible too.
I have some remarks too.
I use this to trigger the update of the widget, with the current solution I sometimes get for some reason false updates.

Code: Select all

                    if string.sub(alertText, 1, 16) ~= string.sub(lastalertText, 1, 16) then
I use the name instead of the idx of the widget.
I use ALL the functions inside the dzVents script, so I do not depend on the globals.
Logic will get you from A to B. Imagination will take you everywhere.
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

Kedi wrote: Tuesday 07 October 2025 11:16 I use this to trigger the update of the widget, with the current solution I sometimes get for some reason false updates.

Code: Select all

                    if string.sub(alertText, 1, 16) ~= string.sub(lastalertText, 1, 16) then
I just compare the entire string.

Code: Select all

if alertText ~= lastalertText then
I have to be honest, I didn't pay much attention to whether the update date/time changed for a consistent event, but I did test at the time that new events appear immediately. So, it works for me.
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
lost
Posts: 699
Joined: Thursday 10 November 2016 9:30
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: Earthquake info from KNMI

Post by lost »

Hello,

Discovering this for Netherlands, I searched if such info was available for france (there is also some URLs for overseas territories) and looking at:
https://renass.unistra.fr/fr/zones/france/

This page gets a json with all recent events from there where all data are logged:
https://renass.unistra.fr/json/zones/france/page-1.json

=>

Code: Select all

[
  {
    "localtime": "2025-10-08T14:47:42.485724Z",
    "description": {
      "fr": "Tir de carrière de magnitude 1.3, proche de Clermont-Ferrand",
      "en": "Quarry blast of magnitude 1.3, near of Clermont-Ferrand"
    },
    "group": 2,
    "countryiso2": "FR",
    "magnitude": 1.3,
    "longitude": 3.205881119,
    "latitude": 45.5742569,
    "automatic": false,
    "eventID": "fr2025sdglhn"
  },
  
  (...)
    {
    "localtime": "2025-10-08T12:22:38.249336Z",
    "description": {
      "fr": "Explosion de magnitude 1.6, proche de Mont-de-Marsan",
      "en": "Explosion of magnitude 1.6, near of Mont-de-Marsan"
    },
    "group": 2,
    "countryiso2": "FR",
    "magnitude": 1.6,
    "longitude": -0.3641246259,
    "latitude": 44.23016739,
    "automatic": false,
    "eventID": "fr2025sdfykw"
  },
  
 (...)
 
   {
    "localtime": "2025-10-08T04:13:23.782784Z",
    "description": {
      "fr": "Tremblement de terre de magnitude 0.5, proche de Grasse",
      "en": "Earthquake of magnitude 0.5, near of Grasse"
    },
    "group": 1,
    "countryiso2": "FR",
    "magnitude": 0.5,
    "longitude": 6.731607914,
    "latitude": 44.07238388,
    "automatic": false,
    "eventID": "fr2025sdegzt"
  },
  {
    "localtime": "2025-10-08T03:57:05.022600Z",
    "description": {
      "fr": "Induit de magnitude 1.3, proche de Pau",
      "en": "Induced of magnitude 1.3, near of Pau"
    },
    "group": 1,
    "countryiso2": "FR",
    "magnitude": 1.3,
    "longitude": -0.6213172281,
    "latitude": 43.41160026,
    "automatic": false,
    "eventID": "fr2025sdefnl"
  },
  {
    "localtime": "2025-10-08T02:07:36.406221Z",
    "description": {
      "fr": "Tremblement de terre de magnitude 0.9, proche de Clermont-Ferrand",
      "en": "Earthquake of magnitude 0.9, near of Clermont-Ferrand"
    },
    "group": 1,
    "countryiso2": "FR",
    "magnitude": 0.9,
    "longitude": 2.828833103,
    "latitude": 45.96072006,
    "automatic": false,
    "eventID": "fr2025sddvvl"
  },
  
  (...)
  
   {
    "localtime": "2025-10-07T12:40:15.749111Z",
    "description": {
      "fr": "Tir de carrière de magnitude 0.8, proche de Nice",
      "en": "Quarry blast of magnitude 0.8, near of Nice"
    },
    "group": 2,
    "countryiso2": "FR",
    "magnitude": 0.8,
    "longitude": 7.457409859,
    "latitude": 44.27844238,
    "automatic": false,
    "eventID": "fr2025sdbcdx"
  }
]
=> Mostly quarry blasts but also explosions (1 in this log from a military test location)... and earthquakes!

I think I'll do something like you, for fun and non-profit!
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

Yes, you can get the information there quite easily.
As described in the first post of this topic, I first tried with another source and later came up with the KNMI that seems to work better for the Netherlands.
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
Kedi
Posts: 595
Joined: Monday 20 March 2023 14:41
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Somewhere in NL
Contact:

Re: Earthquake info from KNMI

Post by Kedi »

janpep wrote: Wednesday 08 October 2025 13:07
Kedi wrote: Tuesday 07 October 2025 11:16 I use this to trigger the update of the widget, with the current solution I sometimes get for some reason false updates.

Code: Select all

                    if string.sub(alertText, 1, 16) ~= string.sub(lastalertText, 1, 16) then
I just compare the entire string.

Code: Select all

if alertText ~= lastalertText then
I have to be honest, I didn't pay much attention to whether the update date/time changed for a consistent event, but I did test at the time that new events appear immediately. So, it works for me.
It is nessessary when you want to send your self a notification (by Telegram) or otherwise sometimes you will get 'spammed' by messages.
Logic will get you from A to B. Imagination will take you everywhere.
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

Kedi wrote: Wednesday 08 October 2025 19:03 It is nessessary when you want to send your self a notification (by Telegram) or otherwise sometimes you will get 'spammed' by messages.
I send myself an E-mail. No problems.
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
HvdW
Posts: 663
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: Earthquake info from KNMI

Post by HvdW »

Strange
This morning 01:16 earthquake Zeerijp and 6:39 Zeerijp
In the log I don't find the first, just the second.
The script runs once a day 'at sunrise'
Bugs bug me.
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

HvdW wrote: Friday 14 November 2025 9:04 The script runs once a day 'at sunrise'
Makes sense if you collect it once a day and request the last one. You ask once, you get once :-)
I have more of the same place.
Note that there are a few differences in magnitude. Changes in what happened at the same time are reflected as differences.
I will have to look at the first one more closely. These seem to be equal. I will check it later.
(BTW, I received mail confirmation or your post just today!)
Aardbeving-JanPep-5.png
Aardbeving-JanPep-5.png (44.41 KiB) Viewed 128 times
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
willemd
Posts: 736
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: Earthquake info from KNMI

Post by willemd »

janpep wrote: Friday 14 November 2025 9:33 I will have to look at the first one more closely. These seem to be equal. I will check it later.
The second one also looks (almost) double. Although the magnitude is slightly different, they are also exactly 30 minutes apart, like the first one. Maybe you have two different data sources that report 30 minutes apart?
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

My script runs every 5 minutes at 2,7,12,17 etc. of the hour.
It only updates the device when there is a difference in the result string. So although small, 2.0 and 2.1 is different.
I did not look at the first two that look to be the same at first glance. But of course an automatic compare in the script never makes a mistake.
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

And just as I thought. Even a small difference is still a difference.
Aardbeving-JanPep-6.png
Aardbeving-JanPep-6.png (22.53 KiB) Viewed 120 times
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
willemd
Posts: 736
Joined: Saturday 21 September 2019 17:55
Target OS: Raspberry Pi / ODroid
Domoticz version: 2024.1
Location: The Netherlands
Contact:

Re: Earthquake info from KNMI

Post by willemd »

and also the type is different
janpep
Posts: 288
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: Earthquake info from KNMI

Post by janpep »

willemd wrote: Saturday 15 November 2025 10:00 and also the type is different
That is true, but the type is not part of the string that I show in the alert device, and no part of the string to compare if something has changed.
It's a bit much for me to stipulate that it has to be at least ?? meters from the previous measurement. The same goes for Magnitude and Depth. So I simply check if the string has changed since the previous measurement.
I wanted to prevent getting a notification every 5 minutes when nothing changed. Setting it to one time per day, you may miss a few and get only the last one. Depending on how you look at it, there is something to be said for all the choices.
Dz on Ubuntu VM on DS718+ behind FRITZ!Box.
EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; Sonoff USB-Dongle Plus-E; Zigbee2Mqtt; MQTT; Greenwave powernodes 1+6; Fibaro switch, plugs, smoke; FRITZ!DECT 200. Scripts listed in profile interests.
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest