Example: Use LM2 as TCP client for reading data from Home Theater

Task

Resident program

Source code    
  1. -- first call
  2. if not ready then
  3. require('socket')
  4.  
  5. warningclosed = true
  6. warningfailed = true
  7. warningerrors = true
  8. warningtimeou = true
  9. denonstatus = false
  10. lastdatareceived = nil
  11.  
  12. -- incoming command parser
  13. function parse(data)
  14. if data == 'PWON' then
  15. denonstatus = true
  16. elseif data == 'PWSTANDBY' then
  17. denonstatus = false
  18. elseif string.sub(data, 1, 4) == 'NSE0' then
  19. grp.write('5/2/2', string.sub(data, 5))
  20. elseif string.sub(data, 1, 4) == 'NSE1' then
  21. grp.write('5/2/3', string.sub(data, 5))
  22. else
  23. -- log other info, not mapped, if useful
  24. log(data)
  25. end
  26.  
  27. -- check if Denon changed status and sent new Object value in the bus only for changes
  28. currentdenonstatus = grp.getvalue('5/2/1')
  29. if currentdenonstatus ~= denonstatus then
  30. grp.write('5/2/1', denonstatus)
  31. end
  32. end
  33.  
  34. ready = true
  35. end
  36.  
  37. -- client connected
  38. if connected then
  39. -- send status request, in order to keep the socket live
  40. -- Denon sends PWON each second automatically on the socket, no request necessary
  41. --client:send('PW?\r')
  42.  
  43. while true do
  44. char, err = client:receive(1)
  45.  
  46. if char ~= nil then
  47. lastdatareceived = os.time()
  48. warningclosed = true
  49. warningfailed = true
  50. warningerrors = true
  51. warningtimeou = true
  52. else
  53. now = os.time()
  54. deltatime = now - lastdatareceived
  55. end
  56.  
  57. -- error while receiving, timeout or closed socket
  58. if err then
  59. -- remote server closed connection, reconnect
  60. if err == 'closed' then
  61. connected = false
  62. if warningclosed then alert('[tcp-client] connection closed') end
  63. warningclosed = false
  64. sleep(1)
  65. elseif err == 'timeout' then
  66. connected = false
  67. if warningtimeou then alert('[tcp-client] connection timeout') end
  68. warningtimeou = false
  69. sleep(1)
  70. elseif warningerrors then alert('[tcp-client] connection failed: %s', err)
  71. warningerrors = false
  72. end
  73.  
  74. break
  75.  
  76. -- end of line, parse buffer
  77. elseif char == '\r' then
  78. data = table.concat(buffer)
  79. parse(data)
  80. buffer = {}
  81.  
  82. -- wait some time before next request
  83. --sleep(1)
  84.  
  85. break
  86. -- other char, add to buffer
  87. else
  88. table.insert(buffer, char)
  89. end
  90. end
  91. -- first call or previously disconnected
  92. else
  93. -- close previous connection when disconnected
  94. if client then
  95. client:close()
  96. client = nil
  97. end
  98.  
  99. -- create tcp client
  100. client = socket.tcp()
  101. client:settimeout(5)
  102. connected, err = client:connect('172.16.1.111', 23)
  103.  
  104. -- connect ok, reset buffer
  105. if connected then
  106. lastdatareceived = os.time()
  107. warningclosed = true
  108. warningfailed = true
  109. warningerrors = true
  110. warningtimeou = true
  111. alert('[tcp-client] connection ok')
  112. buffer = {}
  113. sleep(5)
  114. -- error while connecting,
  115. else
  116. if warningfailed then alert('[tcp-client] connection failed (conn): %s', err) end
  117. warningfailed = false
  118. sleep(5)
  119. end
  120. end

Logic Machine output

  • TCP connection state – OK, closed, timeout, failed

  • Log other info, not mapped, if useful

  • Object values

Other Denon control protocol

You can download Denon device protocol here to see on more what information you can receive from your player.

Denon protocol

 

 

Created by Giovanni Aduso from Schüco