Page 1 sur 8

[LUA] Bibliothèque de fonctions

Publié : 21 avr. 2017, 12:05
par vil1driver
Bonjour,

lorsque l'on est amené à écrire des scripts pour automatiser telle ou telle tâche,
nous avons souvent recours aux même fonctions usuelles..

depuis quand un switch à-t-il été activé,
obtenir l'heure ou la date,
arrondir un nombre,
écrire en couleur dans le journal,
etc..

du coups je passais mon temps à rechercher dans quel script j'avais bien pu utiliser une fonction ou une autre
pour aller la recopier dans mon nouveau script.

c'était fastidieux..

c'est alors que l'idée m'est venue de tout rassembler/centraliser dans un seul et unique fichier
puis appeler ce fichier en début de mes scripts pour avoir simplement et instantanément accès à l'ensemble des fonctions.

c'est simple, efficace et allège la lecture des scripts
de plus si jamais une fonction nécessite une mise à jour, la modification ne se fait q'une fois et profite à l'ensemble des scripts.

j'ai nommé ce fichier bibliothèque "modules.lua" (lien dans ma signature)
je l'inclue dans mes scripts comme ceci:

Code : Tout sélectionner

dofile('/home/pi/domoticz/scripts/lua/modules.lua')
bien sure le chemin est à adapter à votre installation..

si vous utilisez d'autres fonctions bien utiles, n’hésitez pas à partager ;)

Edit Keros : modules.lua au 25/07/2021

Code : Tout sélectionner

--[[
bibliothèque de fonctions pour domoticz
utiles à la réalisation de scripts d'automation en langage lua
/!\ certaines fonctions ne fonctionneront pas sous windows.
copier ce qui se trouve entre les 2 lignes ci dessous, en début de tout vos script
pour charger ce fichier et pouvoir en utiliser les fonctions
--------------------------------------------------------------------------------------------------------
-- chargement des modules (http://easydomoticz.com/forum/viewtopic.php?f=17&t=3940)
dofile('/home/pi/domoticz/scripts/lua/modules.lua')
local debug = true  -- true pour voir les logs dans la console log Dz ou false pour ne pas les voir
--------------------------------------------------------------------------------------------------------
]]


--------------------------------
------ 	  USER SETTINGS	  ------
--------------------------------

-- domoticz
domoticzIP = '192.168.22.100'	--'127.0.0.1'
domoticzPORT = '8080'
domoticzUSER = ''		-- nom d'utilisateur
domoticzPSWD = ''		-- mot de pass
domoticzPASSCODE = ''	-- pour interrupteur protégés
domoticzURL = 'http://'..domoticzIP..':'..domoticzPORT



--------------------------------
------         END        ------
--------------------------------


-- chemin vers le dossier lua et curl
if (package.config:sub(1,1) == '/') then
	-- system linux
	luaDir = debug.getinfo(1).source:match("@?(.*/)")
	curl = '/usr/bin/curl -m 15 '		 							-- ne pas oublier l'espace à la fin
else
	-- system windows
	luaDir = string.gsub(debug.getinfo(1).source:match("@?(.*\\)"),'\\','\\\\')
	-- download curl : https://bintray.com/vszakats/generic/download_file?file_path=curl-7.54.0-win32-mingw.7z
	curl = 'c:\\Programs\\Curl\\curl.exe '		 					-- ne pas oublier l'espace à la fin
end

-- chargement du fichier JSON.lua
json = assert(loadfile(luaDir..'JSON.lua'))()

--time.hour ou time.min ou time.sec
--ex : if (time.hour == 17 and time.min == 05) then
time = os.date("*t")

-- retourne l'heure actuelle ex: "12:45"
heure = string.sub(os.date("%X"), 1, 5)

-- retourne la date ex: "01:01"
date = os.date("%d:%m")

-- retourne l'heure du lever de soleil ex: "06:41"
leverSoleil = string.sub(os.date("!%X",60*timeofday['SunriseInMinutes']), 1, 5)

-- retourne l'heure du coucher de soleil ex: "22:15"
coucherSoleil = string.sub(os.date("!%X",60*timeofday['SunsetInMinutes']), 1, 5)

-- retourne le jour actuel en français ex: "mardi"
days = {"dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi"}
jour = days[(os.date("%w")+1)]

-- retourne VRAI si la semaine est paire
-- usage :
-- if semainePaire() then ..
function semainePaire()
	local tm = os.time()
	local function getYearBeginDayOfWeek()
		yearBegin = os.time{year=os.date("*t",tm).year,month=1,day=1}
		yearBeginDayOfWeek = tonumber(os.date("%w",yearBegin))
		-- sunday correct from 0 -> 7
		if(yearBeginDayOfWeek == 0) then yearBeginDayOfWeek = 7 end
		return yearBeginDayOfWeek
	end
	local function getDayAdd()
		yearBeginDayOfWeek = getYearBeginDayOfWeek(tm)
		if(yearBeginDayOfWeek < 5 ) then
			-- first day is week 1
			dayAdd = (yearBeginDayOfWeek - 2)
		else 
			-- first day is week 52 or 53
			dayAdd = (yearBeginDayOfWeek - 9)
		end  
		return dayAdd
	end
	dayOfYear = os.date("%j",tm)
	dayAdd = getDayAdd(tm)
	dayOfYearCorrected = dayOfYear + dayAdd
	if(dayOfYearCorrected < 0) then
		-- week of last year - decide if 52 or 53
		lastYearBegin = os.time{year=os.date("*t",tm).year-1,month=1,day=1}
		lastYearEnd = os.time{year=os.date("*t",tm).year-1,month=12,day=31}
		dayAdd = getDayAdd(lastYearBegin)
		dayOfYear = dayOfYear + os.date("%j",lastYearEnd)
		dayOfYearCorrected = dayOfYear + dayAdd
	end  
	weekNum = math.floor((dayOfYearCorrected) / 7) + 1
	if( (dayOfYearCorrected > 0) and weekNum == 53) then
		-- check if it is not considered as part of week 1 of next year
		nextYearBegin = os.time{year=os.date("*t",tm).year+1,month=1,day=1}
		yearBeginDayOfWeek = getYearBeginDayOfWeek(nextYearBegin)
		if(yearBeginDayOfWeek < 5 ) then
			weekNum = 1
		end  
	end
	return weekNum%2 == 0
end


-- il fait jour
dayTime = timeofday['Daytime']
-- il fait nuit
nightTime = timeofday['Nighttime']

-- température
function getTemp(device)
	return round(tonumber(otherdevices_temperature[device]),1)
end

-- humidité
function getHum(device)
	return round(tonumber(otherdevices_humidity[device]),1)
end

-- humidité moyenne
function humMoy(device)
	local monthLog = assert(io.popen(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..'/json.htm?range=month&sensor=temp&type=graph&idx='..otherdevices_idx[device]..'"'))
	local list = monthLog:read('*all')
	monthLog:close()
	local data = ReverseTable(json:decode(list).result)
	return(round(data[1].hu))
end

-- humidité absolue
function humAbs(t,hr)
-- https://carnotcycle.wordpress.com/2012/08/04/how-to-convert-relative-humidity-to-absolute-humidity/
-- Formule pour calculer l'humidité absolue
-- Dans la formule ci-dessous, la température (T) est exprimée en degrés Celsius, l'humidité relative (hr) est exprimée en%, et e est la base des logarithmes naturels 2.71828 [élevée à la puissance du contenu des crochets]:
-- Humidité absolue (grammes / m3 ) =  (6,122 * e^[(17,67 * T) / (T + 243,5)] * rh * 2,1674))/(273,15 + T)
-- Cette formule est précise à 0,1% près, dans la gamme de température de -30 ° C à + 35 ° C
	return round((6.112 * math.exp((17.67 * t)/(t+243.5)) * hr * 2.1674)/ (273.15 + t),1)
end

-- set setpoint (faster way)
function setPoint(device,value)
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..'/json.htm?type=command&param=udevice&idx='..otherdevices_idx[device]..'&nvalue=0&svalue='..value..'" &')
end

function dimUp15(device)
	-- 15 step
	switchOn(device, constrain(otherdevices_svalues[device]+1,1,15))
end

function dimDown15(device)
	-- 15 step
	switchOn(device, constrain(otherdevices_svalues[device]-1,1,15))
end

function dimUp(device)
	-- 100 step
	switchOn(device, constrain(otherdevices_svalues[device]+10,10,100))
end

function dimDown(device)
	-- 100 step
	switchOn(device, constrain(otherdevices_svalues[device]-10,10,100))
end

-- vérifie s'il y a eu changement d'état
function stateChange(device)
	if (uservariables['lastState_'..device] == nil) then
		creaVar('lastState_'..device,otherdevices[device])
		log('stateChange : création variable manquante lastState_'..device,debug)
		return false
	elseif (devicechanged[device] == nil) then
		return false
	elseif (devicechanged[device] == uservariables['lastState_'..device]) then
		return false
	else
		duree = lastSeen(uservariables_lastupdate['lastState_'..device])
		updateVar('lastState_'..device,otherdevices[device])
		return otherdevices[device]
	end
end	

-- convertion degrés en direction cardinale
function wind_cardinals(deg)
	local cardinalDirections = {
		['N'] = {348.75, 360},
		['N'] = {0, 11.25},
		['NNE'] = {11.25, 33.75},
		['NE'] = {33.75, 56.25},
		['ENE'] = {56.25, 78.75},
		['E'] = {78.75, 101.25},
		['ESE'] = {101.25, 123.75},
		['SE'] = {123.75, 146.25},
		['SSE'] = {146.25, 168.75},
		['S'] = {168.75, 191.25},
		['SSW'] = {191.25, 213.75},
		['SW'] = {213.75, 236.25},
		['WSW'] = {236.25, 258.75},
		['W'] = {258.75, 281.25},
		['WNW'] = {281.25, 303.75},
		['NW'] = {303.75, 326.25},
		['NNW'] = {326.25, 348.75}
		}
	local cardinal
	for dir, angle in pairs(cardinalDirections) do
		if (deg >= angle[1] and deg < angle[2]) then
			cardinal = dir
			break
		end	
	end
	return cardinal
end
	
-- dump all variables supplied to the script
-- usage
-- LogVariables(_G,0,'')
function LogVariables(x,depth,name)
    for k,v in pairs(x) do
        if (depth>0) or ((string.find(k,'device')~=nil) or (string.find(k,'variable')~=nil) or 
                         (string.sub(k,1,4)=='time') or (string.sub(k,1,8)=='security')) then
            if type(v)=="string" then print(name.."['"..k.."'] = '"..v.."'") end
            if type(v)=="number" then print(name.."['"..k.."'] = "..v) end
            if type(v)=="boolean" then print(name.."['"..k.."'] = "..tostring(v)) end
            if type(v)=="table" then LogVariables(v,depth+1,k); end
        end
    end
end

-- os.execute() output or web page content return
-- usage
-- local resultat = os.capture(cmd , true)
-- print('resultat: ' .. resultat)
function os.capture(cmd, raw)
  local f = assert(io.popen(cmd, 'r'))
  local s = assert(f:read('*a'))
  f:close()
  if raw then return s end
  s = string.gsub(s, '^%s+', '')
  s = string.gsub(s, '%s+$', '')
  s = string.gsub(s, '[\n\r]+', ' ')
  return s
end

-- retourne le type de la variable
-- 'string' , 'number' , 'table'
function typeof(var)
    local _type = type(var);
    if(_type ~= "table" and _type ~= "userdata") then
        return _type;
    end
    local _meta = getmetatable(var);
    if(_meta ~= nil and _meta._NAME ~= nil) then
        return _meta._NAME;
    else
        return _type;
    end
end

-- affiche les logs en bleu sauf si debug est spécifié à false
function log(txt,debug)
    if (debug ~= false) then
        --print("<font color='#0206a9'>"..txt.."</font>")
        print(txt)
    end
end  

-- affiche les logs en rouge sauf si debug est spécifié à false
function warn(txt,debug)
    if (debug ~= false) then
        --print("<font color='red'>"..txt.."</font>")
        print(txt)
    end
end

-- écriture dans un fichier texte dans le dossier lua
function logToFile(fileName,data)
	f = assert(io.open(luaDir..fileName..'.txt',"a"))
	f:write(os.date("%c")..' '..data..'\n')
	f:close()
end  

-- teste l'existance d'un fichier
function file_exists(file)
     local f = io.open(file, "rb")
     if f then f:close() end
     return f ~= nil
end

-- retourne le nom du switch selon son IDX
function getDeviceName(deviceIDX)
   for i, v in pairs(otherdevices_idx) do
      if v == deviceIDX then
         return i
      end
   end
   return 0
end

-- get all lines from a file, returns an empty 
-- list/table if the file does not exist
function lines_from(file)
  if not file_exists(luaDir..file..'.txt') then return {} end
  lines = {}
  for line in io.lines(luaDir..file..'.txt') do 
    lines[#lines + 1] = line
  end
  return lines
end
   
-- encode du texte pour le passer dans une url
function url_encode(str)
  if (str) then
    str = string.gsub (str, "\n", "\r\n")
    str = string.gsub (str, "([^%w %-%_%.%~])",
        function (c) return string.format ("%%%02X", string.byte(c)) end)
    str = string.gsub (str, " ", "+")
  end
  return str	
end

-- supprime les accents de la chaîne
function sans_accent(str)
    if (str) then
		str = string.gsub (str,"Ç", "C")
		str = string.gsub (str,"ç", "c")
		str = string.gsub (str,"[-èéêë']+", "e")
		str = string.gsub (str,"[-ÈÉÊË']+", "E")
		str = string.gsub (str,"[-àáâãäå']+", "a")
		str = string.gsub (str,"[-@ÀÁÂÃÄÅ']+", "A")
		str = string.gsub (str,"[-ìíîï']+", "i")
		str = string.gsub (str,"[-ÌÍÎÏ']+", "I")
		str = string.gsub (str,"[-ðòóôõö']+", "o")
		str = string.gsub (str,"[-ÒÓÔÕÖ']+", "O")
		str = string.gsub (str,"[-ùúûü']+", "u")
		str = string.gsub (str,"[-ÙÚÛÜ']+", "U")
		str = string.gsub (str,"[-ýÿ']+", "y")
		str = string.gsub (str,"Ý", "Y")
    end
    return str
end

-- retourne le temps en seconde depuis la dernière maj du péréphérique
function lastSeen(device)
  timestamp = otherdevices_lastupdate[device] or device
  y, m, d, H, M, S = timestamp:match("(%d+)-(%d+)-(%d+) (%d+):(%d+):(%d+)")
  difference = os.difftime(os.time(), os.time{year=y, month=m, day=d, hour=H, min=M, sec=S})
  return difference
end

-- contraindre
function constrain(x, a, b)
	if (x < a) then
		return a
	elseif (x > b) then
		return b
	else
		return x
	end
end

-- arrondire
function round(num, dec)
   if num == 0 then
	 return 0
   else
	 local mult = 10^(dec or 0)
	 return math.floor(num * mult + 0.5) / mult
   end
end

-- met le script en pause (fortement déconseillé)
-- usage
-- sleep(10) -- pour mettre en pause 10 secondes
function sleep(n)
  os.execute('sleep '..n)
end

-- création de variable utilisateur
-- usage
-- creaVar('toto','10') -- pour créer une variable nommée toto comprenant la valeur 10
function creaVar(name,value)
	local api = '/json.htm?type=command&param=adduservariable'
	local name = '&vname='..url_encode(name)
	local vtype = '&vtype=2'
	local value = '&vvalue='..url_encode(value)
	api = api..name..vtype..value
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- update an existing variable
function updateVar(name,value)
	local api = '/json.htm?type=command&param=updateuservariable'
	local name = '&vname='..url_encode(name)
	local vtype = '&vtype=2'
	local value = '&vvalue='..url_encode(value)
	api = api..name..vtype..value
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- envoie dans un capteur text une chaîne de caractères
-- le text sera intercepté et lu par la custom page grâce à sa fonction MQTT
-- usage
-- speak('tts','bonjour nous sommes dimanche')
function speak(TTSDeviceName,txt)
	commandArray[#commandArray+1] = {['OpenURL'] = domoticzIP..":"..domoticzPORT..'/json.htm?type=command&param=udevice&idx='..otherdevices_idx[TTSDeviceName]..'&nvalue=0&svalue='..url_encode(txt)}
end

-- récupère les infos json du périphérique
-- usage
-- local lampe = jsonInfos('ma lampe')
-- print(lampe.Name)
-- print(lampe.Status)
-- etc..
function jsonInfos(device)
	local rid = assert(io.popen(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..'/json.htm?type=devices&rid='..otherdevices_idx[device]..'"'))
	local list = rid:read('*all')
	rid:close()
	return json:decode(list).result[1]
end

-- parcours la table dans l'ordre
function spairs(t)
    local keys = {}
    for k in pairs(t) do keys[#keys+1] = k end
	table.sort(keys)
	local i = 0
	return function()
		i = i + 1
		if keys[i] then
			return keys[i], t[keys[i]]
		end
	end
end

-- Renverse une table
function ReverseTable(t)
    local reversedTable = {}
    local itemCount = #t
    for k, v in ipairs(t) do
        reversedTable[itemCount + 1 - k] = v
    end
    return reversedTable
end

-- affiche le contenu d'une table
--[[  
   Author: Julio Manuel Fernandez-Diaz
   Date:   January 12, 2007
   (For Lua 5.1)
   
   Modified slightly by RiciLake to avoid the unnecessary table traversal in tablecount()
   Formats tables with cycles recursively to any depth.
   The output is returned as a string.
   References to other tables are shown as values.
   Self references are indicated.
   The string returned is "Lua code", which can be procesed
   (in the case in which indent is composed by spaces or "--").
   Userdata and function keys and values are shown as strings,
   which logically are exactly not equivalent to the original code.
   This routine can serve for pretty formating tables with
   proper indentations, apart from printing them:
      print(table_show(t, "t"))   -- a typical use
   
   Heavily based on "Saving tables with cycles", PIL2, p. 113.
   Arguments:
      t is the table.
      name is the name of the table (optional)
      indent is a first indentation (optional).
]]
function table_show(t, name, indent)
   local cart     -- a container
   local autoref  -- for self references

   --[[ counts the number of elements in a table
   local function tablecount(t)
      local n = 0
      for _, _ in pairs(t) do n = n+1 end
      return n
   end
   ]]
   -- (RiciLake) returns true if the table is empty
   local function isemptytable(t) return next(t) == nil end

   local function basicSerialize (o)
      local so = tostring(o)
      if type(o) == "function" then
         local info = debug.getinfo(o, "S")
         -- info.name is nil because o is not a calling level
         if info.what == "C" then
            return string.format("%q", so .. ", C function")
         else 
            -- the information is defined through lines
            return string.format("%q", so .. ", defined in (" ..
                info.linedefined .. "-" .. info.lastlinedefined ..
                ")" .. info.source)
         end
      elseif type(o) == "number" or type(o) == "boolean" then
         return so
      else
         return string.format("%q", so)
      end
   end

   local function addtocart (value, name, indent, saved, field)
      indent = indent or ""
      saved = saved or {}
      field = field or name

      cart = cart .. indent .. field

      if type(value) ~= "table" then
         cart = cart .. " = " .. basicSerialize(value) .. ";\n"
      else
         if saved[value] then
            cart = cart .. " = {}; -- " .. saved[value] 
                        .. " (self reference)\n"
            autoref = autoref ..  name .. " = " .. saved[value] .. ";\n"
         else
            saved[value] = name
            --if tablecount(value) == 0 then
            if isemptytable(value) then
               cart = cart .. " = {};\n"
            else
               cart = cart .. " = {\n"
               for k, v in pairs(value) do
                  k = basicSerialize(k)
                  local fname = string.format("%s[%s]", name, k)
                  field = string.format("[%s]", k)
                  -- three spaces between levels
                  addtocart(v, fname, indent .. "   ", saved, field)
               end
               cart = cart .. indent .. "};\n"
            end
         end
      end
   end

   name = name or "table"
   if type(t) ~= "table" then
      return name .. " = " .. basicSerialize(t)
   end
   cart, autoref = "", ""
   addtocart(t, name, indent)
   return cart .. autoref
end

-- retourne la table des derniers log (première ligne = dernier log)
function lastLogEntry()
	local rid = assert(io.popen(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..'/json.htm?type=command&param=getlog"'))
	local list = rid:read('*all')
	rid:close()
	local tableau = json:decode(list).result
	return ReverseTable(tableau)
end

-- notification pushbullet
-- usage:
-- pushbullet('test','ceci est un message test')
function pushbullet(title,body)
	local settings = assert(io.popen(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..'/json.htm?type=settings"'))
	local list = settings:read('*all')
	settings:close()
	local pushbullet_key = json:decode(list).PushbulletAPI
	os.execute(curl..'-H \'Access-Token:'..pushbullet_key..'\' -H \'Content-Type:application/json\' --data-binary \'{"title":"'..title..'","body":"'..body..'","type":"note"}\' -X POST "https://api.pushbullet.com/v2/pushes"')
end

-- switch On a device and set level if dimmmable
function switchOn(device,level)
	local api = '/json.htm?type=command&param=switchlight'
	local idx = '&idx='..otherdevices_idx[device]
	local cmd
	if level ~= nil then 
		cmd = '&switchcmd=Set%20Level&level='..level
	else
		cmd = '&switchcmd=On'
	end
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..cmd..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- switch On a devive for x secondes 
function switchOnFor(device, secs)
   switchOn(device)
   commandArray[#commandArray+1] = {[device] = "Off AFTER "..secs}
end

-- switch Off a device
function switchOff(device)
	local api = '/json.htm?type=command&param=switchlight'
	local idx = '&idx='..otherdevices_idx[device]
	local cmd = '&switchcmd=Off'
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..cmd..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- Toggle a device
function switch(device)
	local api = '/json.htm?type=command&param=switchlight'
	local idx = '&idx='..otherdevices_idx[device]
	local cmd = '&switchcmd=Toggle'
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..cmd..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- switch On a group or scene
function groupOn(device)
	local api = '/json.htm?type=command&param=switchscene'
	local idx = '&idx='..otherdevices_scenesgroups_idx[device]
	local cmd = '&switchcmd=On'
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..cmd..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- switch Off a group
function groupOff(device)
	local api = '/json.htm?type=command&param=switchscene'
	local idx = '&idx='..otherdevices_scenesgroups_idx[device]
	local cmd = '&switchcmd=Off'
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..cmd..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

-- Set switch to Stop
function switchStop(device)
	local api = '/json.htm?type=command&param=switchlight'
	local idx = '&idx='..otherdevices_idx[device]
	local cmd = '&switchcmd=Stop'
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..cmd..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end
 
-- Setup a color & brightness of an RGB(W) light
-- API : https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Set_an_RGB.28W.29_light_to_a_certain_color_and_brightness
function setColorAndBrightness(device, color, brightness)
	local api = '/json.htm?type=command&param=setcolbrightnessvalue'
	local idx = '&idx='..otherdevices_idx[device]
	--local color = '&hue='..color
	local color = '&hex='..color
	local brightness = '&brightness='..brightness
	local iswhite = '&iswhite=false'
	local passcode = '&passcode='..domoticzPASSCODE
	api = api..idx..color..brightness..iswhite..passcode
	os.execute(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..api..'" &')
end

function KelvinToRGB(temp)
	-- http://www.tannerhelland.com/4435/convert-temperature-rgb-algorithm-code/
    temp = temp/100
    local red, green, blue
	--Calculate Red:
	if temp <= 66 then
        red = 255
    else
        red = constrain(round(329.698727446 * ((temp - 60) ^ -0.1332047592)),0,255)
	end
    --Calculate Green:
	if temp <= 66 then
		green = constrain(round(99.4708025861 * math.log(temp) - 161.1195681661),0,255)
    else
		green = constrain(round(288.1221695283 * ((temp - 60) ^ -0.0755148492)),0,255)
    end
    --Calculate Blue:
	if temp >= 66 then
        blue = 255
    else
		if temp <= 19 then
            blue = 0
        else
			blue = constrain(round(138.5177312231 * math.log(temp - 10) - 305.0447927307),0,255)
		end
	end
	return {red,green,blue}
end

function RGBToHex(rgb)
	-- https://gist.github.com/marceloCodget/3862929
	local hexadecimal = ''
	for key, value in pairs(rgb) do
		local hex = ''
		while(value > 0)do
			local index = math.fmod(value, 16) + 1
			value = math.floor(value / 16)
			hex = string.sub('0123456789ABCDEF', index, index) .. hex			
		end
		if(string.len(hex) == 0)then
			hex = '00'
		elseif(string.len(hex) == 1)then
			hex = '0' .. hex
		end
		hexadecimal = hexadecimal .. hex
	end
	return hexadecimal
end

function suntimeToKelvin()
	-- http://easydomoticz.com/forum/viewtopic.php?f=10&t=6160
	local mini = 1900
	local maxi = 6600
	local delta = maxi - mini
	local wakeup = 60*timeofday['SunriseInMinutes']
	local goodnight = 60*timeofday['SunsetInMinutes']
	local periode = goodnight - wakeup
	local offset = wakeup-periode/2
	local color = mini
	local time = os.date("*t")
	local now = 60*(time.hour*60 + time.min)
	if now >= wakeup and now < goodnight then
		color = math.floor((maxi-delta/2)+(delta/2)*math.cos((now-offset)*2*math.pi/periode)+0.5)
	end
	return color
end	

-- régulation chauffage (PID)
--[[
	usage:
	
	local pid={}
	pid['debug'] = true								-- true pour voir les logs dans la console log Dz ou false pour ne pas les voir
	pid['zone'] = 'salon'							-- nom de la zone pour affichage dans les logs et ditinction de variables
	pid['sonde'] = 'salon' 							-- Nom de la sonde de température
	pid['OnOff'] = 'chauffage' 						-- Nom de l'interrupteur virtuel de mise en route (hivers/été)
	pid['thermostat'] = 'th_salon' 					-- consigne ou 'nom' de l'interrupteur virtuel de thermostat
	-- actionneur
	pid['radiateur'] = 'radiateur salon' 			-- Nom de l'interrupteur de chauffage
	pid['invert'] = false							-- si On et Off doivent être inversé ou non
	-- PID -- 
	pid['Kp'] = 70 									-- Coefficient proportionnel 
	pid['Ki'] = 8 									-- Coefficient intégrateur
	pid['Kd'] = 3 									-- Coefficient dérivateur
	pid['cycle'] = 15								-- temps en minute d'un cycle PID
	pid['secu'] = 60								-- temps mini en seconde entre 2 ordres opposés
	
	commandArray = {} 
	compute(pid)
	return commandArray
]]
function compute(pid)
	local init = 0
	
	-- récupération température
	local temp = getTemp(pid['sonde'])
	-- récupération température ext
	local temp_ext = nil
	if pid['sonde_ext'] ~= '' and pid['sonde_ext'] ~= nil then
		temp_ext = getTemp(pid['sonde_ext'])
	end
	
	-- création variable : 4 dernières températures
	if (uservariables['PID_temps_'..pid['zone']] == nil ) then
		creaVar('PID_temps_'..pid['zone'],string.rep(temp..';',3)..temp) 
		init = 1
	end
	-- création variable : intégrale
	if (uservariables['PID_integrale_'..pid['zone']] == nil ) then
		creaVar('PID_integrale_'..pid['zone'],'0')
		init = 1
	end
	
	if init == 1 then
		log('PID '..pid['zone']..' initialisation..',pid['debug'])
		do return end
	end
	
	-- définition des variables locales
	local moy_erreur = 0
	local n = 1
	local somme_erreurs = 0
	local heatTime
	local marche
	local arret
	local tmp = {}

	-- définition des commandes marche/arrêt
	if pid['invert'] then
		marche = 'Off' ; arret = 'On'
	else
		marche = 'On' ; arret = 'Off'
	end
	
	-- à chaque cycle
	if ( time.min%pid['cycle'] == 0 ) then
	
		-- maj des 4 dernières temps
		local temps = string.match(uservariables['PID_temps_'..pid['zone']],";([^%s]+)")..";"..temp
		commandArray[#commandArray+1] = {['Variable:PID_temps_'..pid['zone']] = temps}
		
		-- si l'on veut chauffer
		if ( otherdevices[pid['OnOff']] == 'On' ) then

			-- récupération de la consigne
			local consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']
			-- calcul de l'erreur
			local erreur = consigne-temp
			-- calcul intégrale auto consumée et moyenne erreur glissante
			temps:gsub("([+-]?%d+%.*%d*)",function(t)
												tmp[n] = tonumber(t)
												err = tonumber(consigne-t)
												somme_erreurs = somme_erreurs+err
												moy_erreur = moy_erreur+err*n^3
												n = n+1
											end)

			somme_erreurs = round(constrain(somme_erreurs,0,255),1)
			moy_erreur = round(moy_erreur/100,2)
			
			-- calcul de la dérivée (régression linéaire - méthode des moindres carrés)
			local delta_erreurs = round((4*(4*tmp[1]+3*tmp[2]+2*tmp[3]+tmp[4])-10*(tmp[1]+tmp[2]+tmp[3]+tmp[4]))/20,2)
			
			-- aux abords de la consigne, passage au second systême integrale
			if math.abs(somme_erreurs) < 2 then
				somme_erreurs = tonumber(uservariables['PID_integrale_'..pid['zone']])
				-- re calcule intégrale si hors hysteresis
				-- à moins d'un dixièmes de degré d'écart avec la consigne
				-- le ratrapage est considéré OK, l'intégrale n'est pas recalculée
				if math.abs(erreur) > 0.11 then
					-- calcule intégrale
					somme_erreurs = round(constrain(somme_erreurs+erreur/2,0,5),2)
					-- maj
					commandArray[#commandArray+1] = {['Variable:PID_integrale_'..pid['zone']] = tostring(somme_erreurs)}
				end
			end
			
			-- boucle ouverte,
			-- modification dynamique des paramètres de régulation suivant température extérieure
			local Kb = 0
			if temp_ext ~= nil then
				Kb = pid['Kb'] * (consigne - temp_ext - pid['ref']) / 100
			end	
			pid['Kp'] = round(pid['Kp'] + pid['Kp'] * Kb)
			pid['Ki'] = round(pid['Ki'] + pid['Ki'] * Kb)
			pid['Kd'] = round(pid['Kd'] + pid['Kd'] * Kb)
	
			-- calcul pid
			local P = round(pid['Kp']*moy_erreur,2)
			local I = round(pid['Ki']*somme_erreurs,2)
			local D = round(pid['Kd']*delta_erreurs,2)
			
			-- calcul de la commande en %
			local commande = round(constrain(P+I+D,0,100))
					
			-- calcul du temps de fonctionnement
			if commande == 100 then
				-- débordement de 20s pour ne pas couper avant recalcule
				heatTime = (pid['cycle']*60)+20
			elseif commande > 0 then
				-- secu mini maxi
				heatTime = round(constrain(commande*pid['cycle']*0.6,pid['secu'],(pid['cycle']*60)-pid['secu']))
			elseif commande == 0 then
				-- coupure retardée
				heatTime = constrain(pid['secu']-lastSeen(pid['radiateur']),0,pid['secu'])
			end
			
			-- AFTER n'aime pas 1 ou 2..
			if heatTime == 1 or heatTime == 2 then
				heatTime = 0
			end	
			
			-- action sur l'élément chauffant
			if heatTime > 0 then
				commandArray[#commandArray+1] = {[pid['radiateur']] = marche}
				commandArray[#commandArray+1] = {[pid['radiateur']] = arret..' AFTER '..heatTime}
			else
				commandArray[#commandArray+1] = {[pid['radiateur']]=arret}
			end			
		
			-- journalisation
			if pid['debug'] then
				log('PID zone: '..string.upper(pid['zone']))
				if temp_ext ~= nil then
					log('temperature ext: '..temp_ext..'°C')
				end
				log('température int: '..temp..'°C pour '..consigne..'°C souhaité')
				log('Kp: '..pid['Kp'])
				log('Ki: '..pid['Ki'])
				log('Kd: '..pid['Kd'])
				log('erreur: '..moy_erreur)
				log('somme erreurs: '..somme_erreurs)
				log('delta erreurs: '..delta_erreurs)
				log('P: '..P)
				log('I: '..I)
				log('D: '..D)
				log('cycle: '..pid['cycle']..'min (sécu: '..pid['secu']..'s)')
				-- avertissement si secu dépasse 1/4 du cycle
				if ((100*pid['secu'])/(60*pid['cycle'])>25) then
					warn('sécu trop importante, ralonger durée de cycle..')
				end
				log('commande: '..commande..'% ('..string.sub(os.date("!%X",heatTime),4,8):gsub("%:", "\'")..'\")')
				log('')
			end
			
			-- maj sonde virtuelle
			--commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[pid['sonde']..'_pid']..'|0|'..temp..';'..commande..';0'}
			
		end
		
	end
	-- toutes les 15 minutes, si on ne veut pas chauffer
	if ( time.min%15 == 0 and otherdevices[pid['OnOff']] == 'Off' ) then

		-- arrêt chauffage (renvoi commande systematique par sécurité)
		commandArray[#commandArray+1] = {[pid['radiateur']] = arret..' AFTER '..constrain(pid['secu']-lastSeen(pid['radiateur']),3,pid['secu'])}
		
		-- maj sonde virtuelle
		--commandArray[#commandArray+1] = {['UpdateDevice'] = otherdevices_idx[pid['sonde']..'_pid']..'|0|'..temp..';0;0'}
	end

end

-- détermination automatique des paramètres de régulation PID
function autotune(pid)
	
	-- http://brettbeauregard.com/blog/2012/01/arduino-pid-autotune-library/

	if devicechanged[pid['sonde']] then

		-- définition des commandes marche/arrêt
		if pid['invert'] then
			marche = 'Off' ; arret = 'On'
		else
			marche = 'On' ; arret = 'Off'
		end
		
		-- récupération température
		local temp = getTemp(pid['sonde'])
		-- récupération consigne
		local consigne = tonumber(otherdevices_svalues[pid['thermostat']]) or pid['thermostat']

		-- hysteresis
		if temp > consigne then
			commandArray[#commandArray+1] = {[pid['radiateur']] = arret}
		elseif temp < consigne then
			commandArray[#commandArray+1] = {[pid['radiateur']] = marche}
		end

		-- timestamp
		local now = os.time()
		
		-- save all temps
		logToFile(pid['zone']..'_temps',now..';'..temp)
		
		local max1 = consigne
		local max2 = consigne
		local mini = consigne
		local max1_ts = now
		local max2_ts = now
		local mini_ts = now
		local init = 0

		-- recherche des valeurs mini/maxi
		for _,v in spairs(ReverseTable(lines_from(pid['zone']..'_temps'))) do
			t = tonumber(string.match(v,";([^%s]+)"))
			ts = tonumber(string.match(v,"([^%s]+);"))
			if t < mini and init == 0 then
				init = 1
			elseif t > max2 and (init == 1 or init == 2) then
				init = 2
				max2 = t
				max2_ts = ts
			elseif t < mini and (init == 2 or init == 3) then
				init = 3
				mini = t
				mini_ts = ts
			elseif t > max1 and (init == 3 or init == 4) then 
				init = 4
				max1 = t
				max1_ts = ts
			elseif t <= consigne and init == 4 then
				init = 5
				break				
			end
		end
		
		-- autotune
		local Pu = round(os.difftime(max2_ts, max1_ts) / 60)
		local A = tonumber(max1 - mini)
		local Ku = round(200 / (A * math.pi))
		local Kp = round(0.6 * Ku)
		local Ki = round(1.2 * Ku / Pu * pid['cycle'])
		local Kd = round(0.075 * Ku * Pu / pid['cycle'])
		
		-- journalisation
		log('PID autotune '..string.upper(pid['zone']))
		if init == 5 then
			log('max1: '..max1..' a '..os.date('%H:%M', max1_ts),pid['debug'])
			log('mini: '..mini..' a '..os.date('%H:%M', mini_ts),pid['debug'])
			log('max2: '..max2..' a '..os.date('%H:%M', max2_ts),pid['debug'])
			log('Pu:'..Pu,pid['debug'])
			log('A:'..A,pid['debug'])
			log('Ku:'..Ku,pid['debug'])
			log('Kp:'..Kp..' Ki:'..Ki..' Kd:'..Kd)
		else
			log('mesures en cours..')
		end	
		
	end
end

Re: bibliothèque de fonctions pour scripts LUA

Publié : 21 avr. 2017, 14:31
par papoo
quelques unes presentes dans mon fichier fonctions_perso.lua et qui à priori ne sont pas dans ton fichier :

pour afficher 240 caracteres max dans un device text en tronquant en fin de phrase

Code : Tout sélectionner

function TronquerTexte(texte, nb)  -- texte à tronquer, Nb maximum de caractère 
local sep ="[;!?.]"
local DernierIndex = nil
texte = string.sub(texte, 1, nb)
local p = string.find(texte, sep, 1)
DernierIndex = p
while p do
    p = string.find(texte, sep, p + 1)
    if p then
        DernierIndex = p
    end
end
return(string.sub(texte, 1, DernierIndex))
end
pour le calcul de la température ressentie

Code : Tout sélectionner

--============================================================================================== 
function calc_wind_chill(temperature, wind_speed)-- Calculate wind chill.
-- If temperature is low but it's windy, the temperature
-- feels lower than the actual measured temperature. Wind chill formula from
-- <a href="http://www.nws.noaa.gov/om/windchill/">http://www.nws.noaa.gov/om/windchill/</a>.
-- @param temperature Temperature in Fahrenheit, must be 50 or less
-- @param wind_speed Wind speed in miles per hour
-- @return Wind chill of the given conditions, or nil if invalid input received	
	local apparent = nil
	if (temperature ~= nil and wind_speed ~= nil and temperature <= 50) then
		if (wind_speed > 3) then
			local v = math.pow(wind_speed, 0.16)
			apparent = 35.74 + 0.6215 * temperature - 35.75 * v + 0.4275 * temperature * v
		elseif (wind_speed >= 0) then
			apparent = temperature
		end
	end
	return apparent
end
--============================================================================================== 
function calc_heat_index(temperature, humidity)-- Calculate heat index.
-- If it's hot and humidity is high,
-- temperature feels higher than what it actually is. Heat index is
-- the approximation of the human-perceived temperature in hot and moist
-- conditions. Heat index formula from
-- <a href="http://www.ukscience.org/_Media/MetEquations.pdf">http://www.ukscience.org/_Media/MetEquations.pdf</a>.
-- @param temperature Temperature in Fahrenheit, must be 80 or more
-- @param humidity Relative humidity as a percentage value between 40 and 100
-- @return Heat index of the given conditions, or nil if invalid input received
local apparent = nil
	if (temperature ~= nil and humidity ~= nil and temperature >= 80 and humidity >= 40) then
		local t2 = temperature * temperature
		local t3 = t2 * temperature
		local h2 = humidity * humidity
		local h3 = h2 * temperature

		apparent = 16.923
		+ 0.185212 * temperature
		+ 5.37941 * humidity
		- 0.100254 * temperature * humidity
		+ 9.41695e-3 * t2
		+ 7.28898e-3 * h2
		+ 3.45372e-4 * t2 * humidity
		- 8.14971e-4 * temperature * h2
		+ 1.02102e-5 * t2 * h2
		- 3.8646e-5 * t3
		+ 2.91583e-5 * h3
		+ 1.42721e-6 * t3 * humidity
		+ 1.97483e-7 * temperature * h3
		- 2.18429e-8 * t3 * h2
		+ 8.43296e-10 * t2 * h3
		- 4.81975e-11 * t3 * h3
	end

	return apparent
end
--==============================================================================================
function calc_apparent_temperature(temperature, wind_speed, humidity) -- Calculate wind chill or heat index corrected temperature
-- @param temperature Temperature in Fahrenheit
-- @param wind_speed Wind speed in miles per hour
-- @param humidity Relative humidity as a percentage value between 0 and 100
-- @return Apparent temperature given the weather conditions
-- @see calc_wind_chill
-- @see calc_heat_index	
	-- Wind chill
	if (temperature ~= nil and wind_speed ~= nil and temperature <= 50) then
		return calc_wind_chill(temperature, wind_speed)
	-- Head index
	elseif (temperature ~= nil and humidity ~= nil and temperature >= 80 and humidity >= 40) then
		return calc_heat_index(temperature, humidity)
	end

	return temperature
end
--============================================================================================== 
remplacement des caractères html en accentués

Code : Tout sélectionner

	function unescape(str)
	   	if string.match (str, "&") ~= nil then
	   		str = string.gsub( str, '<', '<' )
	   		str = string.gsub( str, '>', '>' )
	   		str = string.gsub( str, '"', '"' )
	   		str = string.gsub( str, '&apos;', "'" )
	   		str = string.gsub( str, '&rsquo;', "'" )
	   		str = string.gsub( str, '&laquo;', "«" )
	   		str = string.gsub( str, '&raquo;', "»" )
	   		str = string.gsub( str, '&nbsp;', " " )
	   		str = string.gsub( str, '&Ccedil;', "Ç" )
	   		str = string.gsub( str, '&ccedil;', "ç" )
	   		str = string.gsub( str, '&Acirc;', "Â" )
	   		str = string.gsub( str, '&Ecirc;', "Ê" )
	   		str = string.gsub( str, '&Icirc;', "Î" )
	   		str = string.gsub( str, '&Ocirc;', "Ô" )
	   		str = string.gsub( str, '&Ucirc;', "Û" )
	   		str = string.gsub( str, '&#(%d+);', function(n) if tonumber(n) < 256 then return string.char(tonumber(n)) else return "" end end )
	   		str = string.gsub( str, '&#x(%d+);', function(n) if tonumber(n) < 256 then return string.char(tonumber(n,16)) else return "" end end )
	   		str = string.gsub( str, '&', '&' ) -- Be sure to do this after all others
	   	end
	   	return str
	end
remplacement des caractères accentués en code html

Code : Tout sélectionner

function accent_html(str)
    if (str) then
	str = string.gsub(str, "'", "&apos;");
	str = string.gsub(str, "â",	"&acirc;")
	str = string.gsub(str, "à",	"&agrave;")
	str = string.gsub(str, "é",	"&eacute;")
	str = string.gsub(str, "ê",	"&ecirc;")
	str = string.gsub(str, "è",	"&egrave;")
	str = string.gsub(str, "ë",	"&euml;")
	str = string.gsub(str, "î",	"&icirc;")
	str = string.gsub(str, "ï",	"&iuml;")
	str = string.gsub(str, "ô",	"&ocirc;")
	str = string.gsub(str, "œ",	"&oelig;")
	str = string.gsub(str, "û",	"&ucirc;")
	str = string.gsub(str, "ù",	"&ugrave;")
	str = string.gsub(str, "ü",	"&uuml;")
	str = string.gsub(str, "ç",	"&ccedil;")
	str = string.gsub(str, "[-ÈÉÊË']+", "E")
    str = string.gsub(str, "[-@ÀÁÂÃÄÅ']+", "A")
    str = string.gsub(str, "[-ÌÍÎÏ']+", "I")
    str = string.gsub(str, "[-ÒÓÔÕÖ']+", "O")
    str = string.gsub(str, "[-ÙÚÛÜ']+", "U")
    str = string.gsub(str, "Ý", "Y")
     end
    return (str)
end
--============================================================================================== 

affiche le contenu d'une table

Code : Tout sélectionner

function print_r ( t )  -- afficher le contenu d'une table
    local print_r_cache={}
    local function sub_print_r(t,indent)
        if (print_r_cache[tostring(t)]) then
            print(indent.."*"..tostring(t))
        else
            print_r_cache[tostring(t)]=true
            if (type(t)=="table") then
                for pos,val in pairs(t) do
                    if (type(val)=="table") then
                        print(indent.."["..pos.."] => "..tostring(t).." {")
                        sub_print_r(val,indent..string.rep(" ",string.len(pos)+8))
                        print(indent..string.rep(" ",string.len(pos)+6).."}")
                    elseif (type(val)=="string") then
                        print(indent.."["..pos..'] => "'..val..'"')
                    else
                        print(indent.."["..pos.."] => "..tostring(val))
                    end
                end
            else
                print(indent..tostring(t))
            end
        end
    end
    if (type(t)=="table") then
        print(tostring(t).." {")
        sub_print_r(t,"  ")
        print("}")
    else
        sub_print_r(t,"  ")
    end
    print()
end
--============================================================================================== 
Conversion degrés fahrenheit en celsius

Code : Tout sélectionner

function fahrenheit_to_celsius(fahrenheit, digits) 
    return round((5/9) * (fahrenheit - 32), digits or 2)
end
--============================================================================================== 
Conversion de miles en kilometres

Code : Tout sélectionner

function miles_to_km(miles, digits) 
    return round((miles * 1.609344), digits or 2)
end
--==============================================================================================
envoi de message via pushbullet (pensez à personnaliser cette fonction avec votre propre key pushbullet

Code : Tout sélectionner

  function Pushbullet(Message)  -- séparer titre et objet du message par un ;
    local pb_token = 'votre KEY PUSHBULLET'
    local pb_total = Message
    local val=string.find(pb_total,";")
    local pb_title = string.sub(pb_total,1,val-1)
    local pb_body = string.sub(pb_total,val+1)
	--Pour Windows
    --local pb_command = 'c:\\Programs\\Curl\\curl -u ' .. pb_token .. ': "https://api.pushbullet.com/v2/pushes" -d type=note -d title="' .. pb_title .. '" -d body="' .. pb_body ..'"'
    --pour Linux
   local pb_command = 'curl -u ' .. pb_token .. ': "https://api.pushbullet.com/v2/pushes" -d type=note -d title="' .. pb_title .. '" -d body="' .. pb_body ..'"'
    -- Run curl command
    exec_success = os.execute(pb_command)
	-- usage : Pushbullet('message') -- message : titre;objet du message
  end
--==============================================================================================

Re: bibliothèque de fonctions pour scripts LUA

Publié : 21 avr. 2017, 15:43
par papoo
j'ajouterai bien une petite fonction pour définir automatiquement le chemin vers cURL, qu'en penses tu?

Code : Tout sélectionner

 
 	domoticzUSER = ''		-- nom d'utilisateur
	domoticzPSWD = ''		-- mot de passe
	
   function File_exists(file)  --Check if file exist
     local f = io.open(file, "rb")
     if f then f:close() end
     return f ~= nil
	--   usage : if not File_exists(File) then
   end 
-==========================================================================
   linuxCurl = '/usr/bin/curl'
   windowsCurl ='c:\\curl\\curl.exe'
 
   if File_exists(linuxCurl) then
  curl = 'linuxCurl -m 5 -u domoticzUSER:domoticzPSWD ' 
   elseif File_exists(windowsCurl) then
 curl = 'windowsCurl -m 5 -u domoticzUSER:domoticzPSWD ' 
      else
   print("Localisation de cURL impossible")
   end

Re: bibliothèque de fonctions pour scripts LUA

Publié : 21 avr. 2017, 16:30
par vil1driver
je me suis dis pareil en voyant ton c:\\Programs\\Curl\\curl
mais ce chemin est variable.. :(
Il faudrait demander à ce que curl.exe soit de base ajouté à domoticz.. qu'on ne le cherche pas :D

sinon j'aurais bien vu ceci

Code : Tout sélectionner

if (package.config:sub(1,1) == '/') then
	--system lunx
	luaDir = debug.getinfo(1).source:match("@?(.*/)")
	curl = '/usr/bin/curl -m 5 '
else
	--system windows
	luaDir = string.gsub(debug.getinfo(1).source:match("@?(.*\\)"),'\\','\\\\')
	curl = 'c:\\Programs\\Curl\\curl.exe '
end
merci pour tes fonctions ;) en particulier afficher une table et pushbulet

Re: bibliothèque de fonctions pour scripts LUA

Publié : 22 avr. 2017, 16:26
par vil1driver
bon j'ai trouvé une fonction pour afficher la table qui me plait un chouilla plus.. mais ce n'est qu'une histoire de gout dans l'affichage..
merci pour l'idée en tout cas, ça va clairement me servir.. :D

pour pushbullet, tu avais une raison de passer titre et message dans la même chaîne à la base ?
pour les obtenir par lecture d'une variable utilisateur ?
j'ai un peu remanié la fonction en séparant les 2 et en récupérant automatiquement la clé api ;)

Code : Tout sélectionner

-- notification pushbullet
-- usage:
-- pushbullet('test','ceci est un message test')
function pushbullet(title,body)
	local settings = assert(io.popen(curl..'-u '..domoticzUSER..':'..domoticzPSWD..' "'..domoticzURL..'/json.htm?type=settings"'))
	local list = settings:read('*all')
	settings:close()
	local pushbullet_key = json:decode(list).PushbulletAPI
	os.execute(curl..'-H \'Access-Token:'..pushbullet_key..'\' -H \'Content-Type:application/json\' --data-binary \'{"title":"'..title..'","body":"'..body..'","type":"note"}\' -X POST "https://api.pushbullet.com/v2/pushes"')
end
ps: 5 secondes de timeout pour curl n'est pas suffisant pour pushbullet, je suis passé à 15

Re: bibliothèque de fonctions pour scripts LUA

Publié : 22 avr. 2017, 17:15
par papoo
elle n'est pas de moi, je l'ai trouvé la
https://www.domoticz.com/forum/viewtopi ... 42&p=87659
avec d'autres

Re: bibliothèque de fonctions pour scripts LUA

Publié : 24 avr. 2017, 21:35
par Jeff
Merci pour vos partages.
Pas sûr de maîtriser grand chose mais quelques fonctions sont compréhensibles :?

Re: bibliothèque de fonctions pour scripts LUA

Publié : 24 avr. 2017, 22:04
par vil1driver
N'hésite pas à demander au besoin ;)

Re: bibliothèque de fonctions pour scripts LUA

Publié : 11 mai 2017, 08:52
par aleph0
Merci à tous pour vos contributions et partage.

Je pense que ce topic mériterai d'être épinglé ou passé dans le wiki tellement il est important :)

Re: bibliothèque de fonctions pour scripts LUA

Publié : 14 mai 2017, 10:13
par bnic
Maintenant il faudrait faire la doc pour résumer au moins toutes les fonctions incluses avec leurs arguments :twisted:

edit :

A priori il y a une dépendance : JSON.lua

http://regex.info/code/JSON.lua