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

Постараюсь подробно изложить все, глядишь через полгода и не вспомню.
Итак требовалось управлять 6 электрокарнизами sunflower KT82TV (в реальности это теже dooya, akko и т.д.). Управление через iridium, где у пользователя есть три кнопки для каждого привода - влево, вправо, стоп.

  1. Выше есть инструкция на английском, она рабочая. Мне мой китаец выслал только на китайском, но внешне видно что команды и логика одинаковые.

  2. Проверяем вообще что привода отвечают на команды, для этого я пользовался преобразователем интерфейса USB - 485, которых на ali также полно. Установил ПО Tik modscan https://www.tik.perm.ru/produkciya/programmnoe_obespechenie/tik_modscan/ и послал приводу команды. Команды привод принял, отработал.

  3. Как формируются команды (для лентяев кто не читает мануал). Например 5500000301E93C, где “55” всегда стоит в начале, 00 00 - адрес в данном случае широковещательный, 03 команда, 01 отрыть, E93С - CRC. Как определить CRC? Заходим в https://crccalc.com/ и забиваем команду 5500000301 переводим в CRC-16 HEX. Обратите внимание что байты надо будет поменять местами. т.е. результат у вас будет 3СE9, но когда будете собирать команду и подавать в привод ЗС и E9 надо поменять местами.

  4. Проверили что все работает локально. Заготавливаем себе таблицу для всех приводов
    %D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B5

  5. Меняем адреса у приводов, для этого бежим по таблице и посылаем для каждого привода команду на изменение адреса: 55 00 00 02 00 02 01 01 9D 58 это команда для установки адреса 0101. Чтобы привод понял что вы хотите ему поменять адрес потребуется зажать кнопку на нем (4-5 сек), он моргнет 2 раза после чего посылаем команду указанную выше.

  6. В WB создаем виртуальное устройство и отправляем команду в perl скрипт

defineVirtualDevice("shades",{
    title: "shades",
    cells:{
        command: { //определили виртуальное устройство диапазон, у которого каждое значение является определенной командой в perl скрипте
            type: "range",
            value: 0,
            min: 0,
            max: 100,
        },      
    }
});

/*значение command
0 - открыть все шторы
1 - закрыть все шторы
2 - стоп все шторы
3 - открыть штора 1
4 - закрыть штора 1
5 - стоп штора 1
6 - открыть штора 2
7 - закрыть штора 2
8 - стоп штора 2
9 - открыть штора 3
10 - закрыть штора 3
11 - стоп штора 3
12 - открыть штора 4
13 - закрыть штора 4
14 - стоп штора 4
15 - открыть штора 5
16 - закрыть штора 5
17 - стоп штора 5
18 - открыть штора 6
19 - закрыть штора 6
20 - стоп штора 6
*/

defineRule("sunflower", { //название правила
  whenChanged: "shades/command",
  then: function (newValue, devName, cellName) { //выполняй следующие действия
     runShellCommand("/usr/bin/akko.perl "+ newValue); // вызываем perl скрипт и передаем код команды в атрибут
}
});
  1. Пишем 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] == 0) # команда открыть 5500000301E93C
    {
        $output = pack("C*",0x55,0x00,0x00,0x03,0x01,0xE9,0x3C);
    }
elsif ($ARGV[0] == 1) # команда закрыть 5500000302A93D
    {
        $output = pack("C*",0x55,0x00,0x00,0x03,0x02,0xA9,0x3D);
    }
# Адресные команды для привода с адресом 0101
elsif ($ARGV[0] == 3) # команда открыть 5501010301B900
    {
        $output = pack("C*",0x55,0x01,0x01,0x03,0x01,0xB9,0x00);
    }
elsif ($ARGV[0] == 4) # команда закрыть 5501010302F901
    {
        $output = pack("C*",0x55,0x01,0x01,0x03,0x02,0xF9,0x01);
    }
elsif ($ARGV[0] == 5) # команда стоп 550101030338C1
    {
        $output = pack("C*",0x55,0x01,0x01,0x03,0x03,0x38,0xC1);
    }
# Адресные команды для привода с адресом 0102
elsif ($ARGV[0] == 6) # команда открыть 55010203014900
    {
        $output = pack("C*",0x55,0x01,0x02,0x03,0x01,0x49,0x00);
    }
elsif ($ARGV[0] == 7) # команда закрыть 55010203020901
    {
        $output = pack("C*",0x55,0x01,0x02,0x03,0x02,0x09,0x01);
    }
elsif ($ARGV[0] == 8) # команда стоп 5501020303C8C1
    {
        $output = pack("C*",0x55,0x01,0x02,0x03,0x03,0xC8,0xC1);
    }
# Адресные команды для привода с адресом 0103
elsif ($ARGV[0] == 9) # команда открыть 550103030118C0
    {
        $output = pack("C*",0x55,0x01,0x03,0x03,0x01,0x18,0xC0);
    }
elsif ($ARGV[0] == 10) # команда закрыть 550103030258C1
    {
        $output = pack("C*",0x55,0x01,0x03,0x03,0x02,0x58,0xC1);
    }
elsif ($ARGV[0] == 11) # команда стоп 55010303039901
    {
        $output = pack("C*",0x55,0x01,0x03,0x03,0x03,0x99,0x01);
    }
# Адресные команды для привода с адресом 0104
elsif ($ARGV[0] == 12) # команда открыть 5501040301A901
    {
        $output = pack("C*",0x55,0x01,0x04,0x03,0x01,0xA9,0x01);
    }
elsif ($ARGV[0] == 13) # команда закрыть 5501040302E900
    {
        $output = pack("C*",0x55,0x01,0x04,0x03,0x02,0xE9,0x00);
    }
elsif ($ARGV[0] == 14) # команда стоп 550104030328C0
    {
        $output = pack("C*",0x55,0x01,0x04,0x03,0x03,0x28,0xC0);
    }
# Адресные команды для привода с адресом 0201
elsif ($ARGV[0] == 15) # команда открыть 5502010301B944
    {
        $output = pack("C*",0x55,0x02,0x01,0x03,0x01,0xB9,0x44);
    }
elsif ($ARGV[0] == 16) # команда закрыть 5502010302F945
    {
        $output = pack("C*",0x55,0x02,0x01,0x03,0x02,0xF9,0x45);
    }
elsif ($ARGV[0] == 17) # команда стоп 55020103033885
    {
        $output = pack("C*",0x55,0x02,0x01,0x03,0x03,0x38,0x85);
    }
# Адресные команды для привода с адресом 0202
elsif ($ARGV[0] == 18) # команда открыть 55020203014944
    {
        $output = pack("C*",0x55,0x02,0x02,0x03,0x01,0x49,0x44);
    }
elsif ($ARGV[0] == 19) # команда закрыть 55020203020945
    {
        $output = pack("C*",0x55,0x02,0x02,0x03,0x02,0x09,0x45);
    }
elsif ($ARGV[0] == 20) # команда стоп 5502020303C885
    {
        $output = pack("C*",0x55,0x02,0x02,0x03,0x03,0xC8,0x85);
    }
else # Широковещательныя команда стоп для всех приводов 550000030368FD
    {
        $output = pack("C*",0x55,0x00,0x00,0x03,0x03,0x68,0xFD);
	printf ("%s\n","stop");
    }	
$port->write($output);
sleep(1);
$in = $port->read("100");
$per = substr($in,5,1);
#printf ("%s\n",ord($per)); # вывести на экран ответ от привода

$port->close;
  1. Т.е. логика такова, что в иридиум когда пользователь нажимает определенную кнопку, я в shades/command получаю код команды, который далее передаю в perl. Это позволило уменьшить кол-во тегов (т.е. не создавать для каждой шторы свое устройство), кто работал с иридиум поймет.

  2. Скорей всего у вас ничего не заработает, т.к. WB коробочный и нужно с ним произвести определенный обряд.

  3. В консоли выполняем команду apt-get install build-essential

  4. В консоли выполняем команду perl -MCPAN -e 'install Device::SerialPort

  5. perl скрипт который я в своем случае разместил в /usr/bin/ надо дать права доступа, для этого выполняем команду chmod +x /usr/bin/akko.perl

  6. Если у вас на шине сидят только привода, то должно все заработать.

Что у меня не получилось решить: если в шине по мимо приводов находятся устройства WB, то при подаче команды на привод, привод у меня команду исполняет и перестает отвечать. Пока думаю докупить модуль расширения с еще одной шиной 485 и туда повесить китайские привода, если кто знает как это лечится или посоветует как провести диагностику буду благодарен.
Пост писал по памяти, возможно что-то упустил - пробуйте. Всем кто принимал участие огромное человеческое спасибо, без вас бы точно не смог!

Есть у кого-то мысли по шине, почему отваливается китаец если есть другие устройства 485?

5 лайков