dzVents get garbage collection dates (various)  [SOLVED]

Moderator: leecollings

imdos
Posts: 34
Joined: Thursday 03 August 2017 21:50
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Contact:

Re: dzVents get garbage collection dates (various)

Post by imdos »

Never mind. It worked without an additional notification.

Sent from my MI 6 using Tapatalk

Making use of: Raspbian(SSD), dz Beta, Woonveilig, Z-Wave(alarm+multi-sensor), RFLink(blinds), P1, Yeelight, Xiaomi temp sensors, Tasmota(SonoFF, Blitzwolf SHP2, Shelly1)
imdos
Posts: 34
Joined: Thursday 03 August 2017 21:50
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Contact:

Re: dzVents get garbage collection dates (various)

Post by imdos »

imdos wrote: Tuesday 05 February 2019 10:00 Never mind. It worked without an additional notification.

Sent from my MI 6 using Tapatalk
I would like to extend the notification to once around 18:30 on the day before the actual pick-up of the garbage. However I don't see where (actually to which) to compare a variable like garbareTomorrow and do a simple check.

Or would it make more sense to compare it in a seperate script and against the alertdevice for example?
Making use of: Raspbian(SSD), dz Beta, Woonveilig, Z-Wave(alarm+multi-sensor), RFLink(blinds), P1, Yeelight, Xiaomi temp sensors, Tasmota(SonoFF, Blitzwolf SHP2, Shelly1)
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by waaren »

imdos wrote: Thursday 14 February 2019 18:11 I would like to extend the notification to once around 18:30 on the day before the actual pick-up of the garbage. However I don't see where (actually to which) to compare a variable like garbareTomorrow and do a simple check.
If you can send me the script via PM as you use it now I will have a look.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
stephanvdplas
Posts: 73
Joined: Wednesday 13 February 2019 18:09
Target OS: Windows
Domoticz version: 2023.1
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by stephanvdplas »

Some more fun: Let the Hue light flash in the colour of the garbage bin that is collected that day, when coming home from morning walk.
I use a different script (if you are interested, I'll post it) for setting the user variables for the number of days until next collection and the type of bin.

Code: Select all

return {
	on = {
		devices = {
			'Ste_Thuis'
		}
	},
  	logging = {
       level = domoticz.LOG_INFO,
       marker = "SvdP-proximity"
    },
	execute = function(domoticz, triggeredItem)

	    local Time = require('Time')
        local Now = Time().hour + (Time().minutes)/100
        domoticz.log('Het is ongeveer ' .. Now .. ' uur',LOG_INFO) 
	    local lmsURL = 'http://' .. domoticz.variables('LMS_IP').value .. ':' .. domoticz.variables('LMS_TCPPort').value .. '/status.html?' 

        if (Now < 6) then timeOfDay = 'nacht'
        elseif (Now < 12) then timeOfDay = 'ochtend'
        elseif (Now < 18) then timeOfDay = 'middag'
        else timeOfDay = 'avond'
        end
        domoticz.log('Het is nu ' .. timeOfDay,LOG_INFO)
        if (triggeredItem.active) then
            if (timeOfDay == 'ochtend') then
 		-- HERE SOME OTHER CODE OF STUFF THAT IS TRIGGERED DAILY --
                if (domoticz.variables('Dagen_tot_ROVA_inzameling').value == 0) then                                                        -- Als de Container vandaag opgehaald wordt dan 
                    domoticz.log('Vandaag wordt de '  .. domoticz.variables('Eerstvolgende_Container').value .. ' opgehaald',LOG_INFO)      -- de lampen in de juiste kleur knipperen
                    if (domoticz.variables('Eerstvolgende_Container').value == 'GFT') then
	                    domoticz.devices('Hue Group Woonkamer').setRGB(11, 244, 11)
                    elseif (domoticz.variables('Eerstvolgende_Container').value == 'PAPIER') then
	                    domoticz.devices('Hue Group Woonkamer').setRGB(11, 11, 255)
                    elseif (domoticz.variables('Eerstvolgende_Container').value == 'PLASTICPLUS') then
	                    domoticz.devices('Hue Group Woonkamer').setRGB(140, 140, 170)
                    end 
                    domoticz.devices('Hue Group Woonkamer').switchOff().afterSec(1)
	                domoticz.devices('Hue Group Woonkamer').switchOn().forSec(2).repeatAfterSec(2, 30)
                end
            end
        end
    end
}
- Running LMS, Domoticz and Dashticz on a windows 11 laptop.
- LMS (11 players) / Hue (26 lights, 2 switches) / Z-wave (14 devices) / Toon (unrooted) / Chromecast
dheuts
Posts: 65
Joined: Monday 25 March 2019 15:14
Target OS: Raspberry Pi / ODroid
Domoticz version:
Location: Brunssum, Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by dheuts »

stephanvdplas wrote: Tuesday 05 March 2019 21:57 Some more fun: Let the Hue light flash in the colour of the garbage bin that is collected that day, when coming home from morning walk.
I use a different script (if you are interested, I'll post it) for setting the user variables for the number of days until next collection and the type of bin.

Code: Select all

return {
	on = {
		devices = {
			'Ste_Thuis'
		}
	},
  	logging = {
       level = domoticz.LOG_INFO,
       marker = "SvdP-proximity"
    },
	execute = function(domoticz, triggeredItem)

	    local Time = require('Time')
        local Now = Time().hour + (Time().minutes)/100
        domoticz.log('Het is ongeveer ' .. Now .. ' uur',LOG_INFO) 
	    local lmsURL = 'http://' .. domoticz.variables('LMS_IP').value .. ':' .. domoticz.variables('LMS_TCPPort').value .. '/status.html?' 

        if (Now < 6) then timeOfDay = 'nacht'
        elseif (Now < 12) then timeOfDay = 'ochtend'
        elseif (Now < 18) then timeOfDay = 'middag'
        else timeOfDay = 'avond'
        end
        domoticz.log('Het is nu ' .. timeOfDay,LOG_INFO)
        if (triggeredItem.active) then
            if (timeOfDay == 'ochtend') then
 		-- HERE SOME OTHER CODE OF STUFF THAT IS TRIGGERED DAILY --
                if (domoticz.variables('Dagen_tot_ROVA_inzameling').value == 0) then                                                        -- Als de Container vandaag opgehaald wordt dan 
                    domoticz.log('Vandaag wordt de '  .. domoticz.variables('Eerstvolgende_Container').value .. ' opgehaald',LOG_INFO)      -- de lampen in de juiste kleur knipperen
                    if (domoticz.variables('Eerstvolgende_Container').value == 'GFT') then
	                    domoticz.devices('Hue Group Woonkamer').setRGB(11, 244, 11)
                    elseif (domoticz.variables('Eerstvolgende_Container').value == 'PAPIER') then
	                    domoticz.devices('Hue Group Woonkamer').setRGB(11, 11, 255)
                    elseif (domoticz.variables('Eerstvolgende_Container').value == 'PLASTICPLUS') then
	                    domoticz.devices('Hue Group Woonkamer').setRGB(140, 140, 170)
                    end 
                    domoticz.devices('Hue Group Woonkamer').switchOff().afterSec(1)
	                domoticz.devices('Hue Group Woonkamer').switchOn().forSec(2).repeatAfterSec(2, 30)
                end
            end
        end
    end
}
Great idea! I'm using another script for RD4 and I was wondering if this is also possible with the RD4 script?
https://github.com/jvanderzande/mijnafv ... imburg-rd4

Does anyone know this or can anybody help me?
Thanks!
Raspberry Pi 4 With Domoticz - RFXCom - Tuya Wifi LED lights - Chuango Alarm - Zwave+ - Zigbee2MQTT - Anna Thermostat - Broadlink IR, P1 - Eufy Robo Vacuum - Worx Robo Mower
annegerben
Posts: 26
Joined: Wednesday 03 August 2016 12:34
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: dzVents get garbage collection dates (various)

Post by annegerben »

waaren wrote: Thursday 08 November 2018 12:32
delcara wrote: Wednesday 07 November 2018 11:24 I'm trying to create a script to get garbage collection dates from ROVA. I've discovered how to get the dates through a curl command. But I've no idea how to translate this to a dzVents script. I've just started with DzVents and have now translated all my blockly to DzVents (relatively simple scripts to control lights etc.). Can you help to translate this curl command to a DzVents script?
Please have a look at the script below.
I tried to translate the curl command into a domoticz.openUrl but I failed in finding the working syntax (the cookie table seems to mess up the openUrl internally). If someone else has found a solution for this I would be much obliged if that solution could be shared here.
So had to use the curl command itself. To ensure that a wait time for the JSON return would not stall the event thread, the command is processed in the background and the script will come back every couple of seconds to check if it is already there.
(In practice I have not seen that the return have taken more then 2 seconds, but just to be sure)

Code: Select all

--[[ getGarbage.lua for [ dzVents >= 2.4 ]

    this script is only useful in those  areas of the Netherlands where the household garbage collector is rova
    Tested on debian stretch but probably also working on other Linux variants.

    needs curl command 
    needs to be able to process commands in the background ( by using leading &)

    Enter your zipcode, housenumber and garbageID in the appropriate places between the lines starting with -- ***
    Next is to set your virtual text and or virtual alert device.

    the text device will contain the most nearby collectdates for the types of household garbage
    the alert device will contain the date and type for the garbagecollection that will arrive first
    notification system will be called when collect will be today

]]-- 
 return {
         on =   {   timer           =   { "at 00:05","at 08:00" },    -- daily run twice
                    devices         =   { "getGarbage"          },    -- Ignore just for test  
                    httpResponses   =   { "delay_Response"      },    -- (re)triggers the script
                },
                
    logging =   {   level   = domoticz.LOG_DEBUG ,              -- Change to ERROR when script is behaving as expected  
                    marker  = ""},                              -- Will be set in execute = function block 
            
    data    =   {   delay           =  { initial = 0 },
                },

    execute = function(dz, item, info)

    -- ************************* Mandatory: Set your values and device names below this Line 
        
        local myZipcode     = "0000AA"            -- Your zipcode like "3085RA"
        local myHousenumber = "99"                -- Your housenumber like 38
        local myGarbageID   = "9999999"            -- Your GarbageID
        local myTextDevice  = "GarbageText"       -- Name with quotes or idx without when created as virtual text device
        local myAlertDevice = "GarbageAlert"      -- Name with quotes or idx without when created as virtual alert device
        
    -- **************************************************************** No changes required below this  
       local initialDelay           = 2 
       local repeatDelay            = 10
       local maxDelay               = 60
       local outFile                = "/tmp/garbageCollectionDates.json"
       local catCommand             = "cat"
       local garbageToday           = false
       
        _G.logMarker                = info.scriptName     -- sets the logmarker for dz.log
       
        local function logWrite(str,level)
            dz.log(str,level or dz.LOG_DEBUG)
        end
        
        local function alertLevel(delta)
            if delta < 2 then return dz.ALERTLEVEL_RED end
            if delta < 3 then return dz.ALERTLEVEL_YELLOW end
            if delta < 4 then return dz.ALERTLEVEL_ORANGE end
            return dz.ALERTLEVEL_GREEN
        end

        local function setGarbageAlertDevice(alertDevice,alertText, delta)
            dz.devices(alertDevice).updateAlertSensor(alertLevel(delta),alertText)
            return (delta == 0)
        end

        local function longGarbageName(str)                                        -- Use descriptive strings
            str = tostring(str)
            str = str:gsub("PMD","  Plastic verpakkingen, blik en drinkpakken ")
            str = str:gsub("GFT","  Groente-, fruit- en tuin afval ")
            str = str:gsub("Restafval" ,"  Restafval ")
            return str
        end
        
        local function retriggerAfterSec(seconds)
            dz.openURL({
                url =  dz.settings['Domoticz url'] .. "/json.htm?type=command&param=getversion",
                method = "GET",
                callback = "delay_Response" }).afterSec(seconds)
        end  
        
        local function osCommand(cmd)
            local fileHandle     = assert(io.popen(cmd, 'r'))
            local commandOutput  = assert(fileHandle:read('*a'))
            local returnTable    = {fileHandle:close()}
            return commandOutput,returnTable[3]            -- rc[3] contains returnCode
        end
       
        function makeTimeStamp(dateString)
            local pattern = "(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)"
            local xyear, xmonth, xday, xhour, xminute, xseconds = dateString:match(pattern)
            local convertedTimestamp  = os.time({year = xyear, month = xmonth, day = xday, hour = xhour, min = xminute, sec = xseconds})
            return convertedTimestamp 
        end
       
        local function procesJSON(resultJSON)
            keep    = {}
            rt      = dz.utils.fromJSON(resultJSON)
            
            local today = os.date("%Y-%m-%d")
            local garbageLines =  "" 
            local earliestDate   = "2999-12-31"       -- Hopefully we will have a different garbage collection system by then
            
            for i = 1,#rt do
                local fmtDate                 = os.date(" %A %d %B, %Y", makeTimeStamp(rt[i].Date))
                if  rt[i].Date >= today and rt[i].Date < earliestDate then
                    fmtDate             = os.date(" %A %d %B, %Y", makeTimeStamp(rt[i].Date))
                    keep.Date           = rt[i].Date
                    keep.fmtDate        = fmtDate
                    keep.GarbageType    = longGarbageName(rt[i].GarbageType)
                    earliestDate        = rt[i].Date
                end
                garbageLines = garbageLines .. fmtDate .. longGarbageName(rt[i].GarbageType) .. " " .. "\n"
            end

            if myTextDevice then       -- Update defined virtual text device with dates / types
                dz.devices(myTextDevice).updateText(garbageLines)
            end
            
            if myAlertDevice then   -- Update AlertDevice with nearby date / type
                local delta  = os.date("%d",tonumber(makeTimeStamp(keep.Date))) - os.date("%d") 
                garbageToday = setGarbageAlertDevice(  myAlertDevice, keep.GarbageType .. "\n" .. keep.fmtDate, delta )
            end  
            
            if dz.time.matchesRule("at 08:00-17:00") and garbageToday then
                dz.notify(keep.GarbageType .. "will be collected today")
            end
        end

        local function triggerCurlInBackGround()
            local curlCommand  = "curl -v --cookie" 
            local curlCookie  =  'RovaLc_inwoners={' ..
                                 '\\"Id\\":' ..             myGarbageID .. ',' .. 
                                 '\\"ZipCode\\":\\"' ..     myZipcode .. '\\",' .. 
                                 '\\"HouseNumber\\":\\"' .. myHousenumber .. '\\"}' 
            local curlHTTP    = "https://www.rova.nl/api/TrashCalendar/GetCalendarItems?portal=inwoners"
            local backGround  = " & "  -- We don't want the script to wait for the result so process curl in background

            getGarbageCollectionDatesCommand = curlCommand .. " " .. curlCookie  .. " " .. curlHTTP .. " > " .. outFile .. backGround 
            osCommand(getGarbageCollectionDatesCommand)
        end
        
        local function waitForAndProcessResult()
            local result, returnCode = osCommand(catCommand .. " " .. outFile) -- is the output there ?
            if returnCode == 0 then                                 -- Yes
                -- logWrite(result) 
                osCommand("rm " .. outFile)
                procesJSON(result)
            else                                                    -- Not yet. Come back in repeatDelay seconds 
                logWrite("No result yet")
                dz.data.delay = dz.data.delay + repeatDelay                    -- Keep track of the delays 
                if dz.data.delay > maxDelay then
                    logWrite("We are waiting > maxDelay seconds for the result. Giving up now",dz.LOG_ERROR)
                else
                    retriggerAfterSec(repeatDelay)
                end
            end 
        end
        
        -- main 
        if item.isDevice or item.isTimer then
            triggerCurlInBackGround()
            retriggerAfterSec(initialDelay) -- We will come back in initialDelay seconds to check if output has already arrived
            dz.data.delay = initialDelay 
        else
            waitForAndProcessResult()
        end
    end
}
I'm a happy user of this script but it's seems like the rova api changed.
The api is only showing the future collections days, so on the collection day what is being is not longer showed.
This causes the notications no longer to work.

I hope anyone has an idea on how to fix this.
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by waaren »

annegerben wrote: Friday 14 February 2020 9:08 I hope anyone has an idea on how to fix this.

Code: Select all

        local myZipcode     = "0000AA"            -- Your zipcode like "3085RA"
        local myHousenumber = "99"                -- Your housenumber like 38
        local myGarbageID   = "9999999"            -- Your GarbageID 
If you send me a DM with your settings (see above) I will try to fix it.
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
annegerben
Posts: 26
Joined: Wednesday 03 August 2016 12:34
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: dzVents get garbage collection dates (various)

Post by annegerben »

waaren wrote: Friday 14 February 2020 10:32 If you send me a DM with your settings (see above) I will try to fix it.
done
User avatar
jvdz
Posts: 2189
Joined: Tuesday 30 December 2014 19:25
Target OS: Raspberry Pi / ODroid
Domoticz version: 4.107
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by jvdz »

dheuts wrote: Tuesday 07 May 2019 20:52
Great idea! I'm using another script for RD4 and I was wondering if this is also possible with the RD4 script?
https://github.com/jvanderzande/mijnafv ... imburg-rd4

Does anyone know this or can anybody help me?
Thanks!
The new version does allow for shelling your own command at notification time, so should make this possible as well in my scripts.

Jos
New Garbage collection scripts: https://github.com/jvanderzande/GarbageCalendar
annegerben
Posts: 26
Joined: Wednesday 03 August 2016 12:34
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: dzVents get garbage collection dates (various)

Post by annegerben »

Below the updated script for rova.nl, All credits go to waaren.

- adjusted to new rova.nl api to keep showing collection type on collection day.
- Papier & Karton added as collection type.

Code: Select all

 --[[ getGarbage.lua for [ dzVents >= 2.4 ]

    this script is only useful in those  areas of the Netherlands where the household garbage collector is rova
    Tested on debian stretch but probably also working on other Linux variants.

    needs curl command 
    needs to be able to process commands in the background ( by using leading &)

    Enter your zipcode, housenumber and garbageID in the appropriate places between the lines starting with -- ***
    Next is to set your virtual text and or virtual alert device.

    the text device will contain the most nearby collectdates for the types of household garbage
    the alert device will contain the date and type for the garbagecollection that will arrive first
    notification system will be called when collect will be today

]]-- 
 
 return 
 {
         on =   
         {   
             timer           =   { 'at 00:05','at 08:00' },    -- daily run twice
             devices         =   { 'getGarbage'          },    -- Ignore just for test  
             httpResponses   =   { 'delay_Response'      },    -- (re)triggers the script
        },
                
        logging =   
        {   
            level   = domoticz.LOG_DEBUG ,              -- Change to ERROR when script is behaving as expected  
            marker  = ''},                              -- Will be set in execute = function block 
            
        data = 
        {   
            delay = { initial = 0 },
            garbage = { initial = {} },
        },

    execute = function(dz, item, info)

    -- ************************* Mandatory: Set your values and device names below this Line 
        
        local myZipcode     = '3085RA'            -- Your zipcode like '3085RA'
        local myHousenumber = '38'                -- Your housenumber like 38
        local myGarbageID   = '9999999'            -- Your GarbageID
        local myTextDevice  = 'GarbageText'       -- Name with quotes or idx without when created as virtual text device
        local myAlertDevice = 'GarbageAlert'      -- Name with quotes or idx without when created as virtual alert device
        
    -- **************************************************************** No changes required below this  
       local initialDelay           = 2 
       local repeatDelay            = 10
       local maxDelay               = 60
       local outFile                = '/tmp/garbageCollectionDates.json'
       local catCommand             = 'cat'
       _G.logMarker                = info.scriptName     -- sets the logmarker for dz.log

        local function logWrite(str, level)
            dz.log(str, level or dz.LOG_DEBUG)
        end
        
        local function alertLevel(delta)
            if delta < 2 then return dz.ALERTLEVEL_RED end
            if delta < 3 then return dz.ALERTLEVEL_YELLOW end
            if delta < 4 then return dz.ALERTLEVEL_ORANGE end
            return dz.ALERTLEVEL_GREEN
        end

        local function setGarbageAlertDevice(alertDevice,alertText, delta)
            dz.devices(alertDevice).updateAlertSensor(alertLevel(delta),alertText)
        end

        local function longGarbageName(str)                                        -- Use descriptive strings
            str = tostring(str)
            str = str:gsub('PMD','  Plastic verpakkingen, blik en drinkpakken ')
            str = str:gsub('GFT','  Groente-, fruit- en tuin afval ')
            str = str:gsub('Restafval' ,'  Restafval ')
            str = str:gsub('Papier','  Papier en karton ')
            return str
        end

        local function retriggerAfterSec(seconds)
            dz.openURL(
                {
                    url =  dz.settings['Domoticz url'] .. '/json.htm?type=command&param=getversion',
                    method = 'GET',
                    callback = 'delay_Response' 
                }).afterSec(seconds)
        end  

        local function osCommand(cmd)
            local fileHandle     = assert(io.popen(cmd, 'r'))
            local commandOutput  = assert(fileHandle:read('*a'))
            local returnTable    = {fileHandle:close()}
            return commandOutput,returnTable[3]            -- rc[3] contains returnCode
        end
       
        function makeTimeStamp(dateString)
            local pattern = '(%d+)%-(%d+)%-(%d+)T(%d+):(%d+):(%d+)'
            local xyear, xmonth, xday, xhour, xminute, xseconds = dateString:match(pattern)
            local convertedTimestamp  = os.time({year = xyear, month = xmonth, day = xday, hour = xhour, min = xminute, sec = xseconds})
            return convertedTimestamp 
        end

        local function updatePersistent(resultJSON)
            local rt = dz.utils.fromJSON(resultJSON)
            for i = 1,#rt do
                local timeStamp = makeTimeStamp(rt[i].Date)
                local garbageType = rt[i].GarbageType
                if dz.data.garbage[garbageType] == nil or dz.data.garbage[garbageType] >= timeStamp then 
                    dz.data.garbage[garbageType] = timeStamp 
                end
            end
        end

        local function updateSensors()
            local garbageLines = {}
            local garbageStamps = {}
            local garbageNotify
            local alertLines = {}
            local textLines = ''

            local todayBegin = makeTimeStamp(dz.time.rawDate .. 'T00:00:00')
            local lowest = 2^32

            for garbageType, timeStamp in pairs(dz.data.garbage) do

                if timeStamp >= todayBegin then 
                    table.insert(garbageStamps, timeStamp )
                    local garbageName = longGarbageName(garbageType)
                    garbageLines[timeStamp] = os.date(' %A %d %B %Y', timeStamp ) .. garbageName
                    if timeStamp < lowest then 
                        garbageNotify = garbageName 
                        lowest = timeStamp 
                    end
                    alertLines[timeStamp] = garbageName .. '\n' .. os.date(' %A %d %B, %Y', timeStamp ) 
                else
                    dz.data.garbage[garbageType] = nil
                end
            end

            table.sort(garbageStamps)
            local delta  = os.date('%d',garbageStamps[1]) - os.date('%d') 

            for _, timeStamp in ipairs(garbageStamps) do
                textLines = textLines .. garbageLines[timeStamp] .. '\n'
            end

            if myTextDevice then       -- Update defined virtual text device with dates / types
                dz.devices(myTextDevice).updateText(textLines)
            end

            if myAlertDevice then   -- Update AlertDevice with nearby date / type
                setGarbageAlertDevice(  myAlertDevice, alertLines[garbageStamps[1]], delta )
            end  

            if delta == 0 then 
                return garbageNotify
            end

        end

        local function triggerCurlInBackGround()
            local curlCommand  = 'curl -v --cookie' 
            local curlCookie  =  'RovaLc_inwoners={' ..
                                 '\\"Id\\":' ..             myGarbageID .. ',' .. 
                                 '\\"ZipCode\\":\\"' ..     myZipcode .. '\\",' .. 
                                 '\\"HouseNumber\\":\\"' .. myHousenumber .. '\\"}' 
            local curlHTTP    = 'https://www.rova.nl/api/TrashCalendar/GetCalendarItems?portal=inwoners'
            local backGround  = ' & '  -- We don't want the script to wait for the result so process curl in background

            getGarbageCollectionDatesCommand = curlCommand .. ' ' .. curlCookie  .. ' ' .. curlHTTP .. ' > ' .. outFile .. backGround 
            osCommand(getGarbageCollectionDatesCommand)
        end

        local function waitForAndProcessResult()
            local result, returnCode = osCommand(catCommand .. ' ' .. outFile) -- is the output there ?
            if returnCode == 0 then                                 -- Yes
                osCommand('rm ' .. outFile)
                updatePersistent(result)
                return true
            else                                                    -- Not yet. Come back in repeatDelay seconds 
                logWrite('No result yet')
                dz.data.delay = dz.data.delay + repeatDelay                    -- Keep track of the delays 
                if dz.data.delay > maxDelay then
                    logWrite('Waiting > maxDelay seconds for the result. Giving up now',dz.LOG_ERROR)
                else
                    retriggerAfterSec(repeatDelay)
                end
            end 
        end

        local function notifyToday(garbageType)
            if dz.time.matchesRule('at 08:00-17:00') and garbageType then
                dz.notify('Garbage alert',garbageType .. 'will be collected today')
            end
        end

        -- main 
        if item.isDevice or item.isTimer then
            triggerCurlInBackGround()
            retriggerAfterSec(initialDelay) -- We will come back in initialDelay seconds to check if output has already arrived
            dz.data.delay = initialDelay 
        else
            if waitForAndProcessResult() then
                notifyToday(updateSensors())
            end
        end
    end
}
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: dzVents get garbage collection dates (various)

Post by rrozema »

Thanks for the great example waaren! It didn't work for me at first though (I got errors on invalid dates that I later found to be because no data was found), so I made "some" changes to the script. It should work on exactly the same devices as the original: if you've got your domoticz set up for the original script, you can simply disable that script and create a temporary new script in which you paste this altered version to test it. If you do so unaltered it'll give you an alert for when our king needs to put out the trash bin at Huis ten Bosch ;-). But it's probably more fun to put in your own provider, postcode and home number to get alerts for your own home address :-).

What I did in this version:
  • added a lot of error checking,
  • added automatic retrieval of the available types
  • added automatic retrieval of you "bagid"
  • added automatically selecting available types
  • added caching type and bagid information
When you change the zip code and/or number, the cached information will be flushed at the next run, so no need to manually clear the cached data: just change the address info and it'll re-request the information from your provider.


edit: removed preliminary version now superseded by the one in the next posting.
Last edited by rrozema on Saturday 21 March 2020 10:14, edited 2 times in total.
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: dzVents get garbage collection dates (various)

Post by rrozema »

Maybe I went a little over the top with this. But... this is my final version that everyone should be able to use. After you've created the both devices, put below script in a dzvents script, fill in your postcode and number and the rest is automatic: If your address is in the area of one of the providers in the list, the dates will be retrieved and updated.

Changes:
  • Added automatic selection of the provider
  • alert icon is normally gray, green one day before collection day, red on collection day.
  • devices are only updated if their content differs
  • corrected program flow in case of any errors

Code: Select all

--[[ getGarbageDates.lua for [ dzVents >= 2.4 ]

This script is only useful in those areas of the Netherlands where the HVC group collects household garbage

Enter your zipcode and housenumber in the appropriate place between the lines starting with --++++
Next is to set your virtual text and or virtual alert device.

the text device will contain the most nearby collectdates for the four types of household garbage
the alert device will contain the date and type for the garbagecollecion that will arrive first

Ga naar de volgende url in de browser, waarbij je de juiste url voor jouw afvalverwerker kiest, en postcode en huisnummer wijzigd.
https://apps.hvcgroep.nl/rest/adressen/3328LN-35
de output die je krijgt te zien bevat een bagId wat je later nodig hebt.

Dit bagId wordt gebruikt in de volgende URLs:
Ophaaldagen: https://apps.hvcgroep.nl/rest/adressen/bagId/kalender/2018 <<replace bagId
De ophaaldagen gebruiken ID's om aan te geven welk afvaltype het betreft.
Informatie over deze afvaltypes kan opgehaald worden via:
https://apps.hvcgroep.nl/rest/adressen/bagId/afvalstromen <<replace bagId

]]--

--++++--------------------- Mandatory: Set your values and device names below this Line -------------------------------------

local ZIPCODE = "1234AB"        -- postcode, no space between 4 digits and 2 letters!
local NUMBER = "123"             -- huisnummer


local TEXT_DEVICE_NAME = "Garbage"
local ALERT_DEVICE_NAME = "GarbageAlert"

--++++---------------------------- Set your values and device names above this Line -----------------------------------------

local GETBAGID = "getBagId_Response"
local GETTYPES = "getTypes_Response"
local GETDATES = "getGarbage_Response"

local provider_list = {
        ["Cyclus NV"] = "https://afvalkalender.cyclusnv.nl",
        ["HVC"] = "https://apps.hvcgroep.nl",
        ["Dar"] = "https://afvalkalender.dar.nl",
        ["Afvalvrij"] = "https://afvalkalender.circulus-berkel.nl",
        ["Meerlanden"] = "https://afvalkalender.meerlanden.nl",
        ["Cure"] = "https://afvalkalender.cure-afvalbeheer.nl", 
        ["Avalex"] = "https://www.avalex.nl",
        ["RMN"] = "https://inzamelschema.rmn.nl",
        ["Venray"] = "https://afvalkalender.venray.nl",
        ["Den Haag"] = "https://huisvuilkalender.denhaag.nl",
        ["Berkelland"] = "https://afvalkalender.gemeenteberkelland.nl",
        ["Alphen aan den Rijn"] = "https://afvalkalender.alphenaandenrijn.nl",
        ["Waalre"] = "http://afvalkalender.waalre.nl",
        ["ZRD"] = "https://afvalkalender.zrd.nl",
        ["Spaarnelanden"] = "https://afvalwijzer.spaarnelanden.nl",
        --["Montfoort"] = "https://afvalkalender.montfoort.nl",     -- url no longer available?
        ["GAD"] = "https://inzamelkalender.gad.nl",
        ["Cranendonck"] = "https://afvalkalender.cranendonck.nl"
    }

return {
    on = {
        timer = {
          "at 00:01",
          "at 05:00"
          -- 'every 1 minutes'
        },
        httpResponses = { 
            GETDATES,  -- Trigger reading garbage collection schema
            GETTYPES,  -- Trigger reading afvalstromen
            GETBAGID
        } 
    },

--    logging = {
--        level = domoticz.LOG_INFO, -- Remove the "-- at the beginning of this and next line for debugging the script
--        marker = "collectGarbage"
--    },

    data = { 
        code = {initial = nil},
        bagId = {initial = nil},
        types = {initial = nil},
        garbage = {initial = {}},
        provider = {initial = nil}
    }, -- Keep a copy of last json just in case

    execute = function(dz, triggerObject)

        local myCode = ZIPCODE .. "-" .. NUMBER

        -- Build a get request for a specified trigger type
        -- and send it after secondsFromNow.
        local function request_Response( triggerName, secondsFromNow)
            local url = nil

            if GETDATES == triggerName then
                local myYear = os.date("%Y")
                url = provider_list[dz.data.provider] .. "/rest/adressen/" .. dz.data.bagId .. "/kalender/" .. myYear
                --dz.log( "request dates from " .. dz.data.provider .. ". url = " .. url .. ".", dz.LOG_INFO )
            elseif GETTYPES == triggerName then
                url = provider_list[dz.data.provider] .. "/rest/adressen/" .. dz.data.bagId .. "/afvalstromen"
                --dz.log( "request types from " .. dz.data.provider .. ". url = " .. url .. ".", dz.LOG_INFO )
            elseif GETBAGID == triggerName then
                url = provider_list[dz.data.provider] .. "/rest/adressen/" .. myCode
                --dz.log( "request bagid from " .. dz.data.provider .. ". url = " .. url .. ".", dz.LOG_INFO )
            else
                dz.log( "Unknown trigger " .. triggerName .. " in request_Response.", dz.LOG_ERROR)
            end
            
            if nil ~= url then
                dz.openURL (
                        {
                            url = url,
                            method = "GET",
                            callback = triggerName
                        }
                    ).afterSec(secondsFromNow)
            end
        end
    
        -- Response to a types request
        local function handleTypesJSON( rt )
            if nil ~= rt and #rt > 0 then
                local types = {}
                
                for j = 1, #rt do
                    types[tostring(rt[j].id)] = rt[j].title
                end
                
                dz.data.types = types
            else
                dz.log( "No types list received from " .. dz.data.provider .. ".", dz.LOG_WARNING )
                dz.data.types = nil
            end
            return (nil ~= dz.data.types)
        end
        
        -- Response to a bagid request
        local function handleBagIdJSON( rt )
            if nil ~= rt and #rt > 0 then
                dz.data.bagId = tostring(rt[1].bagId)
                dz.data.code = myCode

                dz.log( "Got bagId " .. dz.data.bagId .. " for your address from provider " .. dz.data.provider .. ".", dz.LOG_INFO )
            else
                dz.log( "No bagId received from " .. dz.data.provider .. ".", dz.LOG_WARNING )
                dz.data.bagId = nil
            end
            return (nil ~= dz.data.bagId)
        end
    
        local function string2Epoch(dateString) -- seconds from epoch based on stringdate (used by string2Date)
            -- Assuming a date pattern like: yyyy-mm-dd
            local pattern = "(%d+)-(%d+)-(%d+)"
            local runyear, runmonth, runday= dateString:match(pattern)
            local convertedTimestamp = os.time({year = runyear, month = runmonth, day = runday})
            return convertedTimestamp
        end
        
        local function string2Date(str,fmt) -- convert string from json into datevalue
            if fmt then
                return os.date(fmt,string2Epoch(str)) 
            end
            return os.date(" %A %d %B, %Y",string2Epoch(str))
        end
        
        local function alertLevel(delta)
            if delta < 1 then return dz.ALERTLEVEL_RED end
            if delta < 2 then return dz.ALERTLEVEL_ORANGE end
            if delta < 3 then return dz.ALERTLEVEL_GREEN end
            return dz.ALERTLEVEL_GREY
        end
        
        local function setGarbageAlertDevice(alertDeviceName,alertText,alertDate)
            local delta = tonumber(string2Date(alertDate,"%d")) - tonumber(os.date("%d")) -- delta in days between today and first garbage collection date
            local alert_device = dz.devices( alertDeviceName )
            if nil ~= alert_device then
                if nil == alertText then
                    alertText = "<no information available>"
                end
                local color = alertLevel(delta)
                if alertText ~= alert_device.text or color ~= alert_device.color then
                    alert_device.updateAlertSensor( color, alertText )
                end
            end
            return (delta == 0)
        end

        -- Handle response to dates request.
        local function handleGarbageJSON( rt )
            if nil ~= rt and #rt > 0 then
                dz.data.garbage = rt
            elseif nil ~= dz.data.garbage and #dz.data.garbage > 0 then
                rt = dz.data.garbage
                dz.log("Problem with received response (no data). Re-using data from previous run.", dz.LOG_WARNING)
            else
                dz.log("Problem with received response (no data) and no previous data is available.", dz.LOG_ERROR)
                return false
            end
            
            local garbageLines
            local typeEarliestDate
            local overallEarliestDate = nil -- Hopefully we will have a different garbage collection system by then
            local garbageToday = false
            local today = os.date("%Y-%m-%d")
            
            local results = {}
            local unknown = {}
            
            -- Find the first date for each type.
            for j = 1, #rt do
                if dz.data.types[tostring(rt[j].afvalstroom_id)] and rt[j].ophaaldatum >= today then
                    local r = results[tostring(rt[j].afvalstroom_id)]
                    if r == nil or rt[j].ophaaldatum < r then
                        results[tostring(rt[j].afvalstroom_id)] = rt[j].ophaaldatum
                    end
                    if overallEarliestDate == nil or overallEarliestDate > rt[j].ophaaldatum then
                        overallEarliestDate = rt[j].ophaaldatum
                        overallEarliestType = tostring(rt[j].afvalstroom_id)
                    end
                else
                    unknown[tostring(rt[j].afvalstroom_id)] = true
                end
            end
        
            -- if we've found at least one value ...
            if overallEarliestDate then
                -- ... build the lines for the text device.
                -- TODO: sort these lines by date, smallest first.
                garbageLines = ""
                for i, v in pairs(dz.data.types) do
                    if results[i] then
                        garbageLines = garbageLines .. string2Date(results[i],"%a %e %b" ) .. " : " .. dz.data.types[i] .. "\n"
                    end
                end
            else
                garbageLines = "<No information available>"
            end

            -- Plus, update the Alert device with the first upcoming collection date.
            if overallEarliestDate then -- Update AlertDevice with nearest date and its type.
                garbageToday = setGarbageAlertDevice( 
                                    ALERT_DEVICE_NAME,
                                    dz.data.types[overallEarliestType] .. "\n" .. string2Date(overallEarliestDate),
                                    overallEarliestDate
                                )
            else
                garbageToday = false
            end
        
            local text_device = dz.devices(TEXT_DEVICE_NAME)
            if text_device then -- Update defined virtual text device with dates / types
                if garbageLines ~= text_device.text then
                    text_device.updateText(garbageLines)
                end
            end
        
            if dz.time.matchesRule("at 05:00-10:00") and garbageToday then
                if overallEarliestType and dz.data.types[overallEarliestType] then
                    dz.notify(dz.data.types[overallEarliestType] .. " will be collected today")
                end
            end
            
            return true
        end
        

        
        -- Main
        if triggerObject.isTimer then

            -- If we have a nil bagId, a nil provider or the address has changed,
            -- get the first provider from our list and call it's url to see if we
            -- get a bagid for our zipcode + number.
            if nil == dz.data.bagId or nil == dz.data.provider or dz.data.code ~= myCode then
                -- Get the first provider from the provider_list.
                dz.data.provider, _ = next( provider_list, nil )
                if nil ~= dz.data.provider then
                    request_Response( GETBAGID, 1)
                else
                    dz.log( "Sorry, we can't get your garbage collection dates, the provider list seems to be empty.", dz.LOG_ERROR )
                end
            
            -- If we don't have a valid types list, get one now.
            elseif nil == dz.data.types then
                request_Response( GETTYPES, 1 )
                
            -- If we have everything we need, get the dates.
            else
                request_Response( GETDATES, 1 )
            end

        elseif triggerObject.isHTTPResponse then
            
            if triggerObject.ok then
                if GETDATES == triggerObject.trigger then
                    if handleGarbageJSON( triggerObject.json ) then
                        dz.log( "Done collecting dates for your address from " .. dz.data.provider .. ".", dz.LOG_ERROR )
                        return
                    else
                        -- Try again with the next provider from the provider_list.
                        dz.data.provider, _ = next( provider_list, dz.data.provider )
                        if nil ~= dz.data.provider then
                            request_Response( GETBAGID, 1)
                        else
                            dz.log( "Sorry, none of the providers in our list has dates for your address.", dz.LOG_ERROR )
                        end
                    end

                elseif GETTYPES == triggerObject.trigger then
                    if handleTypesJSON( triggerObject.json ) then
                        -- Now that we have a types list, get the dates.
                        request_Response( GETDATES, 1 )
                    else
                        -- Try again with the next provider from the provider_list.
                        dz.data.provider, _ = next( provider_list, dz.data.provider )
                        if nil ~= dz.data.provider then
                            request_Response( GETBAGID, 1)
                        else
                            dz.log( "Sorry, none of the providers in our list has dates for your address.", dz.LOG_ERROR )
                        end
                    end

                elseif GETBAGID == triggerObject.trigger then
                    if handleBagIdJSON( triggerObject.json ) then
                        -- Now that we have a bagid, get the types list.
                        request_Response( GETTYPES, 1 )
                    else
                        -- Try again with the next provider from the provider_list.
                        dz.data.provider, _ = next( provider_list, dz.data.provider )
                        if nil ~= dz.data.provider then
                            request_Response( GETBAGID, 1)
                        else
                            dz.log( "Sorry, none of the providers in our list has dates for your address.", dz.LOG_ERROR )
                        end
                    end

                else
                    dz.log( "Unknown trigger " .. triggerObject.trigger .. " in handle_Response.", dz.LOG_ERROR)
                end
            else
                -- Try again with the next provider from the provider_list.
                dz.data.provider, _ = next( provider_list, dz.data.provider )
                if nil ~= dz.data.provider then
                    request_Response( GETBAGID, 1)
                else
                    dz.log( "Sorry, none of the providers in our list has dates for your address.", dz.LOG_ERROR )
                end
            end
        end
    end
}
@waaren: how do you like this provider selection mechanism with next() 8-)
hjzwiers
Posts: 163
Joined: Friday 12 January 2018 8:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: dzVents get garbage collection dates (various)

Post by hjzwiers »

I used get garbage collection for a long time, but I think something has changed with Cure. Cannot get a BagId anymore. Tried the new script but also not successful. The site seems to have changed to https://www.mijnafvalwijzer.nl/

Anyone else have the same problems/solution?
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: dzVents get garbage collection dates (various)

Post by rrozema »

hjzwiers wrote: Saturday 21 March 2020 13:14 I used get garbage collection for a long time, but I think something has changed with Cure. Cannot get a BagId anymore. Tried the new script but also not successful. The site seems to have changed to https://www.mijnafvalwijzer.nl/

Anyone else have the same problems/solution?
It looks like mijnafvalwijzer.nl is a generic site from the same company that created the search engines for many of the garbage collection companies in the Netherlands. Anyone here who knows how the original url's -like the ones I have in the top of script- were found? So we can find more to add to the list?
hjzwiers
Posts: 163
Joined: Friday 12 January 2018 8:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: dzVents get garbage collection dates (various)

Post by hjzwiers »

I can reach the page with all collection info through https://mijnafvalwijzer.nl/nl/zipcode/housenr/ but then all the data is defiend in klasses. I tried adapting your script but without success
rrozema
Posts: 470
Joined: Thursday 26 October 2017 13:37
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Delft
Contact:

Re: dzVents get garbage collection dates (various)

Post by rrozema »

hjzwiers wrote: Tuesday 31 March 2020 21:18 I can reach the page with all collection info through https://mijnafvalwijzer.nl/nl/zipcode/housenr/ but then all the data is defiend in klasses. I tried adapting your script but without success
Yes, but that is the link for the completely rendered page. In the back-end there are most likely other calls to retrieve the information as was used by our scripts. It's just that the calls to those pages are done by the webserver, not our web client, so we can't see the addresses used for these REST calls. This is why I asked how the original list of urls got compiled: my guess is that they were found by monitoring the calls from some app in a mobile device, but I don't know how to do that, so I can't get at more urls.
ronaldbro
Posts: 327
Joined: Thursday 15 November 2018 21:38
Target OS: Raspberry Pi / ODroid
Domoticz version: 2020.2
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by ronaldbro »

I think mijnafvalwijzer works a little different.
The URL for the json is:

Code: Select all

https://json.mijnafvalwijzer.nl/?method=postcodecheck&postcode=1234AA&street=&huisnummer=123&toevoeging=
Haven't look a lot further yet.
Bikey
Posts: 331
Joined: Sunday 22 February 2015 12:19
Target OS: Linux
Domoticz version: 2020.x
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by Bikey »

Mmm, this url does give back a lot of data, but that's not proper Json as far as I can see.

*** Edit ** after looking again, I see It does provide a Json array with the days the garbage will be collected, but also an huge load of other non relevant info ***

** Edit 2 ** With this regex I can isolate only the Afhaaldagen:

Code: Select all

.*(\"ophaaldagen\".*),.*\"ophaaldagenNext\":.*
Now only to get this in a good DzVents script ;-)
User avatar
HansieNL
Posts: 957
Joined: Monday 28 September 2015 15:13
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: dzVents get garbage collection dates (various)

Post by HansieNL »

@waaren What is the latest dzvents script for MijnAfvalwijzer?
Blah blah blah
User avatar
waaren
Posts: 6028
Joined: Tuesday 03 January 2017 14:18
Target OS: Linux
Domoticz version: Beta
Location: Netherlands
Contact:

Re: dzVents get garbage collection dates (various)

Post by waaren »

HansieNL wrote: Friday 12 June 2020 16:00 @waaren What is the latest dzvents script for MijnAfvalwijzer?
Below is the latest one I made. No idea if it still works (I don't use it myself) but should not be very hard to get it to work if mijnAfvalwijzer stil returns something that looks like a JSON.

Code: Select all

--[[ getGarbageDates.lua for [ dzVents >= 2.4 ]

this script is only useful in those  areas of the Netherlands where the household garbage collector is connected to afvalwijzer.nl

Enter your zipcode and housenumber in the appropriate place between the lines starting with --++++
Next is to set your virtual text and or virtual alert device.

the text device will contain the most nearby collectdates for the four types of household garbage
the alert device will contain the date and type for the garbagecollecion that will arrive first

]]--

return {
        on      =   {   timer              =  { "at 00:05","at 08:00" },    -- daily run twice
                        devices            =  { "Garbage" },               -- Only for test purposes can be ignored  
                        httpResponses      =  { "getGarbage_Response" }     -- Trigger the handle Json part
                },
        logging =   {   level              =   domoticz.LOG_DEBUG,          
                        marker             =   "collectGarbage"      },

        data    =   {   garbage            =    { initial = {}      },       -- Keep a copy of last json just in case  
                        lastStartline      =    { initial = 1       },  
                        lastEndline        =    { initial = 1000    },  
                    },             

    execute = function(dz, triggerObject)

        --++++--------------------- Mandatory: Set your values and device names below this Line --------------------------------------
        local myZipcode     = "3085RA"            -- Your zipcode like "3085RA"
        local myHousenumber =  38                 -- Your housenumber like 38
        local myTextDevice  = "GarbageText"       -- Name with quotes or idx without when created as virtual text device
        local myAlertDevice = "GarbageAlert"      -- Name with quotes or idx without when created as virtual alert device
        --++++---------------------------- Set your values and device names above this Line --------------------------------------------

        local myYear = os.date("%Y")
        garbageTypes  = {"restafval","gft","papier","plastic"}

        local function collectGarbageDates(secondsFromNow)
            local getGarbage_url  = "http://json.mijnafvalwijzer.nl/?method=postcodecheck&postcode="  .. 
                                    myZipcode .. "&street=&huisnummer=" .. 
                                    myHousenumber .. "&toevoeging" 
            dz.openURL  ({  url = getGarbage_url ,
                            method = "GET",
                            callback = "getGarbage_Response" }).afterSec(secondsFromNow)
        end

        -- Add entry to log and notify to all subsystems
        local function errorMessage(message)
            dz.log(message,dz.LOG_ERROR)
            dz.notify(message)
        end

        local function string2Epoch(dateString) -- seconds from epoch based on stringdate (used by string2Date)
            -- Assuming a date pattern like: yyyy-mm-dd
            local pattern = "(%d+)-(%d+)-(%d+)"
            local runyear, runmonth, runday= dateString:match(pattern)
            local convertedTimestamp = os.time({year = runyear, month = runmonth, day = runday})
            return convertedTimestamp
        end

        local function string2Date(str,fmt)             -- convert string from json into datevalue
            if fmt then return os.date(fmt,string2Epoch(str)) end
            return os.date(" %A %d %B, %Y",string2Epoch(str))
        end

        local function alertLevel(delta)
            if delta < 2 then return dz.ALERTLEVEL_RED end
            if delta < 3 then return dz.ALERTLEVEL_YELLOW end
            if delta < 4 then return dz.ALERTLEVEL_ORANGE end
            return dz.ALERTLEVEL_GREEN
        end

        local function setGarbageAlertDevice(alertDevice,alertText,alertDate)
            local delta = tonumber(string2Date(alertDate,"%d")) - tonumber(os.date("%d"))  -- delta in days between today and first garbage collection date
            dz.devices(alertDevice).updateAlertSensor(alertLevel(delta),alertText)
            dz.log("\nalertLevel: " .. alertLevel(delta) .. ", alertText: " .. alertText,dz.LOG_DEBUG)
            return (delta == 0)
        end

        local function longGarbageName(str)                                        -- Use descriptive strings
            str = tostring(str)
            str = str:gsub("plastic","  Plastic verpakkingen, blik en drinkpakken ")
            str = str:gsub("gft","  Groente-, fruit- en tuin afval            ")
            str = str:gsub("papier","  Papier en kartonnen verpakkingen          ")
            str = str:gsub("restafval" ,"  Restafval                                ")
            return str
        end

       local function handleResponse()
            triggerObject.json = dz.utils.fromJSON(triggerObject.data)         -- dzVents does nor recognize the response as pure JSON so conversion is required
            if #triggerObject.json < 1 then
                dz.data.garbage    = triggerObject.json.data.ophaaldagen.data      -- Store this part in dz.data 
                rt = triggerObject.json.data.ophaaldagen.data                      -- and in table
            else
               errorMessage("Problem with response (no data) using data from earlier run")
               rt  = dz.data.garbage                       -- json empty. Get last valid from dz.data
               if #rt < 1 then                              -- No valid data in dz.data either
                  errorMessage("No previous data. are zipcode and housenumber ok and in afvalkalender ?")
                  return false
               end
            end
            
            local lastEndline = 1000
            if dz.data.lastStartline ~= 1 then
                lastEndline = dz.data.lastStartline + 10
            end
            
            local garbageLines = ""
            local typeEarliestDate
            local overallEarliestDate   = "2999-12-31"       -- Hopefully we will have a different garbage collection system by then
            local garbageToday = false
            local today = os.date("%Y-%m-%d")
            
            for i = 1,#garbageTypes do --walk the the type Table
                typeEarliestDate      = "2999-12-31"
                for j = dz.data.lastStartline,math.min(#rt,lastEndline) do                                 -- walk the response table
                    dz.log(rt[j].date .. ": " .. rt[j].type,dz.LOG_DEBUG)        
                    if  rt[j].date >= today and rt[j].date < typeEarliestDate and 
                        rt[j].type == garbageTypes[i] then              -- Keep date closest to today per type
                        typeEarliestDate =  rt[j].date
                        if  typeEarliestDate < overallEarliestDate then     -- date closest to today overall ?
                            overallEarliestDate = typeEarliestDate          -- keep date
                            overallEarliestType =  garbageTypes[i]          -- keep type
                            dz.data.lastStartline = j 
                        end
                        garbageLines = garbageLines .. string2Date(typeEarliestDate,"%a %e %b" ) .. longGarbageName(rt[j].type) .. " " .. "\n"
                        typeEarliestDate = rt[j].date  -- Keep date closest to today

                    end
                end
            end

            if myAlertDevice then   -- Update AlertDevice with nearby date / type
                garbageToday = setGarbageAlertDevice(  myAlertDevice,
                                                        longGarbageName(overallEarliestType) .. "\n" ..
                                                        string2Date(overallEarliestDate),
                                                        overallEarliestDate)
            end

            if myTextDevice then       -- Update defined virtual text device with dates / types
                dz.devices(myTextDevice).updateText(garbageLines)
                dz.log("\n" .. garbageLines,dz.LOG_DEBUG)
            end

            if dz.time.matchesRule("at 08:00-17:00") and garbageToday then
                dz.notify(longGarbageName(overallEarliestType) .. "will be collected today")
            end
        end

        -- Main
        if triggerObject.isHTTPResponse then
            if triggerObject.ok then
                handleResponse()
            else
                errorMessage("Problem with response from hvcgroep (not ok)")
                --collectGarbageDates(600)                            -- response not OK, try again after 10 minutes
            end
        else
            collectGarbageDates(1)
        end
    end
}
Debian buster, bullseye on RPI-4, Intel NUC.
dz Beta, Z-Wave, RFLink, RFXtrx433e, P1, Youless, Hue, Yeelight, Xiaomi, MQTT
==>> dzVents wiki
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest