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