New Dutch DzVents RIVM Stookalert

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

Moderator: leecollings

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

New Dutch DzVents RIVM Stookalert

Post by janpep »

The RIVM stookalert with url https://www.rivm.nl/media/lml/stookalert/stookalert_' .. currentDate .. '.json has stopped.
It had the warning at a provincial level.
The new version (with approach at local level) can be found at https://www.atlasleefomgeving.nl/stookwijzer
It is updated 4 times a day at 4, 10, 16 and 22 o'clock.
Besides the current alert, with information on Air quality level and windspeed, it also gives a 6, 12 and 18 hour forecast warninglevel.
As far as I can see now always the first two as final and the last two as not final.

Here I show the approach with my modified DzVents script:
- Starts with calculating a boundery box around the latitude and longitude coordinates found in Domoticz settings.
- Gets the last known json information.
- Detects level, LKI, Windspeed for the first time. and calculates the hh:mm for next tree times (6, 12 and 18 hr later).
- Times are given in the code color for the level that is found for that time.
- Updates the alert level and adds the information in text.
- Optional send email (once) when level increased to code red.

You need to create an custom alert device and insert the IDX number.
I configured it to run 10 minutes after the given times.
NewDutchRIVMStookalert.png
NewDutchRIVMStookalert.png (9.5 KiB) Viewed 2386 times
Here is the new t-StookAlert-RIVM script.

Code: Select all

-- 09-02-2025 Script by Jan Peppink, https://ict.peppink.nl
-- Modified from my earlier RIVM Stookalert script, because of changed URL with new approach
-- The stookalert is moved to https://www.atlasleefomgeving.nl/stookwijzer
-- It now gives a local advice for unfavorable weather conditions (wind) and poor air quality. 
-- With a Stookalert, the RIVM calls on people not to burn wood.
-- This can prevent inconvenience for people in the area.
-- Results in advice_0, with 0=yellow, 1=orange, 2=red. and a forecast 6, 12 and 18 hours ahead.
-- I translate code yellow to green. With yellow they avoid green as a Clearly allowed. :-)
-- Green = No alert, Orange = Warning, Red = RIVM Stookalert.
--		Setting alertLevel by constant:  domoticz.ALERTLEVEL_GREY, ALERTLEVEL_GREEN, ALERTLEVEL_YELLOW, ALERTLEVEL_ORANGE, ALERTLEVEL_RED
--		Getting alertLevel by number:    0=gray, 1=green, 2=yellow, 3=orange, 4=red

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local SA_alert_idx = 99999                -- Set to the idx of the custom Alert sensor you have to create for this script
local SA_emailTo = ''     -- Optional: Set to your E-mail adres to sent Alert notification once.

----------------------------------------------------------------------------------
return {
	on = {
		timer = {
			--'every 2 minutes',  --Only for testing
			'at 4:10',
			'at 10:10',
			'at 16:10',
			'at 22:10',
		},
		httpResponses = {
			'triggerSA'     -- must match with the callback passed to the openURL command
		},
	},
	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 = 'Stook-Alert',
	},
	execute = function(dz, triggeredItem)
        -- Set Local environment =================
        --local _u = dz.utils       -- Holds subset of handy utilities.
        --local _h = dz.helpers     -- Holds the global functions in global_data
        --local _d = dz.globalData  -- Holds the global data

        -- Get coordinates from settings and adjust a little to create BBox retangle around our location.
        local lat_max = dz.settings.location.latitude + 0.000001
        local long_max = dz.settings.location.longitude + 0.000001
        local lat_min = dz.settings.location.latitude - 0.000001
        local long_min = dz.settings.location.longitude - 0.000001

        -- set RIVM url, with the BBox coordinates.
        local rivmurl='https://data.rivm.nl/geo/alo/wms?service=WMS&SERVICE=WMS&VERSION=1.3.0&REQUEST=GetFeatureInfo&QUERY_LAYERS=stookwijzer_v2&LAYERS=stookwijzer_v2&info_format=application/json&feature_count=2&I=0&J=0&WIDTH=1&HEIGHT=1&CRS=CRS:84&BBOX=' .. long_min .. ',' .. lat_min .. ',' .. long_max .. ',' .. lat_max

		local alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
        local alertText = ''

        -- Use some color variables
        local htmlAdviceColor = '#000000;'  -- Default = Black
        local htmlForecastColor = '#000000;' -- Default = Black
        local cMagenta = '#ff00ff;'
        local cDarkGray = '#808080;'
        local cGreen = '#008000;'
        local cBlue = '#0000FF;'
        local cYellow = '#ffff00;'
        local cDarkYellow = '#ffdb00;'
        local cOrange = '#ffa500;'
        local cRed = '#ff0000;'	
        --Adjust lineheight
        local lineHeight = 1.1
        
        -- Local Functions go here =============
        local function addHours(timeStr, hours)
            -- Add number of hours to the timeStr given as hh:mm.
            local h, m = timeStr:match("(%d+):(%d+)")
            local newH = tonumber(h) + hours
            local newM = tonumber(m)

            newH = newH % 24  -- Ensure hours are within 0-23 range
            newM = newM + math.floor((newH - tonumber(h)) * 60)
            newM = newM % 60  -- Ensure minutes are within 0-59 range

            return string.format("%02d:%02d", newH, newM)
        end

        -----------------------------
        local function setColor(level)
            -- Return the color for a given level.
            local color = ''
            if level == 0 then
                color = cGreen
            elseif level == 1 then
                color = cOrange
            else
                color = cRed
            end
            return color
        end

		-- Now start to do something ============
		if (triggeredItem.isTimer) then
			dz.openURL({
				url = rivmurl,
				method = 'GET',
				callback = 'triggerSA', -- see httpResponses above.
			})
		end

		if (triggeredItem.isHTTPResponse) then
			if (triggeredItem.ok) then
				if (triggeredItem.isJSON) then
					-- We have some result. Store in table.
					local result_table = triggeredItem.json
                    if type(result_table) == "table" then
                        dz.log( 'result_table: type = ' .. type(result_table), dz.LOG_DEBUG )
                        local features_table = result_table['features']
                        if type(features_table) == "table" then
                            dz.log( 'features_table: type = ' .. type(features_table), dz.LOG_DEBUG )
                            local properties_table = features_table[1]['properties']
                            if type(properties_table) == "table" then
                                dz.log( 'properties_table: type = ' .. type(properties_table), dz.LOG_DEBUG )
                                -- Example output
                                --"properties": {
                                --  "pc4": "3411",
                                --  "model_runtime": "07-02-2025 16:00",
                                --  "lki": 2,
                                --  "wind": 7.8,
                                --  "wind_bft": 4,
                                --  "advies_0": 0,
                                --  "advies_6": 0,
                                --  "advies_12": 0,
                                --  "advies_18": 0,
                                --  "definitief_0": true,
                                --  "definitief_6": true,
                                --  "definitief_12": false,
                                --  "definitief_18": false,
                                --  "windrichting": -1
                                --}
                                local lki = properties_table.lki
                                local wind = properties_table.wind
                                -- Advies level
                                local advies_0hr = properties_table.advies_0
                                local advies_6hr = properties_table.advies_6
                                local advies_12hr = properties_table.advies_12
                                local advies_18hr = properties_table.advies_18
                                -- Calculate the time for the forecast hours
                                local firsttime = properties_table.model_runtime:sub(-5)
                                local add6hr = addHours( firsttime, 6 )
                                local add12hr = addHours( firsttime, 12 )
                                local add18hr = addHours( firsttime, 18 )
                                -- Set colors for forecast hours based on level
                                local color0hr = setColor( advies_0hr )
                                local color6hr = setColor( advies_6hr )
                                local color12hr = setColor( advies_12hr )
                                local color18hr = setColor( advies_18hr )
                                -- Log most important content -- What do we have now?
                                dz.log( 'Advies_0 = ' .. advies_0hr .. ', ' .. firsttime .. 'uur, code '.. color0hr .. '; LKI: ' .. lki .. '; Wind: ' .. wind .. ' m/s', dz.LOG_DEBUG )
                                dz.log( 'Advies_6 = ' .. advies_6hr .. ', ' .. add6hr  .. 'uur, code ' .. color6hr, dz.LOG_DEBUG )
                                dz.log( 'Advies_12 = ' .. advies_12hr .. ', '  .. add12hr .. 'uur, code ' .. color12hr, dz.LOG_DEBUG )
                                dz.log( 'Advies_18 = ' .. advies_18hr .. ', '  .. add18hr .. 'uur, code ' .. color18hr, dz.LOG_DEBUG )
                                
                                -- Create the alert text with calculated color
                                local text0hr = '<span style="line-height:' .. lineHeight .. '; color: ' .. color0hr .. '">' .. firsttime ..' uur</span>'
                                local text6h = '<span style="color: ' .. color6hr .. '">' .. add6hr ..' uur</span>'
                                local text12h = '<span style="color: ' .. color12hr .. '">' .. add12hr ..' uur</span>'
                                local text18h = '<span style="color: ' .. color18hr .. '">' .. add18hr ..' uur</span>'
                                
                                -- Now evaluate the results	for firsttime level ============
                                if advies_0hr == 0 then
                                    -- Set alertLevel Green.
                                    alertText = text0hr .. ' Geen stookalert (LKI: ' .. lki .. ' Wind: ' .. wind .. ' m/s)<br>' .. text6h .. ' - ' .. text12h .. ' - ' .. text18h
                                    alertLevel = dz.ALERTLEVEL_GREEN
                                    dz.devices(SA_alert_idx).updateAlertSensor( alertLevel, alertText )
                                elseif advies_0hr == 1 then
                                    alertText = text0hr .. ' Stookalert (LKI: ' .. lki .. ' Wind: ' .. wind .. ' m/s)<br>' .. text6h .. ' - ' .. text12h .. ' - ' .. text18h
                                    -- Set alertLevel Orange.
                                    alertLevel = dz.ALERTLEVEL_ORANGE
                                    dz.devices(SA_alert_idx).updateAlertSensor( alertLevel, alertText )
                                elseif advies_0hr == 2 then
                                    -- RIVM alert!
                                    alertText = text0hr .. ' Stookalert! (LKI: ' .. lki .. ' Wind: ' .. wind .. ' m/s)<br>' .. text6h .. ' - ' .. text12h .. ' - ' .. text18h
                                    -- Set alertLevel Red.
                                    alertLevel = dz.ALERTLEVEL_RED
                                    -- Only send notification when RIVM alert increases the last stored alertLevel to red (=4).
                                    if dz.devices(SA_alert_idx).color < 4 and SA_emailTo ~= '' then
                                        -- alertLevel increased, so send notification.
                                        dz.email( 'Stookalert!', 'Stookalert - LKI:' ..  lki .. ' Wind: ' .. wind , SA_emailTo, 0)
                                    end
                                    -- Update with new alertLevel and alertText.
                                    dz.devices(SA_alert_idx).updateAlertSensor( alertLevel, alertText )
                                end
                            else
                                dz.log( 'No properties_table found', dz.LOG_ERROR )
                            end --properties_table
                        else
                            dz.log( 'No features_table found', dz.LOG_ERROR )
                        end --features_table
                    else
                        dz.log( 'No result_table found', dz.LOG_ERROR )
                    end --result_table
                else
                    dz.log( 'JSON - NOT OK', dz.LOG_ERROR )
                end -- isJSON
            else
                dz.log( 'Item NOT OK', dz.LOG_ERROR )
            end --triggeredItem-OK
        end -- isHTTPResponse
end -- execute
}
-- That's All --------------------------------------------------

You can also take a look at my Dutch local 'Stookwijzer'. That gives more information, is more configurable for the forecast and can update per hour.
Last edited by janpep on Sunday 09 February 2025 21:18, edited 1 time in total.
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.
User avatar
waltervl
Posts: 5853
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by waltervl »

Thanks! I can remove my script on GitHub...
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
HvdW
Posts: 612
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by HvdW »

What a nice script and so easy to set up. Thanks @janpep.
One remark: You can use -- 'every 1 minutes', --Only for testing, doesn't need to be 2 minutes.
Using the 'every 1 minutes' text makes it easy to change the timing.
No need to change from 'every minute' to 'every 12 minutes'
Bugs bug me.
User avatar
waltervl
Posts: 5853
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by waltervl »

I installed it and waited until 22.10 to see what happened ... :) No need to have a 1 or 2 minutes trigger
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
janpep
Posts: 270
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by janpep »

HvdW wrote: Sunday 09 February 2025 22:53 One remark: You can use -- 'every 1 minutes', --Only for testing, doesn't need to be 2 minutes.
Using the 'every 1 minutes' text makes it easy to change the timing.
I don't quite understand the comment. Is 1 minute easier to change than 2?
Even though I am very fast, usually I am not ready for test with changes within 1 minute. So I set it to 2 minutes.
BTW This can easily be changed to 20. :-)
I hope I can continue to use the interval I have chosen?
You can set it up for yourself as you want.
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: 270
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by janpep »

waltervl wrote: Sunday 09 February 2025 23:10 No need to have a 1 or 2 minutes trigger
Yes, of course this is only used while debugging my typo's and layout of the text.
It makes no sense at all to get the same result over and over again for 6 hours every 2 minutes. :-)
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: 612
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by HvdW »

janpep wrote: Sunday 09 February 2025 23:12 BTW This can easily be changed to 20. :-)
You seem to have missed the point or my way of explaining is a bit dumb.
To change 'every minute' to 'every 20 minutes' you need to change the text on 2 spots.
To change 'every 1 minutes' to 'every 20 minutes' you need to change the text on 1 spot.
Just lazy programming.
Bugs bug me.
janpep
Posts: 270
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by janpep »

HvdW wrote: Monday 10 February 2025 0:37 You seem to have missed the point or my way of explaining is a bit dumb.
Ahhh, now I understand that you made a point of what is NOT in my script with the minute(without s). :-)
1) It is already in minutes ! That already corresponds with your wish to change it in just one place.
2) I never set it to one. As said, because I am not so fast with my changes.
3) Actually I only uncomment the line and change it very rarely.
This seems more than enough points on this point.
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.
User avatar
waltervl
Posts: 5853
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by waltervl »

Works perfectly. I only notice it alerts far more then the old RIVM stookwijzer. It used to be on foggy weather with low wind speeds. But now it is mostly only on low wind speed.
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
janpep
Posts: 270
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by janpep »

Yes. Because in the previous version it was about the whole province. Now it looks at your coordinates. I think this gives more changes and more depending in what (air quality) area you live. Wind is the major thing to look at. Mostly fog keeps hanging around when windspeed is low. So it often comes togeter than. Last few weeks windspeed was often very low.
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: 270
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by janpep »

I got the idea that they also increased the threshold for wind speed.
With wind speed 2.7 m/s and LKI of 1, I do not expect red.
Also note that you are now looking at the wind speed at 4:00 PM this afternoon!

What I also noticed is that the LKI level is often a lot lower than I calculate it.
Perhaps it can be explained by the fact that I use other sources. May be they use a different calculation, but I based my calculation on official publication. It does become a bit strange when you see them side by side.
Previously, the old RIVM version often concluded earlier that the fireplace can be stoked. Now that is the case with my own stoking guide.
NewDutchRIVMStookalert-JanPep-02.png
NewDutchRIVMStookalert-JanPep-02.png (21.29 KiB) Viewed 437 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.
User avatar
waltervl
Posts: 5853
Joined: Monday 28 January 2019 18:48
Target OS: Linux
Domoticz version: 2024.7
Location: NL
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by waltervl »

Here they have a table: https://iplo.nl/thema/lucht/houtstook-stookwijzer/
So red is windforce =< 2 bft (1.5-3.3 m/s) or LKI >=7

So especially windspeed < 3.4 m/s gives code red.
Domoticz running on Udoo X86 (on Ubuntu)
Devices/plugins: ZigbeeforDomoticz (with Xiaomi, Ikea, Tuya devices), Nefit Easy, Midea Airco, Omnik Solar, Goodwe Solar
janpep
Posts: 270
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2025.1
Location: Netherlands
Contact:

Re: New Dutch DzVents RIVM Stookalert

Post by janpep »

waltervl wrote: Tuesday 25 February 2025 20:57 So red is windforce < 2 bft (1.5-3.3 m/s) or LKI >=7
Apparently it changed in October last year.
Even <3 bft is red now, which means that they have increased from > 2 m/s (which I still use) to >= 3.4.
I think this is part of policy. They will increase every few months until you can only BBQ and light your fireplace when there is a huge storm.
Nobody cares about Tata Steel and other companies like that. No, they care about your little fireplace.
If a little bit of smoke can travel 2 meters away after 1 second (and at roof height = about 9 meters!!!), then I think the nuisance for my neighbors will be quite limited.
For now I just want to keep it going at > 2 m/s
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