Foros Domótica Doméstica

Programación LUA

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #15 en: Abril 23, 2015, 13:52:30 pm »
--[[
_esNoche(timeStamp)
  función para averiguar si en un momento dado es de noche
--------------------------------------------------------------------------------]]
function _esNoche(instante)
  local miInstante = os.date("*t", instante)
  -- amanecer
  local amanecer = fibaro:getValue(1, 'sunriseHour')
  miInstante.min = tonumber(string.format("%1d", amanecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", amanecer:sub(1,2)))
  local sunriseTime = os.time(miInstante)
  -- anochecer
  local anochecer = fibaro:getValue(1, 'sunsetHour')
  miInstante.min = tonumber(string.format("%1d", anochecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", anochecer:sub(1,2)))
  local sunsetTime = os.time(miInstante)
  --
  if (instante >= sunsetTime) then return true
  elseif (instante >= sunriseTime) then return false
  else return true end
end

if condicion=_esNoche(os.time()) then
  -- acciones
end

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #16 en: Abril 23, 2015, 14:03:15 pm »
Sio en lugar de la hora de anochecer y amanecer del sistema quieres usar unas horas tuyas sustituye
Código: [Seleccionar]
  local amanecer = fibaro:getValue(1, 'sunriseHour')
  miInstante.min = tonumber(string.format("%1d", amanecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", amanecer:sub(1,2)))
 local sunriseTime = os.time(miInstante)
Por
Código: [Seleccionar]
miInstante.min = '08'
miInstante.hour ='00'
local sunriseTime = os.time(miInstante)
y de forma análoga para el anochecer

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #17 en: Abril 23, 2015, 14:42:35 pm »
He añadido tu programación a la anterior poniendo la anterior después de "acción" y colocando el "end" al final. Así:

--[[
%% properties
86 value
90 value
412 value
--]]

local id_luz1 = 86
local id_luz2 = 90
local id_presencia = 412
local id_led1= 87
local id_led2= 89
local id_led3= 92
local tiempoApagado = 90
--[[
_esNoche(timeStamp)
  función para averiguar si en un momento dado es de noche
--------------------------------------------------------------------------------]]
function _esNoche(instante)
  local miInstante = os.date("*t", instante)
  -- amanecer
  local amanecer = fibaro:getValue(1, 'sunriseHour')
  miInstante.min = tonumber(string.format("%1d", amanecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", amanecer:sub(1,2)))
  local sunriseTime = os.time(miInstante)
  -- anochecer
  local anochecer = fibaro:getValue(1, 'sunsetHour')
  miInstante.min = tonumber(string.format("%1d", anochecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", anochecer:sub(1,2)))
  local sunsetTime = os.time(miInstante)
  --
  if (instante >= sunsetTime) then return true
  elseif (instante >= sunriseTime) then return false
  else return true end
end

if condicion=_esNoche(os.time()) then

-- funciona para saber si un dispositivo está activo
function _esActivo(id)
  if (fibaro:getValue(id, "value") ~= nill and
  tonumber(fibaro:getValue(id, "value")) > 0) then
    return true
  end
  return false
end

-- obtener el origen del inicio de la escena
local startSource = fibaro:getSourceTrigger()
-- si se lánzo por un dispositivo ...
if (startSource["type"] == "property") then

  -- obtener el dispositivo que lanzó la escena
  local sourceDevice = startSource['deviceID']

  -- Si se detecta presencia, no hay luzces encendidas
  -- y la tira de les está apagada
  if (sourceDevice == id_presencia) and
     not _esActivo(id_luz1) and
     not _esActivo(id_luz2) and
     not _esActivo(id_led1)and
     not _esActivo(id_led2)and
     not _esActivo(id_led3) then
    -- encender la tira de led
    fibaro:debug('encender tira de leds')
    fibaro:call(id_led1, "turnOn")
        fibaro:call(id_led2, "turnOn")
        fibaro:call(id_led3, "turnOn")
    -- esperar
   fibaro:sleep(1000*tiempoApagado)
    -- si sigue encendido apagar
    if _esActivo(id_led1) or     _esActivo(id_led2) or     _esActivo(id_led3) then
     fibaro:debug('apagar tira de leds')
     fibaro:call(id_led1, "turnOff")
           fibaro:call(id_led2, "turnOff")
           fibaro:call(id_led3, "turnOff")
    end
  end

  -- si se enciende alguna luz y la tira de led está encendida
  if (sourceDevice == id_luz1 or sourceDevice == id_luz2) and _esActivo(id_led1) and _esActivo(id_led2) and _esActivo(id_led3) then
   -- apagar la tira de led
   fibaro:debug('apagar tira de leds')
   fibaro:call(id_led1, "turnOff")
       fibaro:call(id_led2, "turnOff")
       fibaro:call(id_led3, "turnOff")
  end
 
else -- si no lo lanza un dispositivo se entiende que es a mano
 fibaro:debug('Lanzado a mano, nada que hacer')
end
  end

Pero esto me da error en la línea:
if condicion=_esNoche(os.time()) then

Lo de "condicion" a qué se refiere?

Aún me cuesta enternder algunos pasos aunque claramente entiendo mucho más que antes. Es cuestión de tiempo que deje de darte la lata con estas pequeñeces.

Jokin

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #18 en: Abril 23, 2015, 14:51:51 pm »
Linkey,

Hay algunas cosas de base que no las comprendo y creo que son clave para poder avanzar en Programación Lua.
La línea   local amanecer = fibaro:getValue(1, 'sunriseHour') contiene un parámetro "sunriseHour" que parece pertenecer al sistema. Es decir, que el sofware reconoce que "sunriseHour" es una hora concreta. Pero, pero, pero, cómo me informo de que existe ese parámetro en el sistema. He tratado de buscar esto en los manuales que me mandaste pero no encuentro ni este parámetro ni un listado de parámetros que entendería el software. Si bien encuentro un listado de funciones, me falta conocer los parámetros que sé que me va a entender el sofware HC2.
Al menos, la sistemática ya la pillo pero sin conocer qué parámetros puedo utilizar me cuesta avanzar más rápido.

En relación al anterior mensaje. La palabra "condicion" parece ser una variable pero no la tengo definida. Quizás ahí esté el problema?

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #19 en: Abril 23, 2015, 20:32:08 pm »
He añadido tu programación a la anterior poniendo la anterior después de "acción" y colocando el "end" al final. Así:

--[[
%% properties
86 value
90 value
412 value
--]]

local id_luz1 = 86
local id_luz2 = 90
local id_presencia = 412
local id_led1= 87
local id_led2= 89
local id_led3= 92
local tiempoApagado = 90
--[[
_esNoche(timeStamp)
  función para averiguar si en un momento dado es de noche
--------------------------------------------------------------------------------]]
function _esNoche(instante)
  local miInstante = os.date("*t", instante)
  -- amanecer
  local amanecer = fibaro:getValue(1, 'sunriseHour')
  miInstante.min = tonumber(string.format("%1d", amanecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", amanecer:sub(1,2)))
  local sunriseTime = os.time(miInstante)
  -- anochecer
  local anochecer = fibaro:getValue(1, 'sunsetHour')
  miInstante.min = tonumber(string.format("%1d", anochecer:sub(4,5)))
  miInstante.hour = tonumber(string.format("%1d", anochecer:sub(1,2)))
  local sunsetTime = os.time(miInstante)
  --
  if (instante >= sunsetTime) then return true
  elseif (instante >= sunriseTime) then return false
  else return true end
end

if condicion=_esNoche(os.time()) then

-- funciona para saber si un dispositivo está activo
function _esActivo(id)
  if (fibaro:getValue(id, "value") ~= nill and
  tonumber(fibaro:getValue(id, "value")) > 0) then
    return true
  end
  return false
end

-- obtener el origen del inicio de la escena
local startSource = fibaro:getSourceTrigger()
-- si se lánzo por un dispositivo ...
if (startSource["type"] == "property") then

  -- obtener el dispositivo que lanzó la escena
  local sourceDevice = startSource['deviceID']

  -- Si se detecta presencia, no hay luzces encendidas
  -- y la tira de les está apagada
  if (sourceDevice == id_presencia) and
     not _esActivo(id_luz1) and
     not _esActivo(id_luz2) and
     not _esActivo(id_led1)and
     not _esActivo(id_led2)and
     not _esActivo(id_led3) then
    -- encender la tira de led
    fibaro:debug('encender tira de leds')
    fibaro:call(id_led1, "turnOn")
        fibaro:call(id_led2, "turnOn")
        fibaro:call(id_led3, "turnOn")
    -- esperar
   fibaro:sleep(1000*tiempoApagado)
    -- si sigue encendido apagar
    if _esActivo(id_led1) or     _esActivo(id_led2) or     _esActivo(id_led3) then
     fibaro:debug('apagar tira de leds')
     fibaro:call(id_led1, "turnOff")
           fibaro:call(id_led2, "turnOff")
           fibaro:call(id_led3, "turnOff")
    end
  end

  -- si se enciende alguna luz y la tira de led está encendida
  if (sourceDevice == id_luz1 or sourceDevice == id_luz2) and _esActivo(id_led1) and _esActivo(id_led2) and _esActivo(id_led3) then
   -- apagar la tira de led
   fibaro:debug('apagar tira de leds')
   fibaro:call(id_led1, "turnOff")
       fibaro:call(id_led2, "turnOff")
       fibaro:call(id_led3, "turnOff")
  end
 
else -- si no lo lanza un dispositivo se entiende que es a mano
 fibaro:debug('Lanzado a mano, nada que hacer')
end
  end

Pero esto me da error en la línea:
if condicion=_esNoche(os.time()) then

Lo de "condicion" a qué se refiere?

Aún me cuesta enternder algunos pasos aunque claramente entiendo mucho más que antes. Es cuestión de tiempo que deje de darte la lata con estas pequeñeces.

Jokin
Lo de 'condicion' es un error por mi parte, te lo puse como ejemplo y no me he dado cuenta.
condicion = _esNoche(), almacenaría en una variable llamada 'condicion' lo que devuelva la '_esNoche', en este caso verdadero o falso (true, false) 
así que en tu caso deberías quitas la palabra 'condición'
if _esNoche(os.time()) then, significa, si en este preciso instante es de noche entonces...

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #20 en: Abril 23, 2015, 20:42:28 pm »
Linkey,

Hay algunas cosas de base que no las comprendo y creo que son clave para poder avanzar en Programación Lua.
La línea   local amanecer = fibaro:getValue(1, 'sunriseHour') contiene un parámetro "sunriseHour" que parece pertenecer al sistema. Es decir, que el sofware reconoce que "sunriseHour" es una hora concreta. Pero, pero, pero, cómo me informo de que existe ese parámetro en el sistema. He tratado de buscar esto en los manuales que me mandaste pero no encuentro ni este parámetro ni un listado de parámetros que entendería el software. Si bien encuentro un listado de funciones, me falta conocer los parámetros que sé que me va a entender el sofware HC2.
Al menos, la sistemática ya la pillo pero sin conocer qué parámetros puedo utilizar me cuesta avanzar más rápido.

En relación al anterior mensaje. La palabra "condicion" parece ser una variable pero no la tengo definida. Quizás ahí esté el problema?
La verdad es que no hay mucha documentación o no sabemos donde, yo investigando en foros me he enterado de estas cosas.
Si recuerdas cuando consultamos las propiedades de al interruptor Aeon de tu placa de inducción hiciste una consulta invocando una URL desde el navegador, algo así:
http://IP/api/devices/1
1 es el id 1 del dispositivo, representa el propio HC y tiene, entre otras, la propiedad 'sunriseHour'
dependiendo de la versión del sistema quizás necesites usar la sintaxis clásica
http://IP/api/devices?id=1
Otro dispositivo interesante el el número 3 que indica las condiciones meteorológicas obtenidas por el HC desde YahoWeather.
en http://IP/api/globalVariables/, tienes las variables globales
en http://IP//api/scenes, escenas
...

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #21 en: Abril 23, 2015, 21:04:29 pm »
Pues a investigar se ha dicho!
Ahora va muy bien la escena. Me tenía que haber dado cuenta.
Gracias,
Jokin

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #22 en: Abril 23, 2015, 21:44:56 pm »
Me alegro que te funcione!

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #23 en: Abril 24, 2015, 09:10:25 am »
Linkey,
Yo sigo con mis dudas de Lua pero progresando.
¿Cuándo en Lua haces una llamada o te refieres a un sensor de movimiento "Ojo de halcón", por ejemplo, parece que por defecto, se considera que el "breach" es cuando se pone en ON (se activa). Así me lo has planteado cuando me has escrito las programaciones anteriores donde este sensor permitía que se encendiera una tira LED.
Pero cómo se hace para que el "ON", es decir, la acción sea ejecutada cuando el ojo de halcón esté en modo "Safe" durante 20 min, por ejemplo?
Quisiera hacer una escena que apagara dos luces de un baño cuando el ojo de halcón lleve 20 min en estado "Safe". Y que no haga nada si el modo "Safe" lleva menos de 20 min.
Gracias.

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #24 en: Abril 24, 2015, 11:58:30 am »
Linkey,
Yo sigo con mis dudas de Lua pero progresando.
¿Cuándo en Lua haces una llamada o te refieres a un sensor de movimiento "Ojo de halcón", por ejemplo, parece que por defecto, se considera que el "breach" es cuando se pone en ON (se activa). Así me lo has planteado cuando me has escrito las programaciones anteriores donde este sensor permitía que se encendiera una tira LED.
Pero cómo se hace para que el "ON", es decir, la acción sea ejecutada cuando el ojo de halcón esté en modo "Safe" durante 20 min, por ejemplo?
Quisiera hacer una escena que apagara dos luces de un baño cuando el ojo de halcón lleve 20 min en estado "Safe". Y que no haga nada si el modo "Safe" lleva menos de 20 min.
Gracias.
Este tipo de eventos, para mi son “programados”, como pudiera ser que a una determinada hora se cierren las persianas, pero con la diferencia de que el momento en el que queremos que se produzca la acción depende del el tiempo que lleve otro dispositivo inactivo.
Este tipo de eventos los resuelvo todos con una escena que se mantenga en ejecución de forma indeterminada comprobando cada cierto tiempo si hay algo que hacer.

Para comprobar si ha pasado un tiempo determinado desde que se cambió el estado de una propiedad de un objeto se utiliza valor, tiempo = fibaro:get(id, 'value')
Efectivamente el sensor de actividad esta activo (breach)  cuando la propiedad 'value' es 1 e inactivo a 0 (safe).

De manera mas sencilla, también puedes plantear una escena que salte cuando cambie la propiedad, comprobar que se ha puesto a valor 0, esperar 20min y comprobar que el estado no ha cambiado desde hace 20min o más.

Ejemplo:

Código: [Seleccionar]
--[[
%% properties
414 value
--]]

local id_sensor = 414
local id_luz = 16
local tiempoInactividad = 1 -- minutos
 
-- si el sensor se ha apagado
if tonumber(fibaro:getValue(id_sensor, 'value')) == 0 then
  -- esperar el tiempo indicado
  fibaro:debug('esperando')
  fibaro:sleep(tiempoInactividad*60*1000)
  -- calcular el tiempo que lleva el dispositivo sin cambiar de estado
  local valor, instante = fibaro:get(id_sensor, 'value')
  local diferenciaTiempo = os.time() - instante
  fibaro:debug(diferenciaTiempo)
  -- si el tiempo sin cambiar es mayor o igual al tiempo indicado
  if tonumber(valor) == 0 and  diferenciaTiempo >= (tiempoInactividad*60) then
    -- apagar el dispositivo
    fibaro:debug('Apagar')
    fibaro:call(id_luz, 'turnOff')
  end
end

para que funcione si enciendes y apagas varias veces entre el periodo de tiempo de inactividad, no tienes que matar la escena si se lanza otra igual, lo que hace que en un momento dado tengas varias instancias de la misma escena en ejecución.

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #25 en: Abril 24, 2015, 12:52:11 pm »
Me parece muy razonable!
Linkey, al final te voy a tener que invitar a unas cervezas. Por otro hilo he visto que vives en Madrid. Yo vivo en Bilbao pero voy bastante a Madrid. Si sigues instruyéndome te llevaré una buena botella de vino que soy de Laguardia, una zona excelente para esos caldos.
Y ahora me aprovecho y pregunto.

El poner if tonumber(fibaro:getValue(id_sensor, 'value')) == 0 en vez de  if (fibaro:getValue(id_sensor, 'value')) == 0, por qué es. Entiendo que el valor de 'value' es siempre un número, no?

La línea: local valor, instante = fibaro:get(id_sensor, 'value') no la entiendo por la ",".  Es como si hubieras creado dos variables con el mismo valor al mismo tiempo. Entonces la línea: local valor, instante = fibaro:get(id_sensor, 'value') sería igual que poner:

local valor = fibaro:get(id_sensor, 'value')
local instante = fibaro:get(id_sensor, 'value')
? O me lo he inventado?

Lo dicho, te estás ganando esa botella de vino...

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #26 en: Abril 24, 2015, 13:46:01 pm »
El poner if tonumber(fibaro:getValue(id_sensor, 'value')) == 0 en vez de  if (fibaro:getValue(id_sensor, 'value')) == 0, por qué es. Entiendo que el valor de 'value' es siempre un número, no?
Según la documentación de la API de fibaro fibaro:getValue devuelve "A string containing the current value of the property". Esto es, devuelve una cadena no un número, por lo tanto si no usas la función tonumber() para convertir la cadena en un número,  tendrías que poner el 0 entre comillas
if (fibaro:getValue(id_sensor, 'value')) == "0"
O te daría un error al intentar comparar un número con una cadena.

linkey

  • *****
  • 604
    • Ver Perfil
Re:Programación LUA
« Respuesta #27 en: Abril 24, 2015, 14:04:43 pm »
La línea: local valor, instante = fibaro:get(id_sensor, 'value') no la entiendo por la ",".  Es como si hubieras creado dos variables con el mismo valor al mismo tiempo. Entonces la línea: local valor, instante = fibaro:get(id_sensor, 'value') sería igual que poner:

local valor = fibaro:get(id_sensor, 'value')
local instante = fibaro:get(id_sensor, 'value')
? O me lo he inventado?
La documentación de la API de fibaro, fibaro:get()...
Returned Values
This function returns two values:

A string containing the current value of the property, and
A timestamp of when the property was last modified
Please note that these return values are of type string.  When comparing them with a variable of type number, use tonumber to convert them first.
fibaro:get(id_sensor, 'value') devuelve dos valores, por esto se ponen dos variables, para recibir los dos valores

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #28 en: Abril 24, 2015, 14:08:37 pm »
Está clarísimo ahora.
Estoy deseando llegar a casa para probarlo.
Te cuento.

Jokin

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #29 en: Abril 25, 2015, 11:06:03 am »
Acabo de hacer una escena en Lua para hacer que se baje una persiana sólo si la puerta de la terraza está cerrada. Es de las que se abre hacia fuera y si está abierta, la persiana da con la puerta y se puede estropear el motor. Por eso quiero que sólo se baje cuando la puerta está cerrada:

--[[
%% properties
442 puerta
170 persiana
%% globals
--]]

local puerta = 442
local persiana = 170

fibaro:debug  (fibaro:getValue(puerta, "value") )

  if tonumber(fibaro:getValue(puerta, "value")) < 1 then
fibaro:call(persiana,"turnON")
  else
  fibaro:abort()
end


No me funciona y yo creo que es porque para bajar una persiana no hay que "turnON". Y no sé qué función es.
He tratado de mirar con:

http://10.0.1.18/api/devices/170

Pero tampoco veo la función de llamada que debería utilizar.

Habréis observado que he tenido que poner "< 1" en vez de "= 0". Esto es porque si pongo "= 0" me da un error. Y como el valor es 0 para cerrada la puerta y 1 para abierta la puerta, no se me ha ocurrido otra forma de solucionarlo. Al menos no me da error y me lee "fibaro:debug  (fibaro:getValue(puerta, "value") )" dándome el valor de 0 o 1 dependiendo el estado de la puerta.

Gracias.