После включения карниза отправил команду 55 00 00 02 00 02 12 34 50 7F - установка адреса устройства в “12 34” (по умолчанию был FE FE, судя по спеке, но я не проверял).
Соответственно CRC16 нужно будет пересчитать (я пользовался https://crccalc.com/), если будете использовать адрес по умолчанию.
Далее настроил виртуальное устройство в wirenboard:
файл /etc/wb-rules/wb-rules
defineVirtualDevice("akko",{
title: "Шторы",
cells:{
position: {
type: "range",
value: 100,
min: 0,
max: 100,
},
}
});
defineRule("set_position", {
whenChanged: "akko/position",
then: function (newValue, devName, cellName){
runShellCommand("./etc/wb-rules/akko.perl "+newValue);
}
});
И perl скрипт, который устанавливает положение штор c шагом в 10%, например установить в 20 процентов:
./akko.perl 20
или считывает текущее положение штор - в ответе вернется число процентов:
./akko.perl
искать функции по расчету CRC16 для modbus мне было лень, поэтому команды все захардкодил.
файл /etc/wb-rules/akko.perl
#!/usr/bin/perl
use Device::SerialPort;
my $port = Device::SerialPort->new("/dev/ttyRS485-2");
$port->baudrate(9600);
$port->databits(8);
$port->parity("none");
$port->stopbits(1);
$output = "";
if ($ARGV[0]==100) # команда Установить положение эл.карниза в 100% (0x64)
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x64,0x49,0x06);
}
elsif ($ARGV[0]>=90) # .. в 90% (0x5A)
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x5A,0xC8,0xD6);
}
elsif ($ARGV[0]>=80) # .. в 80%
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x50,0x48,0xD1);
}
elsif ($ARGV[0]>=70) # .. в 70%
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x46,0xC9,0x1F);
}
elsif ($ARGV[0]>=60) # .. в 60%
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x3C,0x48,0xFC);
}
elsif ($ARGV[0]>=50)
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x32,0xC9,0x38);
}
elsif ($ARGV[0]>=40)
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x28,0x48,0xF3);
}
elsif ($ARGV[0]>=30)
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x1E,0xC8,0xE5);
}
elsif ($ARGV[0]>=20)
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x14,0x48,0xE2);
}
elsif ($ARGV[0]>=10) # .. в 10%
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x0A,0xC8,0xEA);
}
elsif (@ARGV) # .. в 0%
{
$output = pack("C*",0x55,0x12,0x34,0x03,0x04,0x00,0x48,0xed);
}
else # считать текущее положение эл.карниза
{
$output = pack("C*",0x55,0x12,0x34,0x01,0x02,0x01,0x2B,0x4D);
}
$port->write($output);
sleep(1);
$in = $port->read("100");
$per = substr($in,5,1);
printf ("%s\n",ord($per)); # вывести на экран ответ от эл.карниза
$port->close;