Logic Machine Forum
CoolAutomation - CoolMasterNet integration - 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: CoolAutomation - CoolMasterNet integration (/showthread.php?tid=162)



CoolAutomation - CoolMasterNet integration - admin - 14.12.2015

CoolMasterNet device uses TCP instead of RS-232 for communication, so we've updated the script to work with IP.

1. Create a resident script with 0 sleep interval, change 192.168.3.20 to CoolMasterNet device IP. Status information is polled every 3 seconds.

2. Create objects:

All objects must have VRV tag set.

Set object names, using the following scheme (full address and function):
L1.101 on/off - 1-bit, unit on/off control
L1.101 setpoint - unit setpoint, 2-byte floating point
L1.101 mode - unit mode, 1-byte (0 = cool, 1 = heat, 2 = fan, 3 = dry, 4 = auto)
L1.101 fspeed - fan speed, 1-byte (0 = low, 1 = medium, 2 = high, 3 = top, 4 = auto)
L1 on/off - 1-bit, on/off control for all units on a given line
L* on/off - 1-bit, on/off control for all units on all lines

You can create status objects by adding "status" to object name, example:
L1.101 on/off status
L1.101 setpoint status
L1.101 mode status
L1.101 fspeed status
L1.101 temp status - room temperature, 2-byte floating point

Code:
if not client then
  require('socket')
  require('genohm-scada.eibdgm')

  IP = '192.168.3.20'
  PORT = 10102

  -- knx <> coolmaster mapping
  knxtocm = {}
  cmtoknx = {}

  function reverse(src)
    local res = {}

    for k, v in ipairs(src) do
      res[ v ] = k - 1
    end

    return res
  end

  -- integer<>text mode/fspeed value mapping
  modetotext = { 'cool', 'heat', 'fan', 'dry', 'auto' }
  texttomode = reverse(modetotext)
  speedtotext = { 'low', 'med', 'high', 'top', 'auto' }
  texttospeed = reverse(speedtotext)

  -- get all tagged objects and set mapping
  for _, object in ipairs(grp.tag('VRV')) do
    local address, fn, stat = unpack(object.name:split(' '))

    -- status object
    if stat then
      if not cmtoknx[ address ] then
        cmtoknx[ address ] = {}
      end

      cmtoknx[ address ][ fn ] = {
        id = object.id,
        value = grp.getvalue(object.id),
      }
    -- control object
    else
      knxtocm[ object.id ] = {
        address = address,
        fn = fn,
      }
    end
  end

  function checkerror(res, err)
    if not res then
      sock:close()
      sock = nil
      alert('CoolMaster error: %s', tostring(err))
    end

    return res, err
  end

  function connect()
    sock = socket.tcp()
    sock:settimeout(5)

    return checkerror(sock:connect(IP, PORT))
  end

  function send(data)
    if not sock then
      connect()
    end

    if sock then
      checkerror(sock:send(data))
    end
  end

  -- read single line from socket
  function readline()
    if not sock then
      connect()
    end

    if sock then
      return checkerror(sock:receive())
    end
  end

  function updateknx(address, fn, value, datatype)
    local object = cmtoknx[ address ] and cmtoknx[ address ][ fn ] or nil
    -- object not found
    if not object then
      return
    end

    -- no value or same value, no update required
    if value == nil or object.value == value then
      return
    end

    -- save new value and write to knx
    object.value = value
    grp.write(object.id, value, datatype)
  end

  function parseline(line)
    local address, status, setpoint, temp, speed, mode

    line = line:gsub('>', '')
    address = line:sub(1, 6)

    -- address is invalid, cannot parse line
    if address:sub(1, 1) ~= 'L' then
      return
    end

    -- on/off status
    status = line:sub(8, 9):lower() == 'on'
    updateknx(address, 'on/off', status, dt.bool)

    -- setpoint is integer
    setpoint = line:sub(12, 13)
    setpoint = tonumber(setpoint)
    updateknx(address, 'setpoint', setpoint, dt.float16)

    -- room temp is float, separated by comma
    temp = line:sub(16, 17)
    temp = tonumber(temp)
    updateknx(address, 'temp', temp, dt.float16)

    -- speed: low, med, high, auto
    speed = line:sub(20, 23):lower():trim()
    updateknx(address, 'fspeed', texttospeed[ speed ], dt.uint8)

    -- mode: cool, heat, fan, dry, auto
    mode = line:sub(25, 28):lower():trim()
    updateknx(address, 'mode', texttomode[ mode ], dt.uint8)
  end

  -- read current status
  function readstat()
    send('ls\r\n')

    -- read until error or end of stat
    while true do
      local line = readline()

      -- timeout or end occured
      if not line or line == 'OK' then
        break
      end

      parseline(line)
    end
  end

  -- handle group writes
  function eventhandler(event)
    local object, cmd, value, param

    object = knxtocm[ event.dstraw ]
    -- knx object not mapped, ignore
    if not object then
      return
    end

    -- on/off - boolean
    if object.fn == 'on/off' then
      value = knxdatatype.decode(event.datahex, dt.bool)
      cmd = value and 'on' or 'off'
    -- setpoint - floating point
    elseif object.fn == 'setpoint' then
      value = knxdatatype.decode(event.datahex, dt.float16)
      param = string.format('%.1f', value)
      cmd = 'temp'
    -- mode (fan, dry, auto)
    elseif object.fn == 'mode' then
      value = knxdatatype.decode(event.datahex, dt.uint8)
      cmd = modetotext[ value + 1 ]
    -- speed (low, medium, high, auto)
    elseif object.fn == 'fspeed' then
      value = knxdatatype.decode(event.datahex, dt.uint8)
      param = speedtotext[ value + 1 ]

      if param then
        cmd = 'fspeed'
      end
    end

    -- got valid command
    if cmd then
      -- append address to command
      cmd = cmd .. ' ' .. object.address

      -- append additional parameter if set
      if param then
        cmd = cmd .. ' ' .. param
      end

      send(cmd .. '\r\n')

      readline() -- command result
    end
  end

  -- knx connection
  client = eibdgm:new({ timeout = 1 })
  client:sethandler('groupwrite', eventhandler)

  -- start-up time
  sec, usec = os.microtime()
end

-- handle knx
client:step()

-- read stats every 3 seconds
diff = os.udifftime(sec, usec)
if diff < 0 or diff >= 3 then
  readstat()
  sec, usec = os.microtime()
end



RE: CoolAutomation - CoolMasterNet integration - Torstein - 25.06.2020

Hello!

I need some assistance/direction with a Lua script, please.

I have installed a Clipsal 5500SHAC:
https://www.clipsal.com/products/detail?CatNo=5500SHAC&backto=%2Fsearch%3Fq%3D5500shac&tab-document-1=0

I have installed a CoolMasterNet to integrate with the Daikin VRV system. The CoolMasterNet has been configured and is working correctly. It is connected via IP.
https://coolautomation.com/news/c-bus-by-schneider-electric-hvac-vrf/

I need some assistance with the Lua script, please?

Thank you!
Torstein.


RE: CoolAutomation - CoolMasterNet integration - Daniel - 25.06.2020

This script was created for LM,W4k,SL it will not work for NAC as they have different functions to write to objects. It require a bit of modifications.
in NAC Keywoards = TAG


RE: CoolAutomation - CoolMasterNet integration - Torstein - 25.06.2020

(25.06.2020, 07:47)Daniel. Wrote: This script was created for LM,W4k,SL it will not work for NAC as they have different functions to write to objects.  It require a bit of modifications.
in NAC Keywoards = TAG
Thanks Daniel! Is there any way I can arrange for the required modifications to be done?
Thanks,
T.