Problemy z bazą danych i samym domoticz, przy złym zasilaniu czy kiepskiej jakości kartach to zmora, warto więc na bieżąco kontrolować bazę i stan serwera .
Poniżej skrypt, który działa u mnie już dość długo i przy jakimkolwiek problemie z bazą danych wysyła mi powiadomienie. Nie naprawi to bazy ale pozwoli szybko zareagować.
Skrypt nie jest mojego autorstwa a jedynie go odrobinę dopasowałem do swoich potrzeb i ważne komentarze zmieniłem na rodzimy język.
Do działania skryptu trzeba sobie w domoticz utworzyć czujnik typu "Alert" i nazwać "Baza danych" , lub jeśli nazwiecie inaczej to zmienić to w skrypcie.
W samym skrypcie trzeba odkomentować rodzaj powiadomień i ewentualnie wpisać prawidłowy adres email . W tym przykładzie powiadomienie przychodzi na telegram skonfigurowany w domoticzu.
return {
on = {
timer = {
"at 01:00", -- ustaw godziny jakie chcesz
"at 09:00",
"at 19:00",
},
},
logging = {
level = domoticz.LOG_DEBUG, -- zmień na LOG_ERROR, jak skrypt będzie OK
marker = " Sprawdzanie DB domoticz"
},
execute = function(dz)
-- ======================= USTAWIENIA =================
local email = false -- jak nie chcesz poczty email to ustaw false
local notify = true -- jak nie chcesz powiadomien ustaw na false
local afterSuccessCommand = false
local afterFailCommand = false
local followUpAfterFail = false
local alert = {
active = true, -- set to false if you don't want an Alert device set.
device = "Baza danych", -- Nazwa czujnika alert w domoticz
failText = "Problem z bazą",
OKText = "Baza danych OK",
}
local subject = "Domoticz db check" -- Dowolny tekst
local emailaddress = "twójmail@gmail.com" -- Twój Email
local path = "/home/pi/domoticz/" -- pełna ściezka do bazy danych , w malinie nic nie zmieniac
local database = "domoticz.db" -- database filename + extension
-- local database = "corrupt.db" -- test database filename + extension
-- you can corrupt a test database by just load it in an editor
-- and remove a couple of bytes
local sqlite = "/usr/bin/sqlite3" -- location of your sqlite3 tool (use the command 'which sqlite3' to find location)
local myNotificationTable = {
-- table with one or more notification systems.
-- uncomment the notification systems that you want to be used
-- Can be one or more of
-- dz.NSS_GOOGLE_CLOUD_MESSAGING,
-- dz.NSS_HTTP,
-- dz.NSS_KODI,
-- dz.NSS_LOGITECH_MEDIASERVER,
-- dz.NSS_NMA,
-- dz.NSS_PROWL,
-- dz.NSS_PUSHALOT,
-- dz.NSS_PUSHBULLET,
-- dz.NSS_PUSHOVER,
-- dz.NSS_PUSHSAFER,
dz.NSS_TELEGRAM,
}
-- ======================= Nie zmieniaj nic ponizej ==================
local function logWrite(str,level) -- Support function for shorthand debug log statements
dz.log(tostring(str),level or dz.LOG_DEBUG)
end
local space = " "
local baseCommand = "sudo" .. space .. sqlite .. space .. path .. database .. space
local checks = {}
checks = {
"\'select count(id) from deviceStatus;\'",
"\'.schema\'",
"\'pragma integrity_check;\'",
"\'pragma foreign_key_check;\'",
}
local function rc2Text(rc)
local errorMessages = {
[0] = "baza domoticz OK",
[1] = "Generic error",
[2] = "Internal logic error in SQLite",
[3] = "Access permission denied",
[4] = "Callback routine requested an abort",
[5] = "The database file is locked",
[6] = "A table in the database is locked",
[7] = "memory allocation failed",
[8] = "Attempt to write a readonly database",
[9] = "Operation terminated by sqlite3_interrupt",
[10] = "Some kind of disk I/O error occurred",
[11] = "The database disk image is malformed",
[12] = "Unknown opcode in sqlite3_file_control",
[13] = "Insertion failed because database is full",
[14] = "Unable to open the database file",
[15] = "Database lock protocol error",
[16] = "Internal use only",
[17] = "The database schema changed",
[18] = "String or BLOB exceeds size limit",
[19] = "Abort due to constraint violation",
[20] = "Data type mismatch",
[21] = "Library used incorrectly",
[22] = "Uses OS features not supported on host",
[23] = "Authorization denied",
[24] = "Not used",
[25] = "2nd parameter to sqlite3_bind out of range",
[26] = "File opened that is not a database file",
}
return(errorMessages[rc] or "Unknown error")
end
local function followUp(cmd)
os.execute('sudo ' .. cmd ..' &')
end
local function osExecute(base,check)
local fileHandle = assert(io.popen(base .. check, 'r'))
local commandOutput = assert(fileHandle:read('*a'))
local returnTable = {fileHandle:close()}
check = check:gsub("'","") .." result ==>> " .. ( returnTable[3] ~= 0 and "Failed: " .. rc2Text(returnTable[3]) .. commandOutput .. " (".. returnTable[3] .. ")" or true and "OK" )
logWrite("Command " .. check )
return check,returnTable[3] -- rc[3] contains returnCode
end
local function checkDatabase()
if dz.utils.fileExists(path .. database) then
if dz.utils.fileExists(sqlite) then
for _,check in ipairs (checks) do
local result,rc = osExecute(baseCommand,check)
if rc ~= 0 then
return rc, result
end
end
else
return -1,"sqlite3 not installed"
end
else
return -1,"wrong path to database"
end
return 0
end
local function updateAlert(rc)
if alert and alert.active then
local now = dz.time.rawDate .. ', ' .. dz.time.rawTime .. ': '
local alertLevel = dz.ALERTLEVEL_RED
if rc == 0 then alertLevel = dz.ALERTLEVEL_GREEN end
dz.devices(alert.device).updateAlertSensor(alertLevel, now .. rc2Text(rc))
end
end
-- main program
local rc, result = checkDatabase()
if rc ~= 0 then
logWrite(result,dz.LOG_ERROR)
if email then dz.email(subject,result,emailaddress) end
if notify then
dz.notify(subject, result or "Sprawdzanie bazy danych napotkało nieznany błąd", dz.PRIORITY_NORMAL, dz.SOUND_INTERMISSION,"", myNotificationTable )
end
if afterFailCommand and ( rc > 0 ) then followUp(afterFailCommand) end
else
if afterSuccessCommand then followUp(afterSuccessCommand) end
end
updateAlert(rc)
end
}
Drugi skrypt sprawdza kondycję maliny na podstawie jej wewnętrznych czujników i co dwie minuty aktualizuje identyczny czujnik "Alert" . Jak coś się dzieje z maliną np napięcie zasilania jest za niskie, alert zmieni się na czerwono z odpowiednim opisem
W tym skrypcie wystarczy wpisać IDX utworzonego czujnika "ALERT" z dowolną nazwą np Kondycja Maliny.
return {
on = {
timer = { 'every 2 minutes' }
},
logging = {level = domoticz.LOG_DEBUG, -- zmien na LOG_ERROR, jak skrypt będzie OK
marker = "Kondycja RPI"
},
execute = function(dz, item )
--Flag Bits
local UNDERVOLTED=0x1
local CAPPED=0x2
local THROTTLED=0x4
local SOFT_TEMPLIMIT=0x8
local HAS_UNDERVOLTED=0x10000 --
local HAS_CAPPED=0x20000
local HAS_THROTTLED=0x40000
local HAS_THROTTLED_RB=0x50000
local UNDERVOLTED_THROTTLED=0x50005
local HAS_SOFT_TEMPLIMIT=0x80000
local Alertidx = 560 -- Tu wpisz IDX swojego czujnika "Alert"
local function GetRpiSensor()
local command = 'vcgencmd get_throttled'
--dz.log(command,dz.LOG_INFO)
local handle = assert(io.popen(command))
for line in handle:lines() do
findsensor=line
end
handle:close()
return findsensor
end
-- Start main script
local RpiSensorvalue= GetRpiSensor()
local splittedResult = dz.utils.stringSplit(RpiSensorvalue,'=') -- split string into (table) parts with , as separator
local RPIhex = tonumber(splittedResult[2])
local AlertL = dz.ALERTLEVEL_GREEN
local AlertT = ''
if ( RPIhex > (HAS_SOFT_TEMPLIMIT-1) ) then
RPIhex = RPIhex -HAS_SOFT_TEMPLIMIT
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi HAS Soft TempLimit'
end
if ( RPIhex > (UNDERVOLTED_THROTTLED-1) ) then
RPIhex = RPIhex -UNDERVOLTED_THROTTLED
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi currently under-voltage and throttled'
end
if ( RPIhex > (HAS_THROTTLED_RB-1) ) then
RPIhex = RPIhex -HAS_THROTTLED_RB
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi throttled occurred since last reboot'
end
if ( RPIhex > (HAS_THROTTLED-1) ) then
RPIhex = RPIhex -HAS_THROTTLED
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi HAS Throttled'
end
if ( RPIhex > (HAS_CAPPED-1) ) then
RPIhex = RPIhex -HAS_CAPPED
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi HAS Capped'
end
if ( RPIhex > (HAS_UNDERVOLTED-1) ) then
RPIhex = RPIhex -HAS_UNDERVOLTED
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi HAS undervolted'
end
if ( RPIhex > (SOFT_TEMPLIMIT-1) ) then
RPIhex = RPIhex -8
AlertL = dz.ALERTLEVEL_RED
AlertT = 'Rpi Soft Temp Limit'
end
if ( RPIhex > (THROTTLED-1) ) then
RPIhex = RPIhex -4
AlertL = dz.ALERTLEVEL_RED
AlertT = AlertT .. ' Rpi Throttled'
end
if ( RPIhex > (CAPPED-1) ) then
RPIhex = RPIhex -2
AlertL = dz.ALERTLEVEL_RED
AlertT = AlertT .. ' RPI Ograniczone'
end
if ( RPIhex > (UNDERVOLTED-1) ) then
AlertL = dz.ALERTLEVEL_RED
AlertT = AlertT .. ' RPI za niskie napięcie'
end
if ( AlertT == '') then
AlertT = 'RPI działa OK'
end
-- Set the Alert Sensor
dz.devices(Alertidx).updateAlertSensor(AlertL, AlertT)
end
}
A tak wyglądają czujniki

