User Tools

Site Tools


helvar

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Next revision
Previous revision
helvar [2023/05/19 13:14] – created emozolyakhelvar [2023/09/22 14:33] (current) emozolyak
Line 1: Line 1:
-====== Helvar light control comm. protocol ======+====== Helvar light control communication protocol ====== 
 + 
 +Please refer to the [[https://aca.im/driver_docs/Helvar/HelvarNet-Overview.pdf|HelvarNet communication protocol]] for usage.  
 +This protocol is using ASCII messaging. According to the documentation the routers in the lighting system support either ASCII or RAW format.  
 + 
 +<WRAP center round box 80%> 
 +**Message Format** 
 +Any message sent to, or received from, a router can be in either ASCII or raw binary form (see 
 +Command Format for more information). 
 +Messages must not exceed the maximum length of 1500 bytes. 
 +The format of the data contained within messages is defined by the protocol. 
 +A query reply message from the router will be in the same format as the query command message 
 +sent i.e. if a query message is sent in ASCII form then the reply will also be in ASCII. 
 +</WRAP> 
 + 
 +The usage of this protocol is as follows: 
 + 
 +  *Your application logic, e.g. recipe selection boxes on the dashboards chooses scenario id and writes it to the register  
 +  *Lua script monitors scenes ids written and converts them to the strings according to the HelvarNet protocol and application logic 
 + 
 +<WRAP center round important 80%> 
 +Please be informed this protocol relays your HelvarNet string to the TCP address:port. It does not provide your application logic. Prepare proper dictionaries, templates or mapping rules to compose messages in your application.  
 +</WRAP> 
 + 
 + 
 +<WRAP center round box 80%> 
 +For example, in the command Recall Group 1234, Block 5, Scene 6, Fade Time 32 s, the string is 
 +sent as follows, including the delimiters and the start character '>' and stop character '#': 
 +">V:1,C:11,G:1234,B:5,S:6,F:3200#" 
 +</WRAP> 
 + 
 +  *So the string like ">V:1,C:11,G:1234,B:5,S:6,F:3200#" should be written to the register named CMD0 in the project.  
 +  *Once the string is written to the CMD0 register, it is sent to the remote device to the TCP port assigned in the connection settings.  
 +  *The response (which can be multipart) is stored in the same register  
  
 <code lua> <code lua>
Line 5: Line 39:
 PARTIAL_ETX = '$' PARTIAL_ETX = '$'
 FULL_ETX    = '#' FULL_ETX    = '#'
 + 
 function onScanStart () function onScanStart ()
     now = os.time()     now = os.time()
Line 13: Line 47:
    addDevice{name = "CMD",     shift = 0, base = 10, xtraFields = {} }    addDevice{name = "CMD",     shift = 0, base = 10, xtraFields = {} }
 end  end 
 + 
 function readRegister (reg, device, unitId) function readRegister (reg, device, unitId)
- 
     if (not readBuffer) then      if (not readBuffer) then 
         readBuffer = 'no data'          readBuffer = 'no data' 
     end      end 
-     +    return readBuffer 
-    return readBuffer -- will be assinged in writeRegister+
 end  end 
 + 
 function writeRegister (reg, device, unitId, newValue) function writeRegister (reg, device, unitId, newValue)
-     +  
-    sendString_(newValue) -- expects string to be written externally  +   sendString_(newValue) -- expects string to be written externally  
-    + 
    local buf = {}     local buf = {} 
 +   local tryCount = 0
        
    repeat     repeat 
 +       tryCount = tryCount + 1 ; DEBUG('tryCount = ' .. tryCount)
 +       
        local currentFrame = readUntil(PARTIAL_ETX, FULL_ETX)         local currentFrame = readUntil(PARTIAL_ETX, FULL_ETX) 
-       local lastChar 
        if currentFrame then         if currentFrame then 
            table.insert(buf, currentFrame)            table.insert(buf, currentFrame)
            lastChar = currentFrame[#currentFrame]            lastChar = currentFrame[#currentFrame]
        end         end 
-        +    until (lastChar == FULL_ETX or tryCount > 3)
-   until (not lastChar or (lastChar == FULL_ETX))+
        
-   if (#buf > 0) then  +    if (lastChar == FULL_ETX) then  
-        readBuffer = table.concat(buf) +        readBuffer = buf  
-   end  +        return true  
- +    end  
-   return true +     
 +    readBuffer = 'read bad data!' 
 +    return true 
 end end
 + 
 -------------------------- Helpers -------------------------- -------------------------- Helpers --------------------------
 + 
 function sendString_(s) -- new sendString version  function sendString_(s) -- new sendString version 
 + 
     local sendBuf = {}      local sendBuf = {} 
    
Line 57: Line 92:
     sendBytes(sendBuf)     sendBytes(sendBuf)
 end end
 + 
 function readUntil(endByte1, endByte2) -- read input buffer untils endByte(s) or timeout  function readUntil(endByte1, endByte2) -- read input buffer untils endByte(s) or timeout 
 +    DEBUG("Entered readUntil.")
 +    
     local ONE_BYTE = 1      local ONE_BYTE = 1 
-    local buf = {}+    local buf, rb = {}, nil  
 +    
     repeat      repeat 
-        local rb = readBytes(ONE_BYTE) +        rb = readBytes(ONE_BYTE) 
         if rb then          if rb then 
-            rb = rb[ONE_BYTE]+            rb = rb[ONE_BYTE]          ; DEBUG('read byte: ' .. string.char(rb))
             table.insert(buf, rb)             table.insert(buf, rb)
         end          end 
     until (not rb or (rb == endByte1 or rb == endByte2))     until (not rb or (rb == endByte1 or rb == endByte2))
- +     
-    return ((#buf >= ONE_BYTE) and bufor false +    DEBUG("Exit on rb = " .. tostring(rb) ) 
 +    DEBUG('buf = ' .. table.concat(buf, ' ')) 
 +     
 +    if (#buf > 0) and (buf[#buf] == endByte1 or buf[#buf] == endByte2) then  
 +        DEBUG('Got right frame : ') return buf  
 +    else  
 +        DEBUG('Got wrong frame : ') ; return false  
 +    end 
 end  end 
 </code> </code>
  
helvar.txt · Last modified: 2023/09/22 14:33 by emozolyak

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki