User Tools

Site Tools


hydrus-flowmeter

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
Last revisionBoth sides next revision
hydrus-flowmeter [2023/08/17 10:41] emozolyakhydrus-flowmeter [2024/02/20 14:40] – [Connecting to DIEHL HYDRUS flowmeter] emozolyak
Line 1: Line 1:
-{{ :custom_protocols:mbus:hydrus-meter-for-mbus.jpg?direct&200|}}+{{ :custom_protocols:mbus:hydrus-meter-for-mbus.jpg?direct&150|}} 
 +====== Connecting to DIEHL HYDRUS flowmeter ====== 
 + 
 +<WRAP center round info 80%> 
 +Highly accurate, lead-free brass ultrasonic smart water meter for residential, commercial and industrial installations. It has Mbus onboard. 
 +</WRAP> 
 + 
 + 
 +----
  
-====== Connecting to HYDRUS by DIEHL flowmeter  ====== 
  
 <code lua> <code lua>
Line 9: Line 16:
 end  end 
  
-POLL_DELAY    = 60 -- poll rate constant in sec. +POLL_DELAY    = 60 * 15  -- poll rate constant in sec. 
 HEX_NUMBERING = 16 -- numbering system conversion  HEX_NUMBERING = 16 -- numbering system conversion 
  
Line 28: Line 35:
     end      end 
 end  end 
 +-- prints any parameters 
 function DBG(...)  function DBG(...) 
     for i = 1, #arg do      for i = 1, #arg do 
Line 41: Line 48:
  
 ------ Table helpers ----------------------------- ------ Table helpers -----------------------------
-function table.findPattern(t, pttrn) -- finds pattern in a table  tableFindPattern+function table.findPattern(t, pttrn) 
    
     for tabIndex, _ in ipairs(t) do      for tabIndex, _ in ipairs(t) do 
Line 53: Line 60:
             end              end 
         end         end
-  
         if matchFlag then          if matchFlag then 
-            return (tabIndex + #pttrn) -- start of data +            return (tabIndex + #pttrn) 
         end          end 
     end      end 
Line 61: Line 67:
 end  end 
    
-function table.sub(t, startIndex, endIndex) -- picks sub-table from a table +function table.sub(t, startIndex, endIndex) 
     local tmpTable = {}     local tmpTable = {}
     for k = startIndex, endIndex do      for k = startIndex, endIndex do 
Line 69: Line 75:
 end  end 
    
-table.hexView = function(hextab, spacer) -- get string of a hex view for a table  tabHexView+table.hexView = function(hextab, spacer) 
     local hex = {}      local hex = {} 
     for _, hexbyte in ipairs(hextab) do      for _, hexbyte in ipairs(hextab) do 
Line 82: Line 88:
     return tonumber(hex)     return tonumber(hex)
 end  end 
 +-- integer convertions 
 +table.int = function(t)
 +   return tonumber(table.hexView(t), HEX_NUMBERING) 
 +end  
 +
    
-function getHexByteAsStr(inputByte) -- gets 2 - char hex string of a byte + -- gets 2 - char hex string of a byte  
 +function getHexByteAsStr(inputByte) 
     local strByte = string.format("%X", inputByte)         local strByte = string.format("%X", inputByte)    
     return (#strByte == 1 and '0' .. strByte) or strByte     return (#strByte == 1 and '0' .. strByte) or strByte
 end  end 
  
-table.reverse = function (tab) -- reverses a table   reverseTable+table.reverse = function (tab) 
     local outTable = {}     local outTable = {}
     for i = #tab, 1, -1 do      for i = #tab, 1, -1 do 
Line 103: Line 115:
 CTRL_LONG_FRAME_STX = 0x68 CTRL_LONG_FRAME_STX = 0x68
  
-REQ_UD2             = 0x7B -- Request for Class 2 Data  +REQ_UD2             = 0x7B -- Request for Class 2 Data  FCB  
-REQ_UD2_            = 0x5B -- Request for Class 2 Data +REQ_UD2_            = 0x5B -- Request for Class 2 Data  Frame count bit 
  
 BRDCAST_NET_LAYER_ADDR = 0xFD  -- 253  BRDCAST_NET_LAYER_ADDR = 0xFD  -- 253 
Line 120: Line 132:
  
 dataHandlers = { dataHandlers = {
-    volume = {pattern = {0xC, 0x14}, length = 4, func = table.bcd},  +    volume = {pattern = {0xC, 0x14},       length = 4, func = table.bcd},  
-    flow   = {pattern = {0xB, 0x3C}, length = 3, func = table.bcd}, +    flow   = {pattern = {0xB, 0x3C},       length = 3, func = table.bcd}, 
-    tint   = {pattern = {0xA, 0x5A}, length = 2, func = table.bcd}, +    tint   = {pattern = {0xA, 0x5A},       length = 2, func = table.bcd}, 
-    text   = {pattern = {0xA, 0x66}, length = 2, func = table.bcd}+    text   = {pattern = {0xA, 0x66},       length = 2, func = table.bcd}, 
 +    err    {pattern = {0x4, 0xFD, 0x17}, length = 4, func = table.int}
 } }
  
Line 131: Line 144:
    addDevice{name = "TI",     shift = 0, base = 10, xtraFields = {'temp. internal' }       addDevice{name = "TI",     shift = 0, base = 10, xtraFields = {'temp. internal' }   
    addDevice{name = "TE",     shift = 0, base = 10, xtraFields = {'temp. external' }       addDevice{name = "TE",     shift = 0, base = 10, xtraFields = {'temp. external' }   
 +   addDevice{name = "ERR",     shift = 0, base = 10, xtraFields = {'error flags' }   
 end  end 
  
Line 137: Line 151:
     if (not lastReadTimeStamp or (now - lastReadTimeStamp) >= POLL_DELAY ) then      if (not lastReadTimeStamp or (now - lastReadTimeStamp) >= POLL_DELAY ) then 
    
-        PROBE_PACKET[PROBE_PACKET_CRC_POS] = getCRC(PROBE_PACKET, REQ_UD2_POS, PROBE_PACKET_PAYLOAD_LEN)+        PROBE_PACKET[PROBE_PACKET_CRC_POS] = getCRC(PROBE_PACKET 
 +                                                    , REQ_UD2_POS 
 +                                                    , PROBE_PACKET_PAYLOAD_LEN)
    
         if (not sendBytes(PROBE_PACKET) ) then         if (not sendBytes(PROBE_PACKET) ) then
Line 145: Line 161:
    
         local meterDataFrame = readUntil(ETX)          local meterDataFrame = readUntil(ETX) 
-  
         if (#meterDataFrame > 10) then         if (#meterDataFrame > 10) then
             -- parsing              -- parsing 
             for param, struc in pairs(dataHandlers) do              for param, struc in pairs(dataHandlers) do 
-                 
                 local foundPos = table.findPattern(meterDataFrame, struc.pattern)                 local foundPos = table.findPattern(meterDataFrame, struc.pattern)
                 if foundPos then                 if foundPos then
-                                                                                    DBG('found data at: ', foundPos)+                    DBG('found data for ' .. param ..' at: ', foundPos) 
 +                    local foundBytes = table.sub(meterDataFrame, foundPos 
 +                                                               , foundPos + struc.length - 1)  
 +                    DBG('found bytes: ', foundBytes) 
 +                    foundBytes = table.reverse(foundBytes)    
 +                    DBG("After reverse: ", foundBytes) 
 +                    local actualData = struc.func(foundBytes)      
 +                    DBG("actualData: ", actualData) 
 +                    data[param] = actualData 
 +                    
                     lastReadTimeStamp = now                      lastReadTimeStamp = now 
-                    local foundBytes = table.sub(meterDataFrame, foundPos 
-                                                               , foundPos + struc.length - 1) ; DBG('found bytes: ', foundBytes) 
-                    foundBytes = table.reverse(foundBytes)   ; DBG("After reverse: ", foundBytes) 
-                    data[param] = struc.func(foundBytes)     ; DBG("Data - param: ", data[param]) 
                 else                  else 
                     ERROR("failed to find data !")                     ERROR("failed to find data !")
-                    data = false     +                    data[param] = false     
                 end                 end
             end              end 
Line 169: Line 188:
     end      end 
          
-    if (device.name == 'V') then return data["volume"end  +    if (device.name == 'V'  then return data.volume end  
-    if (device.name == 'Q') then return data["flow"end  +    if (device.name == 'Q'  then return data.flow   end  
-    if (device.name == 'TI') then return data.tint end  +    if (device.name == 'TI' then return data.tint   end  
-    if (device.name == 'TE') then return data.text end +    if (device.name == 'TE' then return data.text   end  
 +    if (device.name == 'ERR') then return data.err    end 
    
 end  end 
Line 181: Line 201:
 -------------------------- Other helpers -------------------------- -------------------------- Other helpers --------------------------
    
-function readUntil(endByte) -- read input buffer untils endByte or timeout  +function readUntil(endByte)  
-    local ONE_BYTE = 1  +    local ONE_BYTE, buf = 1, {}  
-    local buf = {}+    
     repeat      repeat 
         local rx = readBytes(ONE_BYTE)          local rx = readBytes(ONE_BYTE) 
         if rx then          if rx then 
-            rx = rx[1] +            rx = rx[1] table.insert(buf, rx)
-            table.insert(buf, rx)+
         end          end 
     until (not rx or (rx == endByte))     until (not rx or (rx == endByte))
Line 195: Line 214:
 end  end 
  
-function getCRC(a, pos, len)   -- calc. CRC sum for the mbus packet +function getCRC(a, pos, len)   
     local sum, mask  = 0, 0xFF     local sum, mask  = 0, 0xFF
    
Line 203: Line 222:
     end      end 
     return sum     return sum
-end  +end </code>
- +
- +
- +
-</code>+
  
hydrus-flowmeter.txt · Last modified: 2024/02/20 14:42 by emozolyak

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki