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
|