Электрокарнизу Akko ac-72e по rs485

После включения карниза отправил команду 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;