Logic Machine Forum
template for generic drivers - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: template for generic drivers (/showthread.php?tid=842)



template for generic drivers - rocfusion - 16.06.2017

Hi,

Maybe this helps someone.  Here is basic bi-directional example for connecting the LM to some device that is controlled over TCP.

Thanks,

Roger


Place a resident script with a sleep interval of 0

Code:
if not ready then
 socket = require("socket")
 copas = require("copas")
 alert('not Ready')
 ready=true
 
 function parse(data)
  alert('parsing: %s', data)
   -- use this function to parse the data you receive from the tcp device
 end

  function sendTo(command)
   skt:send(command)
   --optional delay between commands sent tcp device you are controlling
   sleep(1)
  end
   
 function fromKNX(command)
  alert('from knx: %s', command)
   local telegram = string.split(command,',')
   -- for every object that has the event script
   if(telegram[1]=='1/1/1')then      
      sendTo('thisComand ='..telegram[2]..'\r')
   end
 end

  -- use this function to get the status of the remote tcp device
  function init()
   alert('Getting status of tcp device')
   sendTo('some command \r')

  end
 
 local server = socket.udp()
 server:setsockname("127.0.0.1",23456)
 function handler(skts)
   skts = copas.wrap(skts)
   alert("UDP connection handler")
   while true do
     local s, err
     alert("UDP receiving...")
     s, erro = skts:receive(2048)
     if not s then
       alert("UDP Receive error: ", erro)
       break
     end
     alert("Received data, bytes: "..s)
     fromKNX(s)
   end
 end
 copas.addserver(server, handler, 1)  
end

if not skt then
  -- create tcp client
  skt, err = socket.connect('10.10.10.41', 4999)
  -- when theres no error connect ok, initialize
  if(not err) then
    skt:settimeout(0)
    -- add receive thread
    copas.addthread(function()
        while true do
          local resp,err = copas.receive(skt)
          -- if theres no connection start a new connection
          if not resp then
            alert("[tcp-client] Receive error: %s", err)
            copas.removeserver(skt)
            skt = nil
            break
          end
          parse(resp)
        end
      end)
    if skt then
      alert('[tcp-client] connection ok')
      -- optional init function use to get initial status of remote device
      -- init()
    -- error while connecting,
    else
      if warningfailed then alert('[tcp-client] connection failed (conn): %s', err) end
      return
    end
  else
    alert('[tcp-client] error connecting %s',err)
    return
  end
end

copas.loop()

Create event based script for
Code:
if event.type=='groupwrite' then
 require('socket')
 local client = socket.udp()
 local evt = event.dst..','..tostring(event.getvalue())
 if client then
   client:sendto(evt, '127.0.0.1', 23456)
   client:close()
 end
elseif event.type =='groupread' then
 grp.response(event.dst,event.getvalue())
end



RE: template for generic drivers - rocfusion - 01.07.2017

Hi,

Maybe someone has an idea, based on the above template. I have this TCP device which the LM is controlling. In this case you set a color light value. The light changes to the requested value by cycling through values and returning back a status for each light change. Now there is one caveat, I can bring this light on from the off state to a particular color with the exception of white. When I turn on white it will cycle through to the last light color that was previously on and then the what value has to be resent to get it to change. The time taken to change between any color is variable, changing from one color to another is not always the same. The number of times I receive a the status that the light is changing color is inconsistent.

For example, I wish to turn the light to white and the last color the light was on with was green.

SEND GOTO WHITE

1 sec later, received LIGHT IS GREEN
1.1 sec later, received LIGHT IS GREEN
0.5 sec later, received LIGHT IS GREEN
2 sec later, received LIGHT IS GREEN
1 sec later, received LIGHT IS GREEN
1.5 sec later, received LIGHT IS GREEN

NOW I SEND GOTO WHITE

Now for some light colors I may have to wait for 42 responses before I can change to white.

My idea is to create some kind of timer every time a status is received. This gets cancelled on receiving a new status. When the timer is reached then send the request to change to white.

Now my question is how can I realize this when working with my template. Using Sleep is not really an option because whilst the status of the light is coming back there can be other status values coming back. Is there a way to delay a non blocking function call with the option to cancel it in LUA?

Thanks,


Roger


RE: template for generic drivers - rocfusion - 03.07.2017

Nobody has an idea?


RE: template for generic drivers - admin - 04.07.2017

Have a look at this script, it has timers together with receiving data from a socket:
https://forum.logicmachine.net/showthread.php?tid=539&pid=2945#pid2945


RE: template for generic drivers - rocfusion - 04.07.2017

Hi,

That script I understand, in my script above I am working with Copas, its like nothing is being executed unless there is a send or receive to\from the socket.

Thanks,

Roger


RE: template for generic drivers - admin - 04.07.2017

You have to use copas.step instead of copas.loop


RE: template for generic drivers - rocfusion - 04.07.2017

Ok when I use step that code would only execute every time the socket is sending or receiving something.


RE: template for generic drivers - rocfusion - 04.07.2017

Hi Admin,

I figured it out.  I can use copas to add a new thread, then put it to sleep until its needed.


Code:
 co = copas.addthread(function()
    while true do
      copas.sleep(2) -- wait 2 seconds
      alert("send some command")
      copas.sleep(-1) -- put the thread to sleep until wakeup is called
    end
  end)



then when I need to activate it I use

Code:
copas.wakeup(co)



Thanks,


Roger