Programación LUA

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #45 en: Mayo 05, 2015, 13:18:35 pm »
Ya me empieza a dar un poco verguenza pero necesito de nuevo tu ayuda.
Resulta que tengo todos los electrodomésticos domesticados (además de domotizados, claro). Me avisan cuando se ponen en marcha y cuando se paran. Esto me ayuda a que no me deje la ropa en la lavadora o en la secadora más de la cuenta, etc. El caso es que hay uno que no se ha dejado domesticar.
Las escenas son muy simples como te puedes imaginar. Cuando el enchufe informa de que el consumo es mayor de 50 W, por ejmplo, me manda un email que dice que el electrodoméstico se ha puesto en marcha y, EN PRINCIPIO, cuando el consumo es de 0W me dice que ya ha terminado. Pero, pero, estos electrodomésticos modernos no tienen un consumo de 0W pues tienen muchas lucecitas (y paneles LCD) y el consumo oscila entre 3W y 5W con fluctuaciones entre estos extremos.
Con la secadora y el lavavajillas lo he solucionado porque he puesto que me notifiquen que han acabado cuando lleguen a 4 W y todo va bien pero la pedor... de la lavadora en la mitad de sus ciclos se para (me imagino que para descansar o para fastidiarme) y baja su consumo a niveles de como si estuviera parada. Esto hace que me informe varias veces de que está parada y de que se ha puesto en marcha (tantas veces como ciclos tiene de parada).
La solucioón que he encontrado es hacer una escena que avise SÓLO si la lavadora está al menos 15 min con un consumo menor de 6W, situación que sólo ocurre cuando está completamente parada. Y, claro, aunque mi profe particular Linkey me está enseñando un montón de Lua, aún no se me ocurre cómo hacer esta escena.
Gracias,
Jokin

linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #46 en: Mayo 05, 2015, 19:32:47 pm »
Creo que sería una escena parecida a la anterior, con la diferencia de que cambia propiedad del dispositivo que lanza la acción, la función a aplicar y sobre que dispositivo ya que no serán el mismo que lanza la acción como en el caso anterior.
Me explico, la acción la lanza el enchufe de la lavadora, pero el mensaje lo envía el dispositivo móvil.

linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #47 en: Mayo 06, 2015, 12:21:46 pm »
La propiedad creo que será "power" depende de tu dispositivo (ya hemos hablado de ello) y la función si quieres que lance un mensaje "sendPush", tendrás que averiguar el id de tu dispositivo móvil...
 http://IP_DE_TU_HC2/api/devices
buscas el nombre de tu dispositivo móvil y miras el id, ej:
 {"id":406,"name":"LiNPhone","roomID":...
Basada en la escena anterior, he escrito esta sobre la marcha así que no la he depurado y puede que tenga algún error (tendrás que depurarlo). Tocando un poquito las variable y la función "function _condicion(valor)", podrás adaptarla a distintas condiciones (xx el id del enchufe de la lavadora, yy id del dispositivo móvil):
Código: [Seleccionar]
--[[
%% properties
xx power
--]]

local elapTime = 15 -- minutos
local funcion = 'sendPush'
local funcionId = yy -- id del dispositivo móvil
local argumento = 'La lavadora ha terminado'
local startSource = fibaro:getSourceTrigger()

function _condicion(valor)
  if tonumber(valor) < 6 -- menor de 6W
   return true
  end
  return false
end

if startSource['type'] == 'property' then
  local deviceID = startSource['deviceID']
  local propertyName = startSource['propertyName']
  local value = fibaro:getValue(deviceID, propertyName)
  --fibaro:debug('accionado id '..deviceID..' '..propertyName..' '..value)
  if _condicion(value) then
    --fibaro:debug('esperando...')
    fibaro:sleep(elapTime*60*1000)
    -- calcular el tiempo que lleva el dispositivo sin cambiar de estado
    local valor, instante = fibaro:get(deviceID, 'value')
    local diferenciaTiempo = os.time() - instante
    --fibaro:debug('ha pasado '..diferenciaTiempo..'seg')
    -- si el tiempo sin cambiar es mayor o igual al tiempo indicado
    if _condicion() and  diferenciaTiempo >= (elapTime*60) then
      -- apagar el dispositivo
      --fibaro:debug('Apagar '..deviceID)
      fibaro:call(deviceID, funcion, argumento)
    end
  end
end

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #48 en: Mayo 06, 2015, 19:39:12 pm »
Gracias Linkey,

Lo he probado después de corregir algunas cosas pero me da error y no sé si estoy haciendo algo mal.
Te cuento lo que he corregido porque he pensado que estaba mal. De todas formas, no estoy seguro de que todos los cambios hayan sido corrector.

-Donde pone "funcionId" he puesto "deviceID" pues "funcionId" no se menciona luego.

-Donde pone "valor" he puesto "value". De esto no estoy seguro que sea correcto el cambio.

-En el primer "if tonumber..." he añadido un "then" antes de "return true".

-No estoy seguro de que el "end" después del "return true" no deba ser un "else". No lo he cambiado.

El caso es que finalmente no me funciona.
Podrías echar un vistazo para ver qué puede ser, por favor?

Gracias.

linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #49 en: Mayo 06, 2015, 21:11:59 pm »
-Donde pone "funcionId" he puesto "deviceID" pues "funcionId" no se menciona luego.
En lugar de quitar "funcionId", tienes que poner en la línea 35
 fibaro:call(funcionId, funcion, argumento)
Cita de: Jokin
-Donde pone "valor" he puesto "value". De esto no estoy seguro que sea correcto el cambio.
No, no quites valor, vamos a usar valor en lugar de value, para almacenar el valor de la propiedad que en este caso es el valor de "power" y no de value, daría lo mismo pero así no nos liamos.
Cita de: Jokin
-En el primer "if tonumber..." he añadido un "then" antes de "return true".
OK
Cita de: Jokin
-No estoy seguro de que el "end" después del "return true" no deba ser un "else". No lo he cambiado.
No, está bien así, si valor < 6 entonces retorna verdadero y ya no sigue la función, por lo tanto no es necesario un else , ya que si no se cumple la condición sigue y sale devolviendo falso.

Queda así:
Código: [Seleccionar]
--[[
%% properties
xx power
--]]

local elapTime = 1 -- minutos
local funcion = 'sendPush'
local funcionId = yy -- id del dispositivo móvil
local argumento = 'La lavadora ha terminado'
local startSource = fibaro:getSourceTrigger()

function _condicion(valor)
  if tonumber(valor) < 6 then-- menor de 6W
   return true
  end
  return false
end

if startSource['type'] == 'property' then
  local deviceID = startSource['deviceID']
  local propertyName = startSource['propertyName']
  local valor = fibaro:getValue(deviceID, propertyName)
  fibaro:debug('accionado id '..deviceID..' '..propertyName..' '..valor)
  if _condicion(valor) then
    fibaro:debug('esperando...')
    fibaro:sleep(elapTime*60*1000)
    -- calcular el tiempo que lleva el dispositivo sin cambiar de estado
    valor, instante = fibaro:get(deviceID, propertyName)
    local diferenciaTiempo = os.time() - instante
    fibaro:debug('ha pasado '..diferenciaTiempo..'seg')
    -- si el tiempo sin cambiar es mayor o igual al tiempo indicado
    if _condicion(valor) and  diferenciaTiempo >= (elapTime*60) then
      -- apagar el dispositivo
      fibaro:debug(funcion..' '..funcionId..' '..argumento)
      fibaro:call(funcionId, funcion, argumento)
    end
  end
end

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #50 en: Mayo 10, 2015, 17:12:30 pm »
Gracias como siempre Linkey.

He estado todo el fin de semana con este tema. He corregido mis errores con tus sugerencias y en principio funciona. El problema es que no para de mandar mensajes. Es como si nadie le dijera que una vez que avise de que el Lavavajillas (por ejemplo) acaba de terminar ya no tiene que avisar más hasta que no se vuelva a encender.
Entiendo que lo que pasa es que el lavavajillas, al acabar empieza a cumplir cada minuto con la premisa de la Escena de Lua (está con un consumo constante de 3,5 W).

--[[
%% properties
4 power
--]]

local elapTime = 1 -- minutos
local funcion1 = 'sendPush'
local funcion2 = 'sendEmail'
local funcionId1 = 72 -- id del dispositivo móvil de Joaquínb
local funcionId2 = 54 -- id del email de Joaquín
local argumento = 'El lavavajillas acaba de terminar (Lua)'
local subject = 'El lavavajillas se acaba de terminar'
local message = 'El lavavajillas se acaba de terminar.'
local startSource = fibaro:getSourceTrigger()

function _condicion(valor)
  if tonumber(valor) < 6 and tonumber(valor) > 2  then -- menor de 6W y mayor de 2W
   return true
  end
  return false
end

if startSource['type'] == 'property' then
  local deviceID = startSource['deviceID']
  local propertyName = startSource['propertyName']
  local valor = fibaro:getValue(deviceID, propertyName)
  fibaro:debug('accionado id '..deviceID..' '..propertyName..' '..valor)
  if _condicion(valor) then
    fibaro:debug('esperando...')
    fibaro:sleep(elapTime*60*1000)
    -- calcular el tiempo que lleva el dispositivo sin cambiar de estado
    valor, instante = fibaro:get(deviceID, propertyName)
    local diferenciaTiempo = os.time() - instante
    fibaro:debug('ha pasado '..diferenciaTiempo..'seg')
    -- si el tiempo sin cambiar es mayor o igual al tiempo indicado
    if _condicion(valor) and  diferenciaTiempo >= (elapTime*60) then
      -- apagar el dispositivo
      fibaro:debug(funcion1..' '..funcionId1..' '..argumento)
      fibaro:debug(funcion2..' '..funcionId2..' '..subject)
      fibaro:call(funcionId1, funcion1, argumento)
      fibaro:call(funcionId2, funcion2, subject, message)
    end
  end
end

Cómo se podría hacer para que sólo mandara un mensaje?
Yo sólito he incluido lo de que envíe un mensaje de email también.
Gracias.

linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #51 en: Mayo 10, 2015, 20:45:39 pm »
Hola,
en principio la escena solo se lanza cuando hay algún cambio en el estado de la propiedad "power"en el dispositivo 4, así que no debería lanzares si no cambia el valor. Supongo que será por que tenga varios cambio fluctuando entre 2 y 6 W.


linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #52 en: Mayo 10, 2015, 20:52:47 pm »
Se me ocurre usar una variable global para almacenar el estado del lavavajillas (encendido/apagado)
usar dos condiciones en la escena
1 si es mayor de 6W es que se ha encendido y se graba en la variable "ON"
2 si es menor de 6W y la variable es "ON" se envía el mensaje y se graba "OFF" en la variable

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #53 en: Mayo 10, 2015, 21:08:24 pm »
Me parece una idea estupenda. Cuál sería el comando en Lua para hacer que una variable se fuerce a llamar "ON" en unas condiciones determinadas, por ejemplo. Con eso creo que sabría hacer lo que comentas. Me imagino que sería algo así como "fibaro:setGlobal"?

linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #54 en: Mayo 10, 2015, 21:50:47 pm »
Primero tienes que crear una variable global en paneles -> panel de variables y luego con
fibaro:setGlobal()
fibaro:getGlobal()
asignas u obtienes el valor a/de la variable.
http://www.fibarouk.co.uk/support/lua/library/fibarosetglobal/

Re:Programación LUA
« Respuesta #55 en: Mayo 12, 2015, 14:22:14 pm »
Me ha surgido una duda existencial o quizás sea una idiotez. Cómo funciona una escena en Lua? Me explico. Empieza leyendo desde arriba y cuando llega abajo, empieza de nuevo? La pregunta lo hago porque qué pasa si pongo solo:
Fibaro:call(46)
Entiendo que se encenderá la luz del dispositivo id 46. Pero y si la apago manualmente? Vuelve a encenderse? Es decir, la escena se ejecuta continuamente hasta que la paras?
Pero como paras una escena en Lua sin utilizar una condición que no se cumpla?
A mi no me funciona:
fibaro:abort() y me imagino que es porque la escena "se aborta" en ese punto pero vuelve a empezar. O algo estoy haciendo mal?
Lo único que quiero es hacer en Lua es una escena que se ejecute una vez y nada más. Y quisiera evitar el utilizar condiciones o contadores con variables para conseguirlo.


Enviado desde mi iPhone utilizando Tapatalk

linkey

  • *****
  • 609
    • Ver Perfil
Re:Programación LUA
« Respuesta #56 en: Mayo 12, 2015, 20:50:00 pm »
Las escenas en HC2 no se ejecutan solas, pueden ejecutarse por tres motivos:
 por cambio de una propiedad de un dispositivo
 por cambio del valor de una variable global
 por cualquier otro motivo, puede ser llamada por otra escena o dispositivo virtual, o que la lances manualmente  pulsando el botón ejecutar desde el interfaz web o alguna aplicación para dispositivo móvil. En la cabecera de la escena defines el disparador de la escena "%% properties", "%% globals"
Código: [Seleccionar]
--[[
%% properties
13 value
15 value
 
%% globals
nobre_variable_global
–]]
Adicionalmente, hay escenas que se ejecutan solas nada más ser grabadas o cuando se inicia el HC2, en LUA esto se declara también en la cabecera
Código: [Seleccionar]
--[[
%% autostart
--]]
puedes consultar el motivo que lanzo la escena con:
fibaro:getSourceTrigger()
y decidir en consecuencia que hace el código de la escena a continuación...
la escena ejecuta el código de arriba a abajo, a excepción de las llamadas a funciones, cuando las llamas se ejecutan y retornan al punto de llamada (hay una excepción de la función setTimeout() que ejecuta otras funciones de forma asíncrona, pero mejor no te complico) y, aunque puedes programar bucles en los que la función quede indefinidamente, normalmente terminan.
Tienes que entender el concepto de instancia, que quiere decir que la escena es "carga" en memoria para su ejecución, una escena puede ejecutarse varias veces y puede que en un periodo de tiempo la misma escena se esté ejecutando varias veces (hay varias instancias de la misma escena en memoria), hay veces que quieres que esto suceda, por ejemplo si una misma escena actúa para varios dispositivos, (si se enciende la luz o si se abre la puerta), pero otras veces no quieres que se ejecute la escena si ya se está ejecutando otra instancia de la misma, para eso se suele usar abort(). la función abort() no es necesaria para terminar la escena.

Que lío no se si te he aclarado algo! 

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #57 en: Mayo 13, 2015, 07:40:44 am »
Me lo has aclarado!
Tengo que decir que conocer todos los entresijos de Lua me está costando. Soy persistente y no desespero. Tu ayuda está siendo crucial en mi intento.
Gracias.

Jokin

  • *****
  • 1920
  • Meliorem domum
    • Ver Perfil
Re:Programación LUA
« Respuesta #58 en: Mayo 16, 2015, 23:38:36 pm »
Escribo mi comentario en este hilo porque mi duda creo que sólo se va a poder resolver en Lua.
Resulta que tengo un enchufe Fibaro que tengo debajo del lavabo del aseo donde he enchufado una tira de LEDs que alumbra la parte inferior del lavabo. Muy bonito. Lo que quiero es poder encenderlo sin tener que utilizar un smartphone o similar. Quisiera poderlos encender con un interruptor físico. Como todos los interruptores están destinados a otras luces (todas ellas domotizadas), se me había ocurrido que fuera una secuencia en el manejo del interruptor la que la encienda.
Por ejemplo, se podría hacer que únicamente si el interruptor de la luz principal del aseo se enciende y se apaga 2 veces seguidas en menos de 2 s (ON/OFF/ON/OFF), se encienda el enchufe? Esto permitiría encender la luz fácilmente y sin tener que utilizar un dispositivo externo. Para nota ya sería apagarlo si el interruptor central se pone OFF/ON/OFF/ON/OFF/ON en menos de X segundos.
Sí, necesito cosas un poco raras... ;)
Gracias.

javifrechi

  • ****
  • 322
  • Trasegando
    • Ver Perfil
    • Domótica Doméstica
Re:Programación LUA
« Respuesta #59 en: Mayo 17, 2015, 01:14:02 am »
Lo que quiero es poder encenderlo sin tener que utilizar un smartphone o similar. Quisiera poderlos encender con un interruptor físico. Como todos los interruptores están destinados a otras luces (todas ellas domotizadas), se me había ocurrido que fuera una secuencia en el manejo del interruptor la que la encienda.

Y si a esa tira LED le pones un RGBW de Fibaro y haces una asociación directa o una escena, para que cuando enciendas una de las luces domotizadas, se te encienda la tira LED? Más facil no?
Como se que te gusta el arroz con leche, por debajo de la puerta te meto un adobe.