Afvalkalender by script

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: 232
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Afvalkalender by script

Post by janpep »

Until recently I used the Afvalwijzer plug-in.
I want to emphasize that worked great (!) and I do not want to say anything bad about it. It's wonderful that you no longer have to copy it from the municipal calendar into your agenda for the entire year.
But it was not exactly what I wanted. I made quite a few adjustments to the Python script even though I never learned Python. This has the risk that I will have to do it again after an update. I was also left with two devices (Alert and Text), which I preferred to see in one.
When I started to reorder my scripts, I decided to write a script myself that uses only one text device.
It's great that the plug-in is made to get the information from all kinds of sources, but for personal use, I only need one and therefore I did not implement that in the script. Nevertheless I like to share it. May be someone can use it.

Here a picture of the result at different times:
Afvalkalender-1-JanPep.png
Afvalkalender-1-JanPep.png (38.01 KiB) Viewed 1551 times
You can use this script if the 'Afvalkalender' is used in your place. I find it difficult to figure out where. So that's your homework: You have to find out if 'Afvalkalender' is used for your zip code.

Then to get the right URL:
  • Step 1: To get the bagId you need (only one time action) for postalcode-housenumber. I run:

    Code: Select all

    https://afvalkalender.alphenaandenrijn.nl/rest/adressen/<postalcode>-<housenumber>
  • Step 2: With the bagId you get the needed JSON information. I run:

    Code: Select all

    https://afvalkalender.<city>.nl/rest/adressen/<bagId>/afvalstromen

When you get the json result, you can continue.

The set-up:
  • It makes use of a text device, in which the (optional) colored icon of the relevant bin for the next batch is shown.
  • When you use icons, you have to give put the right icon numbers in the script.
  • Add your bagid, email, etc. under 'Your settings'.
  • The contents of the waste bin (e.g. "PMD (plastic, metalen verpakkingen, drinkpakken)") is translated to the color "Bruine bak". In your case there might be other descriptions to 'translate'.
  • The next 3 batches of the waste bins are shown in chronological order.
  • An offset of 1 day has been added in the script. In my case, the bin is emptied early in the morning and I put it outside the night before. Dates and notifications are therefore based on that day before.
Suppose the next turn is the 'Groene bak':
  • This will appear with blue text up to 4 days in advance: dd-mm-yyyy Groene bak
  • The third day before with orange text: 'Overmorgen Groene bak
  • The second day before with orange background: Morgen Groene bak
  • One day in advance with red background and white text: Vanavond Groene bak
    On this day, that the bin must be put out on the street, an email notification will be sent (with delay) at a set time.
  • On the collection day itself with green text: Vandaag is de Groene bak geleegd
The script retrieves the fresh data once a day.

t-Afvalkalender

Code: Select all

--t-Afvalkalender
-- 18-05-2024 by Jan Peppink; hppts://ict.peppink.nl
--  Based on the idea of the Afvalwijzer plug-in.
--  Result: all information I want presented as I like in one device.
--  Homework: You have to find out if 'afvalkalender' is used for your postalcode.
-- Step 1: To get the bagId you need (only one time action) for postalcode-housenumber I run:
--  https://afvalkalender.alphenaandenrijn.nl/rest/adressen/<postalcode>-<housenumber>
--  In the result we have: bagId to set in variable below.
-- Step 2: With the bagId you get the needed JSON information. I run:
--  https://afvalkalender.<city>.nl/rest/adressen/<bagId>/afvalstromen	
-- From the result we need only two fields:
--  1. "title": "Gfte", OR title": "Papier en karton", OR "title": "PMD (plastic, metalen verpakkingen, drinkpakken)" AND
--  2. "ophaaldatum": "2024-05-27" 
-- Translate the found titles into '<color> bin'
-- First bin gets date, or when it comes closer 'the day after tomorrow', or 'tomorrow', or 'this evening', or 'was today'.
-- Optional use of icons that change with the color of the first to come.
--  Activate by setting ak_icons_installed = 1
--  NB. DOUBLE check function getIconNumber and correct your iconNumbers !!
-- Send email notification (using calculated delay) on the evening that thebin has to be put on the street.
-- Mail wil only be send if ak_mailTime is set as 'hh:mm' and not '' .

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local ak_bagId = 'yourbagID'
local ak_URL = 'https://afvalkalender.alphenaandenrijn.nl/rest/adressen/' .. ak_bagId .. '/afvalstromen'
local ak_wastebin_idx = 99999         --idx of the Text device.
local ak_emailTo = "[email protected]"  -- Set E-mail adres to sent notification to.
local ak_mailTime = '19:30'          -- '' = no mail, or set time as 'hh:mm'
local ak_icons_installed = 0    -- 1 or 0 when custom icons have been installed or not.

return {
	on = {
		timer = {
            --'every 2 minutes',  -- Only for testing.
			'at 2:05',  -- Refresh info for the day, while I am sleeping.
		},
        httpResponses = {
		    'afvalkalender'       -- 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 = "Afvalkalender-"
    },
	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.

        -- Use some color variables
        local cRed = '#ff0000;'	
        local cOrange = '#ffa500;'        
        local cBlue = '#3b3bc4;'
        local cWhite = '#FFFFFF;'

        --Adjust lineheight
        local lineHeight = 1.1
        
        -- Local Functions go here =============
        local function getIconNumber( binText )
            if binText == 'Blauwe bak' then iconNumber = 135 end
            if binText == 'Bruine bak' then iconNumber = 136 end
            if binText == 'Groene bak' then iconNumber = 137 end
            return iconNumber
        end

        -- Now start to do something ============
        -- Get the data.
		if (triggeredItem.isTimer) then
            -- Retrieve the data.
			dz.openURL({
				url = ak_URL,
				method = 'GET',
				callback = 'afvalkalender'
			})
		end	

	    if (triggeredItem.isHTTPResponse) then
            -- Process the obtained data.
	        -- Check the response and process the data.
    		if (triggeredItem.ok and triggeredItem.isJSON) then
                dz.log( 'Item and JSON - OK', dz.LOG_DEBUG )
				-- 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 )
                    -- The data we want is:
                    --   "title": "Gfte", OR title": "Papier en karton", OR "title": "PMD (plastic, metalen verpakkingen, drinkpakken)" AND
                    --   "ophaaldatum": "2024-05-27" 
                    
                    --Start a table for the found items.
                    found_items_table = {}
                    -- Loop through the result table and add found item to found_items_table.
                    local tc = #result_table
                    for i = 1, tc do
                        -- Save needed records in found_items_table
                        if result_table[i].title == "Gfte" then
                            bin = 'Groene bak'
                            day = result_table[i].ophaaldatum
                            table.insert(found_items_table, day .. ',' .. bin)
                        elseif result_table[i].title == "Papier en karton" then
                            bin = 'Blauwe bak'
                            day = result_table[i].ophaaldatum
                            table.insert(found_items_table, day .. ',' .. bin)
                        elseif result_table[i].title == "PMD (plastic, metalen verpakkingen, drinkpakken)" then
                            bin = 'Bruine bak'
                            day = result_table[i].ophaaldatum
                            table.insert(found_items_table, day .. ',' .. bin)
                        end
                    end

                    -- Order this table by date ascending.
                    table.sort( found_items_table )

                    --Process the sorted items to add them to the deviceText.
                    local deviceText = ''
                    local tc = #found_items_table
                    for i = 1, tc do
                        dz.log( 'Gevonden = ' .. found_items_table[i], dz.LOG_DEBUG )
                        --Example: Gevonden = 2024-05-18,Bruine bak
                        
                        --One by one split the lines to date [1] and wastebin [2]
                        local currentBin = _u.stringSplit( found_items_table[i], ',' )
                        -- we need to calculate to seconds for the offset to get date and warning a day earlier.
                        local ak_seconndsOffset = 86400
                        local binDate = dz.time.dateToDate( currentBin[1], 'yyyy-mm-dd', 'dd-mm-yyyy', -ak_seconndsOffset )
                        local unixBaktime = dz.time.dateToTimestamp( binDate, 'dd-mm-yyyy' ) 
                        local unixTodaytime = dz.time.dateToTimestamp( dz.time.rawDate, 'yyyy-mm-dd' )
                        -- We need the binDaySeconds to calculate the date diff
                        local binDaySeconds = unixBaktime - unixTodaytime
                        dz.log( 'Gevonden dagen in seconden = ' .. binDaySeconds, dz.LOG_DEBUG )                        

                        local binText = currentBin[2]

                        if i == 1 then
                            --For the first record:
                            if ak_icons_installed == 1 then
                                -- Get icon for first record found.
                                iconNumber = getIconNumber( binText )
                                dz.devices(ak_wastebin_idx).setIcon( iconNumber )
                            end

                            --Define deviceText based on which day.
                            if binDaySeconds < 0 then
                                deviceText = '<span style="line-height:' .. lineHeight .. '; color: Green">Vandaag is de ' .. binText .. ' geleegd.</span>'
                            elseif binDaySeconds == 0 then
                                deviceText = '<span style="line-height:' .. lineHeight .. '; background-color: ' .. cRed .. ' ; color: ' .. cWhite .. '">Vanavond ' .. binText .. '</span>'
                                --Send mail if time is configured
                                if ak_mailTime ~= '' then
                                    --Calculate the delay to send mail at configured time.
                                    mailSendTime = dz.time.dateToDate( currentBin[1] .. ' ' .. ak_mailTime , 'yyyy-mm-dd hh:MM', 'yyyy-mm-dd hh:MM', 0 )
                                    mailunixSendTime = dz.time.dateToTimestamp( mailSendTime, 'yyyy-mm-dd hh:MM' )
                                    currentUnixTime = dz.time.dDate
                                    mailDelaySeonds = mailunixSendTime - currentUnixTime
                                    dz.log( 'mailDelay in seconds = ' .. mailDelaySeonds, dz.LOG_DEBUG )
                                    
                                    if mailDelaySeonds > 0 then
                                        -- Calculated mailDelaySeonds is time in future.
                                        dz.log( 'Mail wordt verzonden met delay van ' .. mailDelaySeonds .. ' seconden.', dz.LOG_DEBUG )
                                        dz.email('Vandaag ' .. binText, 'Vandaag ' .. binText, ak_emailTo, mailDelaySeonds )
                                    end
                                end                                
                            elseif binDaySeconds == 86400 then
                                deviceText = '<span style="line-height:' .. lineHeight .. '; background-color: ' .. cOrange ..  '">Morgen ' .. binText .. '</span>'
                            elseif binDaySeconds == 172800 then
                                deviceText = '<span style="line-height:' .. lineHeight .. '; color: ' .. cOrange ..  '">Overmorgen ' .. binText .. '</span>'
                            else
                                deviceText = '<span style="line-height:' .. lineHeight .. '; color: ' ..  cBlue .. '">' .. binDate .. ' ' .. binText .. '</span>'
                            end                            
                        else
                            deviceText = deviceText .. '\n' .. binDate .. ' ' .. binText
                        end

                    end
                    dz.devices(ak_wastebin_idx).updateText( deviceText )
                else
                    dz.log( 'No result_table found', dz.LOG_ERROR )
                end
		    else
			    dz.log( 'Item or JSON - NOT OK', dz.LOG_ERROR )
			end
	    end
	end
}
-- That's All --------------------------------------------------
And icons for green, brown and blue waste bins.
Icons_Afvalkalender-JanPep.zip
(21.95 KiB) Downloaded 56 times
Domoticz in Ubuntu virtual machine on Synology DS718+ behind FRITZ!Box.
Using: EvoHome; MELCloud; P1 meter; Z-Stick GEN5; Z-Wave-js-ui; 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 0 guests