Example: LogicMachine as gateway to Denver e-Ribbon Fire

Task

This examples will show how to integrate/control Decoflame’s Denver e-Ribbon bio fire system into common KNX/ModBus/BACnet/EnOCean/DALI network through LogicMachine.
Denver e-Ribbon Fire™ is an automatic built-in burner with a continuous, linear flame tray which can be manufactured in any dimensions exclusively by Decoflame.

Connection to Denver e-Ribbon fire system is done over RS-232 port.

Send Function

Add this code to Scripting –> Common Functions

Source code    
  1. function send(dev, req)
  2. local port, b1, b2, cs, data, res, err
  3.  
  4. -- checksum calculation
  5. function getcs(b1, b2)
  6. return 0xFF - bit.band(b1 + b2, 0xFF)
  7. end
  8.  
  9. require('serial')
  10. port = serial.open(dev, { baudrate = 19200 })
  11.  
  12. -- get two bytes from request
  13. b1 = bit.rshift(req, 8)
  14. b1 = bit.band(b1, 0xFF)
  15. b2 = bit.band(req, 0xFF)
  16.  
  17. -- calculate checksum
  18. cs = getcs(b1, b2)
  19.  
  20. -- send data
  21. data = string.char(0x01, b1, b2, cs, 0x04)
  22. port:flush()
  23. port:write(data)
  24.  
  25. -- wait for reply
  26. res, err = port:read(#data, 1)
  27. port:close()
  28.  
  29. -- valid reply
  30. if type(res) == 'string' and #res == #data then
  31. b1, b2, cs = res:byte(2, 4)
  32.  
  33. -- verify checksum
  34. if cs == getcs(b1, b2) then
  35. return b1, b2
  36. -- invalid checksum
  37. else
  38. return nil, 'invalid checksum'
  39. end
  40. -- no reply or invalid reply
  41. else
  42. return nil, err
  43. end
  44. end

Send commands to fire

Add control objects in LogicMachine and specify separate Event-based scripts for each control grp address.
For example, below is script to send ‘flame5’ command.

Source code    
  1. log(send('/dev/RS232', 0x0005))

Statuses from fire

The fire can return statuses based on specific commands e.g. fuel level.
Add following function in Common Functions.

Source code    
  1. function getstatus(port, data)
  2. local b1, b2 = send(port, data)
  3. if b1 then
  4. b1 = bit.band(b1, 0x0F)
  5. b1 = bit.lshift(b1, 8)
  6. return bit.bor(b1, b2)
  7. end
  8. end

Add resident script with necessary time interval to update respective grp addresses with statuses

Source code    
  1. -- fuel level status
  2. fuel = getstatus('/dev/RS232', 0x9000)
  3. if fuel then
  4. grp.update('1/1/1', fuel)
  5. end