Online checker websites

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

Online checker websites

Post by janpep »

Domoticz is increasingly proving to be useful as my personal central information centre. I have therefore now also transferred control of some websites that I manage. It ensures that I am notified in a timely manner if one of those websites is unavailable for some reason.
After an afternoon of fiddling around I had it done. And in the context of 'show your projects', I want to share the result.

I use an alert device for this, while a notification is also sent by email if one of the websites is offline. I have the script running every 20 minutes.
The device is only updated when content has changed. This already makes a difference in preventing unnecessary registration. For myself, I have also included the device in a script that clears the logs from time to time, because I am not interested in longer history and also not to take up unnecessary space.

Multiple websites can be entered with URL and Name.
A maximum number of (offline sites) to be shown in the alert device is adjustable (because of the limited space). Therefore, put the most important websites first.

Site after site is called and the response processed via callback. By using the asynchronous shell command execution, you are not affected by the 10 second limitation. A fantastic invention!
To maintain an overview of the whole, a number of things are kept in variables in global_data. For explanation see DzVents wiki

The example result:
WebsiteCheck-1-JanPep.png
WebsiteCheck-1-JanPep.png (11.03 KiB) Viewed 996 times
and
WebsiteCheck-2-JanPep.png
WebsiteCheck-2-JanPep.png (8.35 KiB) Viewed 996 times
The variables that are set in global_data under data:

Code: Select all

        --Used in t-CheckWebsites
        cw_offlineWebsites = { initial = '' },
        cw_alertText = { initial = '' },
        cw_rowCount = { initial = 0 },
        cw_offlineCount =  { initial = 0 },
And finally the script t_CheckWebsites itself:

Code: Select all

-- 18-06-2014 Script by Jan Peppink; hppts://ict.peppink.nl
-- Script runs every xx minutes to check if websites are online.
--      HTTP response status code 200 expected.
--      Gives notification when one or more websites is offline.
--      Set custom Alert device.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local cw_alertIdx = 99999 -- Set to the idx of the Virtual Alert sensor you have to create for this script
local cw_timerInterval = 20  --Set every xx minutes.
local cw_maxalertLines = 4 --Max offline websites to show in devicetext.
-- Set websites to check. When more than 'maxalertLines', place most important first.
local websites = {
    {url = "https://website1.com", name = "Website 1"},
    {url = "https://website2.com", name = "Website 2"},
    {url = "https://website3.com", name = "Website 3"},
    --Add more of these lines as needed.
}
-- For notification
local emailTo = "[email protected]"
local notificationSubject = "Website Monitoring"
local notificationMessage = "Website %s is offline!"

----------------------------------------------------------------------------------
return {
    on = {
        timer = {
            'every ' .. cw_timerInterval .. ' minutes',
        },
		shellCommandResponses = {
		    -- matches callback strings below
            'webcheck',
        },
    },
	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 = " Websitechecks-"
    },
	execute = function( dz, triggeredItem )
        -- Set Local environment=================
        --local _u = dz.utils       -- Holds subset of handy utilities.
        --local _h = dz.helpers     -- Holds the global functions.
        local _d = dz.globalData  -- Holds the global data.

        -- Set your alert device index to store the result.
        local cw_alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
        local cw_alertText = ''
		local cw_lastalertText = dz.devices(cw_alertIdx).text   -- Holds string of the previous round.
        local tableMaxRow = #websites --Number of (loops) sites to check.

        -- Local Functions go here =============
        local function isWebsiteOnline( url2Check )
            dz.executeShellCommand({
                command = 'curl -Is -ipv4 ' .. url2Check .. ' | head -n 1',
                callback = 'webcheck'
            })   
        end

        -- Now start to do something ============
		if triggeredItem.isTimer then
		    --Start cleaning up variables and set counter for brand new start.
		    _d.cw_offlineWebsites = ''
		    _d.cw_alertText = ''
		    _d.cw_rowCount = 1
		    _d.cw_offlineCount = 0
            dz.log( 'Checking ' .. websites[_d.cw_rowCount].name,  dz.LOG_DEBUG )
            isWebsiteOnline( websites[_d.cw_rowCount].url )
		end
		
        if triggeredItem.isShellCommandResponse then
            --We catched the reponse.
            if triggeredItem.statusCode == 0 then
                --Command ended with success.
                if triggeredItem.trigger == 'webcheck' then
                    -- Trigger = webcheck.
                    if triggeredItem.data:match( "200" ) then
                        -- HTTP code = 200. Site is online.
                        dz.log( websites[_d.cw_rowCount].name .. ' is online.',  dz.LOG_DEBUG )
                    else
                        -- Site is offline, or unexpected HTTP code. Needs check.
                         _d.cw_offlineCount =  _d.cw_offlineCount + 1
                        -- Add site to message to send notification.
                        _d.cw_offlineWebsites = _d.cw_offlineWebsites .. string.format(notificationMessage, websites[_d.cw_rowCount].name ) .. '<br>'
                        if _d.cw_offlineCount <= cw_maxalertLines then
                            --Also add for the device.
                            _d.cw_alertText = _d.cw_alertText .. string.format( notificationMessage, websites[_d.cw_rowCount].name ) .. '<br>'
                        end
                        dz.log( websites[_d.cw_rowCount].name .. ' is offline!',  dz.LOG_DEBUG )                    
                    end

                    if _d.cw_rowCount < tableMaxRow then
                        -- Go for the next website
                        _d.cw_rowCount = _d.cw_rowCount + 1
                        dz.log( 'Checking ' .. websites[_d.cw_rowCount].name,  dz.LOG_DEBUG )
                        isWebsiteOnline( websites[_d.cw_rowCount].url )
                    else
                        --We are done looping the websites. Now check results.
                        if _d.cw_offlineWebsites ~= '' then
                            cw_alertLevel = dz.ALERTLEVEL_RED
                            cw_alertText = _d.cw_alertText
                            dz.email( notificationSubject, _d.cw_offlineWebsites, emailTo, 0 )
                        else
                            cw_alertText = 'Alle website zijn online.'
                            cw_alertLevel = dz.ALERTLEVEL_GREEN
                        end
                        if cw_alertText ~= cw_lastalertText then
                            -- We have new information, so update the device.
                            dz.devices(cw_alertIdx).updateAlertSensor( cw_alertLevel, cw_alertText )
                        end
                    end
                end
            end
        end
    end
}
-- That's All --------------------------------------------------
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.
User avatar
gizmocuz
Posts: 2350
Joined: Thursday 11 July 2013 18:59
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Top of the world
Contact:

Re: Online checker websites

Post by gizmocuz »

That seems like a bad idea.
Have a google for 'uptimerobot'
And leave this to the professionals (and you can also get a push notification)
Quality outlives Quantity!
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

gizmocuz wrote: Thursday 20 June 2024 7:44 That seems like a bad idea.
You may prefer a different method, but I think 'bad idea' is a rather strong expression for something that has worked well for me for many years. Of course you can always do it differently. I transferred the existing functionality from a bash script to Domoticz, where for me the display in the alert device is a nice addition to the dashboard. In this way I bring more and more things together there. In addition, I prefer to do as much as possible under my own control.
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.
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

I am learning more and more about dzVents as I go along. It is also possible to place the persistent data in the script itself under 'data'. I overlooked that before. Since other scripts do not use this persistent data, I have now moved it and using global_data is no longer needed. I will adjust that in my other scripts as well, where applicable.
A second point is that I added a timeout to ensure I remain within the 10 seconds. Therefore the shell command timeout is now set to 9 seconds and the curl timeout is set to 1 second less than that.

Updated script t-CheckWebsites:

Code: Select all

-- 18-06-2014 Script by Jan Peppink; hppts://ict.peppink.nl
-- Script runs every xx minutes to check if websites are online.
--      HTTP response status code 200 expected.
--      Gives notification when one or more websites is offline.
--      Set custom Alert device.
-- 20-06-2024 Added timeout for curl as variable under Your settings.
-- 21-06-2024 Moved persistant data from global_data to local data.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local cw_alertIdx = 99999 -- Set to the idx of the Virtual Alert sensor you have to create for this script
local cw_timerInterval = 20  --Set every xx minutes.
local cw_maxalertLines = 4 --Max offline websites to show in devicetext.
local cw_timeout = 9 -- Timeout in seconds. Stay < 10 sec. for shellcommand. Curl gets 1 second less.
-- Set websites to check. When more than 'maxalertLines', place most important first.
local websites = {
    {url = "https://website1.com", name = "Website 1"},
    {url = "https://website2.com", name = "Website 2"},
    {url = "https://website3.com", name = "Website 3"},
    --Add more of these lines as needed.
}
-- For notification
local emailTo = "[email protected]"
local notificationSubject = "Website Monitoring"
local notificationMessage = "%s is offline!"

----------------------------------------------------------------------------------
return {
    on = {
        timer = {
            'every ' .. cw_timerInterval .. ' minutes',
        },
		shellCommandResponses = {
            -- matches callback strings below
            'webcheck',
        },
    },
    data = {
        -- Persistant data to use in the next run.
        cw_offlineWebsites = { initial = '' },
        cw_alertText = { initial = '' },
        cw_rowCount = { initial = 0 },
        cw_offlineCount = { initial = 0 },
    },
	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 = " Websitechecks-"
    },
	execute = function( dz, triggeredItem )
        -- Set Local environment=================
        --local _u = dz.utils       -- Holds subset of handy utilities.
        --local _h = dz.helpers     -- Holds the global functions.
        --local _d = dz.globalData  -- Holds the global data.

        -- Set your alert device index to store the result.
        local cw_alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
        local cw_alertText = ''
		local cw_lastalertText = dz.devices(cw_alertIdx).text   -- Holds string of the previous round.
        local tableMaxRow = #websites --Number of (loops) sites to check.

        -- Local Functions go here =============
        local function isWebsiteOnline( url2Check )
            dz.executeShellCommand({
                command = 'curl -Is -ipv4 --max-time ' .. cw_timeout -1 .. ' ' .. url2Check .. ' | head -n 1',
                callback = 'webcheck',
                timeout = cw_timeout,
            })   
        end

        -- Now start to do something ============
		if triggeredItem.isTimer then
		    --Start cleaning up variables and set counter for brand new start.
		    dz.data.cw_offlineWebsites = ''
		    dz.data.cw_alertText = ''
		    dz.data.cw_rowCount = 1
		    dz.data.cw_offlineCount = 0
            dz.log( 'Checking ' .. websites[dz.data.cw_rowCount].name,  dz.LOG_DEBUG )
            isWebsiteOnline( websites[dz.data.cw_rowCount].url )
		end
		
        if triggeredItem.isShellCommandResponse then
            --We catched the reponse.
            if triggeredItem.statusCode == 0 then
                --Command ended with success.
                if triggeredItem.trigger == 'webcheck' then
                    -- Trigger = webcheck.
                    if triggeredItem.data:match( "200" ) then
                        -- HTTP code = 200. Site is online.
                        dz.log( websites[dz.data.cw_rowCount].name .. ' is online.',  dz.LOG_DEBUG )
                    else
                        -- Site is offline, or unexpected HTTP code. Needs check.
                         dz.data.cw_offlineCount =  dz.data.cw_offlineCount + 1
                        -- Add site to message to send notification.
                        dz.data.cw_offlineWebsites = dz.data.cw_offlineWebsites .. string.format(notificationMessage, websites[dz.data.cw_rowCount].name ) .. '<br>'
                        if dz.data.cw_offlineCount <= cw_maxalertLines then
                            --Also add for the device.
                            dz.data.cw_alertText = dz.data.cw_alertText .. string.format( notificationMessage, websites[dz.data.cw_rowCount].name ) .. '<br>'
                        end
                        dz.log( websites[dz.data.cw_rowCount].name .. ' is offline!',  dz.LOG_DEBUG )                    
                    end

                    if dz.data.cw_rowCount < tableMaxRow then
                        -- Go for the next website
                        dz.data.cw_rowCount = dz.data.cw_rowCount + 1
                        dz.log( 'Checking ' .. websites[dz.data.cw_rowCount].name,  dz.LOG_DEBUG )
                        isWebsiteOnline( websites[dz.data.cw_rowCount].url )
                    else
                        --We are done looping the websites. Now check results.
                        if dz.data.cw_offlineWebsites ~= '' then
                            cw_alertLevel = dz.ALERTLEVEL_RED
                            cw_alertText = dz.data.cw_alertText
                            dz.email( notificationSubject, dz.data.cw_offlineWebsites, emailTo, 0 )
                        else
                            cw_alertText = 'Alle website zijn online.'
                            cw_alertLevel = dz.ALERTLEVEL_GREEN
                        end
                        if cw_alertText ~= cw_lastalertText then
                            -- We have new information, so update the device.
                            dz.devices(cw_alertIdx).updateAlertSensor( cw_alertLevel, cw_alertText )
                        end
                    end
                end
            end
        end
    end
}
-- That's All --------------------------------------------------
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.
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

I added a second try when website does not respond immediatly with a HTTP 200 reponse.

Code: Select all

-- 18-06-2014 Script by Jan Peppink; hppts://ict.peppink.nl
-- Script runs every xx minutes to check if websites are online.
--      HTTP response status code 200 expected.
--      Gives notification when one or more websites is offline.
--      Set custom Alert device.
-- 20-06-2024 Added timeout for curl as variable under Your settings.
-- 21-06-2024 Moved persistant data from global_data to local data.
-- 25-06-2024 Added cw_retry for a second try when no HTTP 200 answer is received.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local cw_alertIdx = 99999-- Set to the idx of the Virtual Alert sensor you have to create for this script
local cw_timerInterval = 20 --Set every xx minutes.
local cw_maxalertLines = 4 --Max offline websites to show in devicetext.
local cw_timeout = 9 -- Timeout in seconds. Stay < 10 sec. for shellcommand. Curl gets 1 second less.
-- Set websites to check. When more than 'maxalertLines', place most important first.
local websites = {
    {url = "https://website1.com", name = "Website 1"},
    {url = "https://website2.com", name = "Website 2"},
    {url = "https://website3.com", name = "Website 3"},
    --Add more of these lines as needed.
}
-- For notification
local emailTo = "[email protected]"
local notificationSubject = "Website Monitoring"
local notificationMessage = "%s is offline!"

----------------------------------------------------------------------------------
return {
    on = {
        timer = {
            'every ' .. cw_timerInterval .. ' minutes',
        },
		shellCommandResponses = {
            -- matches callback strings below
            'webcheck',
        },
    },
    data = {
        -- Persistant data to use in the next run of this script.
        cw_offlineWebsites = { initial = '' },
        cw_alertText = { initial = '' },
        cw_rowCount = { initial = 0 },
        cw_offlineCount = { initial = 0 },
        cw_retry = { initial = 0 },
    },
	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 = "Websitechecks-"
    },
	execute = function( dz, triggeredItem )
        -- Set Local environment=================
        --local _u = dz.utils       -- Holds subset of handy utilities.
        --local _h = dz.helpers     -- Holds the global functions.
        --local _d = dz.globalData  -- Holds the global data.

        -- Set your alert device index to store the result.
        local cw_alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
        local cw_alertText = ''
		local cw_lastalertText = dz.devices(cw_alertIdx).text   -- Holds string of the previous round.
        local tableMaxRow = #websites --Number of (loops) sites to check.

        -- Local Functions go here =============
        local function isWebsiteOnline( url2Check )
            dz.executeShellCommand({
                command = 'curl -Is -ipv4 --max-time ' .. cw_timeout -1 .. ' ' .. url2Check .. ' | head -n 1',
                callback = 'webcheck',
                timeout = cw_timeout,
            })   
        end

        -- Now start to do something ============
		if triggeredItem.isTimer then
		    --Start cleaning up variables and set counter for brand new start.
		    dz.data.cw_offlineWebsites = ''
		    dz.data.cw_alertText = ''
		    dz.data.cw_rowCount = 1
		    dz.data.cw_offlineCount = 0
		    dz.data.cw_retry = 0
            dz.log( 'Checking ' .. websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
            isWebsiteOnline( websites[dz.data.cw_rowCount].url )
		end
		
        if triggeredItem.isShellCommandResponse then
            --We catched the reponse.
            if triggeredItem.statusCode == 0 then
                --Command ended with success.
                if triggeredItem.trigger == 'webcheck' then
                    -- Trigger = webcheck.
                    if triggeredItem.data:match( "200" ) then
                        -- HTTP code = 200. Site is online.
                        dz.log( websites[dz.data.cw_rowCount].name .. ' is online.', dz.LOG_DEBUG )
                        -- reset the retry counter.
                        dz.data.cw_retry = 0
                    else
                        -- Site is offline, or unexpected HTTP code.
                        if dz.data.cw_retry == 0 then
                            --Seems offline. Give it a second try.
                            dz.data.cw_retry = dz.data.cw_retry + 1
                            dz.log( 'No HTTP 200 response from ' .. websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
                            dz.log( 'Go for second check ' .. websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
                            isWebsiteOnline( websites[dz.data.cw_rowCount].url )
                        else
                            -- Also the retry is offline. Give up.
                             dz.data.cw_offlineCount = dz.data.cw_offlineCount + 1
                            -- Add site to message to send notification.
                            dz.data.cw_offlineWebsites = dz.data.cw_offlineWebsites .. string.format(notificationMessage, websites[dz.data.cw_rowCount].name ) .. '<br>'
                            if dz.data.cw_offlineCount <= cw_maxalertLines then
                                --Also add for the device.
                                dz.data.cw_alertText = dz.data.cw_alertText .. string.format( notificationMessage, websites[dz.data.cw_rowCount].name ) .. '<br>'
                            end
                            dz.log( websites[dz.data.cw_rowCount].name .. ' is offline!', dz.LOG_DEBUG )
                        end
                    end

                    if dz.data.cw_rowCount < tableMaxRow then
                        -- Go for the next website
                        dz.data.cw_retry = 0
                        dz.data.cw_rowCount = dz.data.cw_rowCount + 1
                        dz.log( 'Checking ' .. websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
                        isWebsiteOnline( websites[dz.data.cw_rowCount].url )
                    else
                        --We are done looping the websites. Now check results.
                        if dz.data.cw_offlineWebsites ~= '' then
                            cw_alertLevel = dz.ALERTLEVEL_RED
                            cw_alertText = dz.data.cw_alertText
                            dz.email( notificationSubject, dz.data.cw_offlineWebsites, emailTo, 0 )
                        else
                            cw_alertText = 'Alle website zijn online.'
                            cw_alertLevel = dz.ALERTLEVEL_GREEN
                        end
                        if cw_alertText ~= cw_lastalertText then
                            -- We have new information, so update the device.
                            dz.devices(cw_alertIdx).updateAlertSensor( cw_alertLevel, cw_alertText )
                        end
                    end
                end
            end
        end
    end
}
-- That's All --------------------------------------------------
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.
User avatar
gizmocuz
Posts: 2350
Joined: Thursday 11 July 2013 18:59
Target OS: Raspberry Pi / ODroid
Domoticz version: beta
Location: Top of the world
Contact:

Re: Online checker websites

Post by gizmocuz »

If you want to self-host, you can also use Kuma.

https://github.com/louislam/uptime-kuma

You can easily install this via docker compose
Quality outlives Quantity!
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

gizmocuz wrote: Wednesday 26 June 2024 8:07 If you want to self-host, you can also use Kuma.
Thank you for thinking with me, but this is doing much more than I need or want. And it is again a separate package in a separate place. I mostly prefer to do just what I want and, when possible, with what I already have running.
For me it is enough to get the HTTP 200 answer. And visible in Domoticz when it is missed.
As said before, in a bash script (not visible in Domoticz), already working for many years. I have added the retry to prevent a false negative. (Like to play and finetune.) So, I am happy that this can be done with the available options in dzVents.
For me it works completely as desired.
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.
HvdW
Posts: 504
Joined: Sunday 01 November 2015 22:45
Target OS: Raspberry Pi / ODroid
Domoticz version: 2023.2
Location: Twente
Contact:

Re: Online checker websites

Post by HvdW »

Maybe you can use the setup from System Alive Check for the notifications and the way it just sends 1 notification without bothering you with endless repeating notifications.
Like mentioned in the script: -- the reason for this script is to not treat devices as dead immediately after they
-- do not respond. More often than not, the second ping atempt does work. So only
-- if the device has been not responding for a while AFTER it is been presumed dead
-- then this script will notify you

Code: Select all

-- System-alive-check

-- this script can be used in conjunction with the System-alive checker plug-in.
-- the plugin pings a list of devices and creates switches for these devices
-- the reason for this script is to not treat devices as dead immediately after they
-- do not respond. More often than not, the second ping atempt does work. So only
-- if the device has been not responding for a while AFTER it is been presumed dead
-- then this script will notify you
-- put the names of these switches in the devicesToCheck list
-- you may have to tweak the THRESHOLD depending on the check interval

local THRESHOLD = 10 -- minutes
local devicesToCheck = 
        {
            'Luftdaten', 'Power', 'Gas',
        }

return 
{
    on = 
    {
        devices = devicesToCheck,

        timer = 
        { 
            'every 6 minutes',
        },
    },

    data = 
    {
        notified = { initial = {} },
    },

    logging = 
    {
        level = domoticz.LOG_ERROR, -- change from LOG_DEBUG to LOG_ERROR when script executes without problems
        marker = 'notify',
    },

    execute = function(dz, item)
        if item.isTimer then
            
            for index, deviceName in ipairs(devicesToCheck) do
                local device = dz.devices(deviceName) 
                dz.log('device name  ' .. device.name, dz.LOG_DEBUG) 
                dz.log('device state ' .. device.state, dz.LOG_DEBUG)        
                dz.log('device lastUpdate ' .. device.lastUpdate.minutesAgo, dz.LOG_DEBUG)        
                dz.log('device notified ' .. tostring(dz.data.notified[deviceName]), dz.LOG_DEBUG)        
                                
                if device.lastUpdate.minutesAgo >= THRESHOLD and dz.data.notified[deviceName] ~= true  then
                    dz.log('Idle device ' .. deviceName, dz.LOG_DEBUG)        
                    dz.notify('notifyer', deviceName .. ' is not responding anymore.',dz.PRIORITY_HIGH)
                    dz.data.notified[deviceName] = true   -- om deze regel, daar draait het om -> eenmalige notificatie
                end
            end
        else
            dz.data.notified[item.name] = false
        end
    end
}

--einde system alive check
Bugs bug me.
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

HvdW wrote: Wednesday 03 July 2024 0:00 Maybe you can use the setup from System Alive Check for the notifications and the way it just sends 1 notification without bothering you with endless repeating notifications.
Thank you for your addition.
It was already on my todo list to build something like that. However, the advantage now is that you also have an idea of ​​how long it was out last night. Perhaps there was some maintenance involved. 3 per hour is not what I call 'endless repeating', but a good and strong reminder :-). Also, during the day, the notification is ment to let you take action and to check and restore the website functionality. When you "endless" do not pay attention, the checking and notification doesn't make much sense.
What you copy/paste here is a complete different script with "'Luftdaten', 'Power', 'Gas'," and has not much to do with "Show-my-project".
I would prefer to receive a notification also when it is back online again. That gives an idea of start~ and endtime. Also that action is no longer needed. That makes it a little more complex.
As said, it is on my list, and I will look at your example. It makes sense to store the ''status' in the data part.
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.
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

janpep wrote: Wednesday 03 July 2024 10:37 As said, it is on my list, and I will look at your example. It makes sense to store the ''status' in the data part.
I have modified the script with some improvements. It was another nice puzzle.
In summary:
  • The websites are checked at adjustable intervals.
  • The website array now also keeps track of the latest status of the website, so that notifications are only sent in case of changes. Therefore, I placed the small array in persistent data (in the script itself).
  • Added trigger for 'system start'. Restart Domoticz re-initializes the array. (Necessary when sites are added or removed.)
  • Repeated attempts reduce the chance of a false negatives. Limit for max. number of retries is adjustable.
  • Alert device is only updated when content changes. Only offline sites are shown.
  • Notification is sent once. When the status of one of the sites changes. (Up or down.)
  • Notification contains the status of all sites. Some shown below as an example.
WebsiteCheck-3-JanPep.png
WebsiteCheck-3-JanPep.png (5.83 KiB) Viewed 702 times
The renamed and updated script st-CheckWebsites:

Code: Select all

-- 18-06-2014 Script by Jan Peppink; hppts://ict.peppink.nl
-- Script runs every xx minutes to check if websites are online.
--      HTTP response status code 200 expected.
--      Gives notification when one or more websites is offline.
--      Set custom Alert device.
-- 20-06-2024 Added timeout for curl as variable under Your settings.
-- 21-06-2024 Moved persistant data from global_data to local data.
-- 25-06-2024 Added cw_retry to count retries when no HTTP 200 answer is received.
-- 26-06-2024 Added cwmaxRetries to limit the max number of retries.
-- 04-07-2024 Moved websites array to data part. Added to keep track of online status.
--            Added re-initialize array at Domoticz system start.
--            Send notification once when status has changed. Notification gives them all.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local cw_alertIdx = 99999    -- Set to the idx of the Virtual Alert sensor you have to create for this script
local cw_timerInterval = 20  -- Set every xx minutes.
local cw_maxalertLines = 4  -- Max offline websites to show in devicetext.
local cw_timeout = 9        -- Timeout in seconds. Stay < 10 sec. for shellcommand. Curl gets 2 seconds less.
local cw_maxRetries = 2     -- Maximum number of retries for each site.
-- For notification
local cw_emailTo = "[email protected]"
local cw_notificationSubject = "Website Monitoring"
local cw_notificationMessage = "%s is %s!"
-- Set websites to check under the data part. When more than 'maxalertLines', place most important first.
-- >>> RESTARTT domoticz after changing the website list to re-initialize the array. <<<


----------------------------------------------------------------------------------
return {
    on = {
        system =
        {
            'start',
        },
        timer = {
            'every ' .. cw_timerInterval .. ' minutes',
        },
        shellCommandResponses = {
            -- matches callback strings below
            'webcheck',
        },
    },
    data = {
        -- Persistant data to use in the next run of this script.
        cw_notificationText = { initial = '' },
        cw_alertText = { initial = '' },
        cw_rowCount = { initial = 0 },
        cw_offlineCount = { initial = 0 },
        cw_retry = { initial = 0 },
        cw_websites = { initial = {
            {url = "https://website1.com", name = "Website 1", online = true },
            {url = "https://website2.com", name = "Website 2", online = true },
            {url = "https://website3.com", name = "Website 3", online = true },
            }
        },
        cw_notificationTosend = { initial = false },
    },
	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 = "Websitechecks-"
    },
	execute = function( dz, triggeredItem )
        -- Set Local environment=================
        --local _u = dz.utils       -- Holds subset of handy utilities.
        --local _h = dz.helpers     -- Holds the global functions.
        --local _d = dz.globalData  -- Holds the global data.

        -- Set your alert device index to store the result.
        local cw_alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
		local cw_lastalertText = dz.devices(cw_alertIdx).text   -- Holds string of the previous round.
        local cw_tableMaxRow = #dz.data.cw_websites --Number of (loops) sites to check.

        -- Local Functions go here =============
        -- for the sites to check call
        local function isWebsiteOnline( url2Check )
            dz.executeShellCommand({
                command = 'curl -Is -ipv4 --max-time ' .. cw_timeout - 2 .. ' ' .. url2Check .. ' | head -n 1',
                callback = 'webcheck',
                timeout = cw_timeout,
            })
        end

        -- Now start to do something ============
        if triggeredItem.isSystemEvent and triggeredItem.type == 'start' then
            --Re-initialize the website array at Domoticz start.
		    dz.data.initialize('cw_websites')            
        end

		if triggeredItem.isTimer then
		    --Start cleaning up variables and set counter for brand new start.
		    dz.data.cw_notificationText = ''
		    dz.data.cw_alertText = ''
		    dz.data.cw_rowCount = 1
		    dz.data.cw_offlineCount = 0
		    dz.data.cw_retry = 0
		    dz.data.cw_notificationTosend = false
            dz.log( '#rows in webite table =  ' .. cw_tableMaxRow, dz.LOG_DEBUG )
            dz.log( 'Checking ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
            isWebsiteOnline( dz.data.cw_websites[dz.data.cw_rowCount].url )
            --End script and wait for the isShellCommandResponse.
            return            
		end
		
        if triggeredItem.isShellCommandResponse then
            --We catched the reponse.
            if triggeredItem.statusCode == 0 then
                --Command ended with success.
                if triggeredItem.trigger == 'webcheck' then
                    -- Trigger = webcheck.
                    if triggeredItem.data:match( "200" ) then
                        -- HTTP code = 200. Site is online.
                        dz.log( dz.data.cw_websites[dz.data.cw_rowCount].name .. ' is online.', dz.LOG_DEBUG )
                            -- Add site status to message to send notification.
                        dz.data.cw_notificationText = dz.data.cw_notificationText .. string.format( cw_notificationMessage, dz.data.cw_websites[dz.data.cw_rowCount].name, '<span style="color: green">Online</span>' ) .. '<br>'

                        -- If this site was not Online before, then set online to true.
                        if dz.data.cw_websites[dz.data.cw_rowCount].online ~= true then
                            --Set online status to true
                            dz.data.cw_websites[dz.data.cw_rowCount].online = true
                            --Mark for notification because of status change.
                            dz.data.cw_notificationTosend = true
                        end
                        -- reset the retry counter.
                        dz.data.cw_retry = 0
                    else
                        -- Site is offline, or unexpected HTTP code.
                        if dz.data.cw_retry < cw_maxRetries then
                            --Seems offline. Give it a next try.
                            dz.log( 'No HTTP 200 response from ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )

                            dz.data.cw_retry = dz.data.cw_retry + 1
                            dz.log( 'Retry ' .. dz.data.cw_retry .. ' for ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
                            isWebsiteOnline( dz.data.cw_websites[dz.data.cw_rowCount].url )
                            --End script and wait for the isShellCommandResponse.
                            return
                        else
                            -- Also the retry is offline. Give up.
                            dz.data.cw_offlineCount = dz.data.cw_offlineCount + 1

                            dz.log( dz.data.cw_websites[dz.data.cw_rowCount].name .. ' is offline!', dz.LOG_DEBUG )
                            -- Add site status to message to send notification.
                            dz.data.cw_notificationText = dz.data.cw_notificationText .. string.format( cw_notificationMessage, dz.data.cw_websites[dz.data.cw_rowCount].name, '<span style="color: red">Offline</span>' ) .. '<br>'

                            if dz.data.cw_offlineCount <= cw_maxalertLines then
                                --Also add site status for the device text.
                                dz.data.cw_alertText = dz.data.cw_alertText .. string.format( cw_notificationMessage, dz.data.cw_websites[dz.data.cw_rowCount].name, 'Offline' ) .. '<br>'
                            end

                            -- If this site was not Offline before, then set online to false
                            if dz.data.cw_websites[dz.data.cw_rowCount].online ~= false then
                                --Set online status to false.
                                dz.data.cw_websites[dz.data.cw_rowCount].online = false
                            --Mark for notification because of status change.
                                dz.data.cw_notificationTosend = true
                            end
                        end
                    end

                    if dz.data.cw_rowCount < cw_tableMaxRow then
                        -- Go for the next website.
                        dz.data.cw_retry = 0
                        dz.data.cw_rowCount = dz.data.cw_rowCount + 1
                        dz.log( 'Checking ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
                        isWebsiteOnline( dz.data.cw_websites[dz.data.cw_rowCount].url )
                        --End script and wait for the isShellCommandResponse.
                        return
                    else
                        --We are done looping the websites. Now check results.
                        if dz.data.cw_offlineCount > 0 then
                            cw_alertLevel = dz.ALERTLEVEL_RED
                            if dz.data.cw_notificationTosend == true then
                                dz.email( cw_notificationSubject, dz.data.cw_notificationText, cw_emailTo, 0 )
                            end
                        else
                            dz.data.cw_alertText = 'Alle website zijn online.'
                            cw_alertLevel = dz.ALERTLEVEL_GREEN
                            if dz.data.cw_notificationTosend == true then
                                dz.email( cw_notificationSubject, dz.data.cw_notificationText, cw_emailTo, 0 )
                            end
                        end
                        if dz.data.cw_alertText ~= cw_lastalertText then
                            -- Text changed, so update the device.
                            dz.devices(cw_alertIdx).updateAlertSensor( cw_alertLevel, dz.data.cw_alertText )
                        end
                    end
                end
            end
        end
    end
}
-- That's All --------------------------------------------------
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.
janpep
Posts: 212
Joined: Thursday 14 March 2024 10:11
Target OS: Linux
Domoticz version: 2024.7
Location: Netherlands
Contact:

Re: Online checker websites

Post by janpep »

The link to the website has been added to the notification. That makes it easier to check immediately.

Code: Select all

-- 18-06-2014 Script by Jan Peppink; hppts://ict.peppink.nl
-- Script runs every xx minutes to check if websites are online.
--	  HTTP response status code 200 expected.
--	  Gives notification when one or more websites is offline.
--	  Set custom Alert device.
-- 20-06-2024 Added timeout for curl as variable under Your settings.
-- 21-06-2024 Moved persistant data from global_data to local data.
-- 25-06-2024 Added cw_retry to count retries when no HTTP 200 answer is received.
-- 26-06-2024 Added cwmaxRetries to limit the max number of retries.
-- 04-07-2024 Moved websites array to data part. Added to keep track of online status.
--			Added re-initialize array at Domoticz system start.
--			Send notification once when status has changed. Notification gives them all.
-- 12-07-2024 Added link to the notification for easy immmediate check.

--- Your settings ----------------------------------------------------------------
-- First set the used device index numbers and variables you might want to change.
local cw_alertIdx = 99999	-- Set to the idx of the Virtual Alert sensor you have to create for this script
local cw_timerInterval = 20  -- Set every xx minutes.
local cw_maxalertLines = 4  -- Max offline websites to show in devicetext.
local cw_timeout = 9		-- Timeout in seconds. Stay < 10 sec. for shellcommand. Curl gets 2 seconds less.
local cw_maxRetries = 2	 -- Maximum number of retries for each site.
-- For notification
local cw_emailTo = "[email protected]"
local cw_notificationSubject = "Website Monitoring"
local cw_notificationMessage = "%s is %s!"

-- Set websites to check under the data part. When more than 'maxalertLines', place most important first.
-- >>> RESTARTT domoticz after changing the website list to re-initialize the array. <<<


----------------------------------------------------------------------------------
return {
	on = {
		system =
		{
			'start',
		},
		timer = {
			'every ' .. cw_timerInterval .. ' minutes',
		},
		shellCommandResponses = {
			-- matches callback strings below
			'webcheck',
		},
	},
	data = {
		-- Persistant data to use in the next run of this script.
		cw_notificationText = { initial = '' },
		cw_alertText = { initial = '' },
		cw_rowCount = { initial = 0 },
		cw_offlineCount = { initial = 0 },
		cw_retry = { initial = 0 },
		cw_websites = { initial = {
			{url = "https://website1.com", name = "Website 1", online = true },
			{url = "https://website2.com", name = "Website 2", online = true },
			{url = "https://website3.com", name = "Website 3", online = true },
			}
		},
		cw_notificationTosend = { initial = false },
	},
	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 = "Websitechecks-"
	},
	execute = function( dz, triggeredItem )
		-- Set Local environment=================
		--local _u = dz.utils	   -- Holds subset of handy utilities.
		--local _h = dz.helpers	 -- Holds the global functions.
		--local _d = dz.globalData  -- Holds the global data.

		-- Set your alert device index to store the result.
		local cw_alertLevel = dz.ALERTLEVEL_GREY -- Holds the alertLevel (color) to set
		local cw_lastalertText = dz.devices(cw_alertIdx).text   -- Holds string of the previous round.
		local cw_tableMaxRow = #dz.data.cw_websites --Number of (loops) sites to check.

		-- Local Functions go here =============
		-- for the sites to check call
		local function isWebsiteOnline( url2Check )
			dz.executeShellCommand({
				command = 'curl -Is -ipv4 --max-time ' .. cw_timeout - 2 .. ' ' .. url2Check .. ' | head -n 1',
				callback = 'webcheck',
				timeout = cw_timeout,
			})
		end

		-- Now start to do something ============
		if triggeredItem.isSystemEvent and triggeredItem.type == 'start' then
			--Re-initialize the website array at Domoticz start.
			dz.data.initialize('cw_websites')			
		end

		if triggeredItem.isTimer then
			--Start cleaning up variables and set counter for brand new start.
			dz.data.cw_notificationText = ''
			dz.data.cw_alertText = ''
			dz.data.cw_rowCount = 1
			dz.data.cw_offlineCount = 0
			dz.data.cw_retry = 0
			dz.data.cw_notificationTosend = false
			dz.log( '#rows in webite table =  ' .. cw_tableMaxRow, dz.LOG_DEBUG )
			dz.log( 'Checking ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
			isWebsiteOnline( dz.data.cw_websites[dz.data.cw_rowCount].url )
			--End script and wait for the isShellCommandResponse.
			return			
		end
		
		if triggeredItem.isShellCommandResponse then
			--We catched the reponse.
			if triggeredItem.statusCode == 0 then
				--Command ended with success.
				if triggeredItem.trigger == 'webcheck' then
					-- Trigger = webcheck.
					if triggeredItem.data:match( "200" ) then
						-- HTTP code = 200. Site is online.
						dz.log( dz.data.cw_websites[dz.data.cw_rowCount].name .. ' is online.', dz.LOG_DEBUG )
							-- Add site status to message to send notification.
						dz.data.cw_notificationText = dz.data.cw_notificationText .. string.format( '<a href="' .. dz.data.cw_websites[dz.data.cw_rowCount].url .. '" target="_blank">' .. cw_notificationMessage, dz.data.cw_websites[dz.data.cw_rowCount].name .. '</a>', '<span style="color: green">Online</span>' ) .. '<br>'

						-- If this site was not Online before, then set online to true.
						if dz.data.cw_websites[dz.data.cw_rowCount].online ~= true then
							--Set online status to true
							dz.data.cw_websites[dz.data.cw_rowCount].online = true
							--Mark for notification because of status change.
							dz.data.cw_notificationTosend = true
						end
						-- reset the retry counter.
						dz.data.cw_retry = 0
					else
						-- Site is offline, or unexpected HTTP code.
						if dz.data.cw_retry < cw_maxRetries then
							--Seems offline. Give it a next try.
							dz.log( 'No HTTP 200 response from ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )

							dz.data.cw_retry = dz.data.cw_retry + 1
							dz.log( 'Retry ' .. dz.data.cw_retry .. ' for ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
							isWebsiteOnline( dz.data.cw_websites[dz.data.cw_rowCount].url )
							--End script and wait for the isShellCommandResponse.
							return
						else
							-- Also the retry is offline. Give up.
							dz.data.cw_offlineCount = dz.data.cw_offlineCount + 1

							dz.log( dz.data.cw_websites[dz.data.cw_rowCount].name .. ' is offline!', dz.LOG_DEBUG )
							-- Add site status to message to send notification.
							dz.data.cw_notificationText = dz.data.cw_notificationText .. string.format( '<a href="' .. dz.data.cw_websites[dz.data.cw_rowCount].url .. '" target="_blank">' .. cw_notificationMessage, dz.data.cw_websites[dz.data.cw_rowCount].name .. '</a>', '<span style="color: red">Offline</span>' ) .. '<br>'

							if dz.data.cw_offlineCount <= cw_maxalertLines then
								--Also add site status for the device text.
								dz.data.cw_alertText = dz.data.cw_alertText .. string.format( cw_notificationMessage, dz.data.cw_websites[dz.data.cw_rowCount].name, 'Offline' ) .. '<br>'
							end

							-- If this site was not Offline before, then set online to false
							if dz.data.cw_websites[dz.data.cw_rowCount].online ~= false then
								--Set online status to false.
								dz.data.cw_websites[dz.data.cw_rowCount].online = false
							--Mark for notification because of status change.
								dz.data.cw_notificationTosend = true
							end
						end
					end

					if dz.data.cw_rowCount < cw_tableMaxRow then
						-- Go for the next website.
						dz.data.cw_retry = 0
						dz.data.cw_rowCount = dz.data.cw_rowCount + 1
						dz.log( 'Checking ' .. dz.data.cw_websites[dz.data.cw_rowCount].name, dz.LOG_DEBUG )
						isWebsiteOnline( dz.data.cw_websites[dz.data.cw_rowCount].url )
						--End script and wait for the isShellCommandResponse.
						return
					else
						--We are done looping the websites. Now check results.
						if dz.data.cw_offlineCount > 0 then
							cw_alertLevel = dz.ALERTLEVEL_RED
							if dz.data.cw_notificationTosend == true then
								dz.email( cw_notificationSubject, dz.data.cw_notificationText, cw_emailTo, 0 )
							end
						else
							dz.data.cw_alertText = 'Alle website zijn online.'
							cw_alertLevel = dz.ALERTLEVEL_GREEN
							if dz.data.cw_notificationTosend == true then
								dz.email( cw_notificationSubject, dz.data.cw_notificationText, cw_emailTo, 0 )
							end
						end
						if dz.data.cw_alertText ~= cw_lastalertText then
							-- Text changed, so update the device.
							dz.devices(cw_alertIdx).updateAlertSensor( cw_alertLevel, dz.data.cw_alertText )
						end
					end
				end
			end
		end
	end
}
-- That's All --------------------------------------------------
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 1 guest