LogicMachine Forum
Curtain Dooya dt82tv - Printable Version

+- LogicMachine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Gateway (https://forum.logicmachine.net/forumdisplay.php?fid=10)
+--- Thread: Curtain Dooya dt82tv (/showthread.php?tid=6290)



Curtain Dooya dt82tv - Zhiger2003 - 02.02.2026

Hello. I need to connect Dooya DT82TV electric curtains to a controller and control them via the RS-485 protocol. There are several problems. First, the curtains understand HEX(photo is attached) rather than the usual 0/1 or true/false, so I probably need to write code for conversion and understanding. Second, I also need a JSON profile (also code) to connect each device via Modbus. To be honest, I don't know how to program or write scripts at all. I would be very grateful if there was ready-made code and instructions on how to do everything.


RE: Curtain Dooya dt82tv - Daniel - 02.02.2026

How do you knw that they are modbus? Do you have any documentation? You cannot haev modbus and custom RS485 script running paraleal.


RE: Curtain Dooya dt82tv - admin - 02.02.2026

You can't use a profile because this is a custom protocol not Modbus.

For testing purposes use an event script. Change baudrate, parity and command bytes as needed.
Code:
require('serial')

port = serial.open('/dev/RS485-1', {
  baudrate = 9600,
  parity = 'even',
  duplex = 'half'
})

command = string.char(0x55, 0x01, 0x01, 0x03, 0x02, 0xF9, 0x01)
port:write(command)

If the test script works then it can be modified to send different commands depending on the input value. 4-bit value should work (e.g. up/down/stop).


RE: Curtain Dooya dt82tv - Zhiger2003 - 04.02.2026

(02.02.2026, 13:01)admin Wrote: You can't use a profile because this is a custom protocol not Modbus.

For testing purposes use an event script. Change baudrate, parity and command bytes as needed.
Code:
require('serial')

port = serial.open('/dev/RS485-1', {
  baudrate = 9600,
  parity = 'even',
  duplex = 'half'
})

command = string.char(0x55, 0x01, 0x01, 0x03, 0x02, 0xF9, 0x01)
port:write(command)

If the test script works then it can be modified to send different commands depending on the input value. 4-bit value should work (e.g. up/down/stop).

Thanks its working. Now i have another question, is it possible to give it a range with event script?


RE: Curtain Dooya dt82tv - Daniel - 04.02.2026

What do you mean by range? Do you want to stop it after a time? If yes then you can add os.delay(10) on the ened and then send stop command. Make sure to set event script execution to First instance only.


RE: Curtain Dooya dt82tv - admin - 04.02.2026

Attach an event script to a 4-bit object. A different command is sent depending on the input value (stop, up or down).
Code:
value = event.getvalue()

up = bit.band(value, 8) ~= 0
stop = bit.band(value, 7) == 0

if stop then
  command = string.char(0x55, 0x01, 0x01, 0x03, 0x03, 0x38, 0xC1)
elseif up then
  command = string.char(0x55, 0x01, 0x01, 0x03, 0x02, 0xF9, 0x01)
else
  command = string.char(0x55, 0x01, 0x01, 0x03, 0x01, 0xB9, 0x00)
end

require('serial')

port = serial.open('/dev/RS485-1', {
  baudrate = 9600,
  parity = 'even',
  duplex = 'half'
})

port:write(command)



RE: Curtain Dooya dt82tv - AEK - 05.02.2026

(04.02.2026, 04:42)Zhiger2003 Wrote:
(02.02.2026, 13:01)admin Wrote: You can't use a profile because this is a custom protocol not Modbus.

For testing purposes use an event script. Change baudrate, parity and command bytes as needed.
Code:
require('serial')

port = serial.open('/dev/RS485-1', {
  baudrate = 9600,
  parity = 'even',
  duplex = 'half'
})

command = string.char(0x55, 0x01, 0x01, 0x03, 0x02, 0xF9, 0x01)
port:write(command)

If the test script works then it can be modified to send different commands depending on the input value. 4-bit value should work (e.g. up/down/stop).

Thanks its working. Now i have another question, is it possible to give it a range with event script?

Hi, I made this integration/ see the scripts
This one make string comand to send to rs485 port (with CRC calculation)
Code:
function cmd_str_crc (t)
    if type(t) ~= 'table' then
      log('входная переменная не таблица')
      return
      end
    x, y = CRC16(t)
    --log(x,y)
    table.insert(t,x)
    table.insert(t,y)
    --log(t)
    s=''
    for i = 1 , #t do
      s = s..string.char(t[i])
      end
    return s
    end
 
  function And(num1,num2)
      local tmp1 = num1
      local tmp2 = num2
      local ret = 0
      local count = 0
      repeat
          local s1 = tmp1 % 2
          local s2 = tmp2 % 2
          if s1 == s2 and s1 == 1 then
              ret = ret + 2^count
          end
          tmp1 = math.modf(tmp1/2)
          tmp2 = math.modf(tmp2/2)
          count = count + 1
      until(tmp1 == 0 and tmp2 == 0)
      return ret
  end
   
  function Xor(num1,num2)
      local tmp1 = num1
      local tmp2 = num2
      local ret = 0
      local count = 0
      repeat
          local s1 = tmp1 % 2
          local s2 = tmp2 % 2
          if s1 ~= s2 then
              ret = ret + 2^count
          end
          tmp1 = math.modf(tmp1/2)
          tmp2 = math.modf(tmp2/2)
          count = count + 1
      until(tmp1 == 0 and tmp2 == 0)
      return ret
  end
   
  function bit_rshift(value,n)
      value = math.modf(value / (2^n))
      return value
  end
 
  function CRC16(arr)
      local tmp = 0xffff
      for i=1,#arr do
          tmp = Xor(arr[i],tmp)
          for j=1,8 do
              local tmp1 = And(tmp,0x01)
              if tmp1 == 1 then
                  tmp = bit_rshift(tmp,1)
                  tmp = Xor(tmp,0xa001)
              else
                  tmp = bit_rshift(tmp,1)
              end
          end
      end
      local ret1 = (tmp % 256)
      local ret2 = math.modf( tmp / 256)
      return ret1,ret2
  end
 
  function motor_up(cur_group, cur_adr)
    cmd = {cur_group, cur_adr, 0x03,0x01}
    s = cmd_str_crc (cmd)
    return s
    end
 
 
  function motor_down(cur_group, cur_adr)
    cmd = {cur_group, cur_adr, 0x03,0x02}
    s = cmd_str_crc (cmd)
    return s
    end
 
  function motor_stop(cur_group, cur_adr)
    cmd = {cur_group, cur_adr, 0x03,0x03}
    s = cmd_str_crc (cmd)
    return s
    end
 
  function motor_set_address(cur_group, cur_adr, new_group, new_adr)
    cmd = {cur_group, cur_adr,0x02, 0x00, 0x02, new_group, new_adr}
    s = cmd_str_crc (cmd)
    return s
    end
this one shows how to send 1 command
Code:
require('user.motor')
require('serial')
port = serial.open('/dev/RS485-1', {
  baudrate = 9600,
  databits = 8,
  stopbits = 1,
  parity = 'none',
  duplex = 'half'
})
-- движение
t = { 0x55, 0x03, 0x02, 0x03,0x01}
s = cmd_str_crc (t)
port:write(s)
os.sleep(2)
-- остановка
t = { 0x55, 0x03, 0x02, 0x03,0x03}
s = cmd_str_crc (t)
port:write(s)
--[[
-- запись адреса
t = { 0x55, 0x00, 0x00, 0x02,0x02, 0x01, 0x02}
s = cmd_str_crc (t)
port:write(s)
]]
And this is a deamon for several motors
Code:
-- kotov motors deamon
if not port then
    require('serial')
  port = serial.open('/dev/RS485-1', {
    baudrate = 9600,
    databits = 8,
    stopbits = 1,
    parity = 'none',
    duplex = 'half'
  })
  end
-- стуктура таблицы - id приводов BL - новер комнаты -номер привода = группа, номер
cmds = {
  'BL' = {
    ['27'] ={
      ['1'] = { 0x0C, 0x05 },
      ['2'] = { 0x0C, 0x06 },
      ['3'] = { 0x0C, 0x07 }
    },
    ['29'] ={
      ['1'] = { 0x0D, 0x08 },
      ['2'] = { 0x0E, 0x07 }
    }
  }
}
   
if not lb then
    require('user.motor')
  lb = require('localbus').new(0.5)
  function groupcallback(event)
    pref, cmd = unpack(grp.alias(event.dst):split('-'))
    val = event.getvalue()
    typ, room , num =unpack(pref:split('.'))
    if cmds[typ] then
      all_adr = cmds[typ][room][num]
      if cmd == 'short' then
        direction = 0x03
      elseif cmd == 'stop' then
        if val then
          direction =0x02
        else
          direction = 0x01
        end
      else
        log('некорректное имя группового адреса', grp.alias(event.dst))
      end
      port:write(motor_move(cur_group, cur_adr, direction))
   
    end
 
  --lb:sethandler('groupupdate', groupcallack)
  lb:sethandler('groupwrite', groupcallback)
  --lb:sethandler('groupresponse', groupcallback)
end
lb:step()
--log(lb)

GA names for  motors are next
BL.09.2-long
BL.09.2-stop