четверг, 6 марта 2025 г.

Управление умной лампой с помощью виджетов Android

Я как-то писал статью статью о том, как сделал приложение для управления умной лампой через яндекс алису https://boolkin.blogspot.com/2023/09/Yandex-station-android-apk.html

Проблема этого способа в том, что коды пропысываются жестко и если что-то поменяется (срок действия уодов которые генерировал яндекс для меня составлял один год) то придется заново пересобирать приложение и мало того для того чтобы включить или выключить лампу надо сначала запустить свое приложение и уже потом нажимать нужную кнопку. Именно поэтому пришла идея отказаться от своего приложения и воспользоваться сторонними разработками - виджеты с http запросами. Конкретно речь идет о приложении в моем случае Ярлыки HTTP запросовЯрлыки HTTP запросов 

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




Пишу со смарта, поэтому оформление немного храмает, но я думаю примерно понятно. Добавляется ярлык, добавляется http post запрос на адрес api.iot, в заголовок добавляется авторизация, а сам запрос делается как json:

{
  "devices": [
    {
      "id": "",
      "actions": [
        {
          "type": "devices.capabilities.on_off",
          "state": {
            "instance": "on",
            "value": true
          }
        }
      ]
    }
  ]
}
Естественно id должно быть айди вашей лампы, а авторизация та что даст яндекс.

Если включить то value true, а если лампу выключить то value false

воскресенье, 19 января 2025 г.

Статистика википедии

Наверняка про википедию слышали все, а вот про то что в русском сегменте вики хозяйничают украинцы по полной программе, про это думаю слышали не так много людей, а еще меньше людей  заморачиваются по этому поводу. Возможно, некоторые более-менее продвинутые пользователи интернета и вики видели такую картину, показывающие эту статистику правок рувики по странам, где четко видно как выделяется Украина на фоне других стран, а Россия тем временем вообще подсвечена серым цветом:

Статистика находится по этому адресу Можно прокрутить статистику по месяцам начиная с 2018 года, и посмотреть как менялась активность украинцев в российской википедии, для чего был написан простейший скрипт. Фишка в том что эти данные по редакторам можно смотреть и в табличном виде, для чего нужно нажать на кнопку "глобуса" над картой справа. После формирования таблицы все числа с редакторами будут отсортированы по правой стороне и это поможет выделить нужные цифры. Сам скрипт такой:

tds = document.getElementsByTagName("td");
total = 0;
numb = 0;

for (let i=0;i<tds.length;i++) {
    if (tds[i].className =="right aligned") {
    total = total +parseInt(tds[i].innerHTML);
    numb++;
    }
}
x = parseInt(tds[0].innerHTML);
proc = x *100 / total;
console.log(total +" из " + numb + " стран; УКР=" + Math.round(proc) + "%");

И вот результат сравнений по годам для правок от 100 штук:

янв 2018: 380 из 29 стран; УКР=18% 

дек 2018: 350 из 27 стран; УКР=20%

дек 2019: 360 из 29 стран; УКР=17% 

дек 2020: 340 из 25 стран; УКР=21%

дек 2021: 370 из 30 стран; УКР=19% 

дек 2022: 320 из 27 стран; УКР=16%

дек 2023: 390 из 31 стран; УКР=13%

дек 2024: 400 из 34 стран; УКР=10%

Вот по годам для правок до 99 штук:

янв 2018: 1760 из 60 стран; УКР=36%

дек 2018: 1640 из 60 стран; УКР=34%

дек 2019: 1510 из 54 стран; УКР=36%

дек 2020: 1730 из 60 стран; УКР=35%

дек 2021: 1570 из 53 стран; УКР=36%

дек 2022: 1650 из 57 стран; УКР=24%

дек 2023: 1510 из 60 стран; УКР=24%

дек 2024: 1510 из 56 стран; УКР=24% 

Как видно активность снижается, что не может не радовать)

понедельник, 7 октября 2024 г.

Продолжение по Owen и Codesys

В прошлый раз писал о том как запустить опрос нескольких устройств по протоколу modbus чтобы опрос велся в пакетном режиме - тогда советовали использовать символы, и приходилось делать еще множество преобразований, а еще чтобы сделать опрос сразу 30 устройств пришлось даже расширять память. Оказалось что Овен выпустили давным давно библиотеку, которая так же в пакетном режиме опрашивает модбас устройства и преобразований становится меньше.

Удобно то что добавлять и убирать опрашиваемые устройства можно в коде и гораздо проще чем через конфиг контроллера, хотя и сделал я это немного странновато, но работает. Удобно что в Кодесис есть экспорт программы, который экспортируется целиком в текстовом формате - можно экспортировать кусок программы, лишь один блок FB, что я и сделал и скопировал его в гитхаб гист. Этот блок вызывается из главной программы, и в него передается количество оправшиваемых модбас устройств, адреса которых записаны в отдельном массиве. Вообще там есть еще и множество глобальных переменных, но пока решил не добавлять 

(* @NESTEDCOMMENTS := 'Yes' *)
(* @PATH := '\/Program' *)
(* @OBJECTFLAGS := '0, 8' *)
(* @SYMFILEFLAGS := '2048' *)
FUNCTION_BLOCK ModbusRead
VAR_INPUT
devnumb:BYTE;
END_VAR
VAR_OUTPUT
END_VAR
VAR
mbadr:BYTE;
mbdep:BYTE;
get_modbus: MB_RD_INP_REGS; (*функция 04 - чтение трех параметров типа INT*)
Buffer: ARRAY[0..255] OF BYTE; (* байтовый буфер данных*)
cmpl: BOOL;
TimeOut: TIME:=T#10ms;(*таймаут*)
Exception: BYTE;
DataSize: WORD;
master1: BYTE:= 0;
i:BYTE:=1;
END_VAR
(* @END_DECLARATION := '0' *)
IF enabl = FALSE THEN
enabl := TRUE;
END_IF
(*Устанавливаем настройки COM-порта*)
IF port_opened=0 THEN
Settings.Port:=com_num; (*номер COM-порта 0 – RS-485, 1 – RS-232*)
Settings.dwBaudRate:=115200; (*скорость*)
Settings.byParity:=0;
Settings.dwTimeout:=0;
Settings.byStopBits:=1;
Settings.dwBufferSize:=0;
Settings.dwScan:=0;
END_IF
(*Открываем COM-порт*)
COM_SERVICE1(Enable:=(port_opened=0), Settings:=Settings , Task:=OPEN_TSK );
(*Если COM-порт открыт, то переходим к приему и передачи данных *)
IF COM_SERVICE1.ready THEN
port_opened:=2;
END_IF
IF port_opened=2 THEN (*Удачно проинициализировали*)
CASE master1 OF
0:
get_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adrDep[i] , (*адрес*)
FirstAddr:=32000 , (*номер регистра*)
Quantity:=16, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа FLOAT*)
DEP[arrDep[i]].Ua:=GET_R(buffer[0],buffer[1],buffer[2],buffer[3]);
DEP[arrDep[i]].Ub:=GET_R(buffer[4],buffer[5],buffer[6],buffer[7]);
DEP[arrDep[i]].Uc:=GET_R(buffer[8],buffer[9],buffer[10],buffer[11]);
DEP[arrDep[i]].Ia:=GET_R(buffer[12],buffer[13],buffer[14],buffer[15]);
DEP[arrDep[i]].Ib:=GET_R(buffer[16],buffer[17],buffer[18],buffer[19]);
DEP[arrDep[i]].Ic:=GET_R(buffer[20],buffer[21],buffer[22],buffer[23]);
DEP[arrDep[i]].Freq:=GET_R(buffer[24],buffer[25],buffer[26],buffer[27]);
DEP[arrDep[i]].Ratio:=GET_R(buffer[28],buffer[29],buffer[30],buffer[31]);
comm_ok[arrDep[i]]:=1;
ELSE
comm_ok[arrDep[i]]:=0;
END_IF
master1:=1; (*переходим к выполнению следующего ФБ*)
END_IF
1:
get_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adrDep[i], (*адрес*)
FirstAddr:=31000 , (*номер регистра*)
Quantity:=19, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения
операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа BOOL*)
DEP[arrDep[i]].IN1:=buffer[1].0;
DEP[arrDep[i]].IN2:=buffer[3].0;
DEP[arrDep[i]].IN3:=buffer[5].0;
DEP[arrDep[i]].IN4:=buffer[7].0;
DEP[arrDep[i]].IN5:=buffer[9].0;
DEP[arrDep[i]].IN6:=buffer[11].0;
DEP[arrDep[i]].IN7:=buffer[13].0;
DEP[arrDep[i]].Enable:=buffer[15].0;
DEP[arrDep[i]].Ua_ON:=buffer[17].0;
DEP[arrDep[i]].Ub_ON:=buffer[19].0;
DEP[arrDep[i]].Uc_ON:=buffer[21].0;
DEP[arrDep[i]].phaseCross:=buffer[23].0;
DEP[arrDep[i]].MT3_phA:=buffer[25].0;
DEP[arrDep[i]].MT3_phB:=buffer[27].0;
DEP[arrDep[i]].MT3_phC:=buffer[29].0;
DEP[arrDep[i]].Cntr_CH_STAT:=buffer[31].0;
DEP[arrDep[i]].Cntr_CH_RSLT:=buffer[33].0;
DEP[arrDep[i]].power1:=buffer[35].0;
DEP[arrDep[i]].power2:=buffer[37].0;
comm_ok[arrDep[i]]:=1;
ELSE
comm_ok[arrDep[i]]:=0;
END_IF
master1:=2; (*переходим к выполнению следующего ФБ*)
END_IF
2:
get_modbus(
Enable:=enabl , (* разрешение работы блока *)
Mode:=MB_RTU , (*режим передачи*)
DevAddr:=adrDep[i] , (*адрес*)
FirstAddr:=33000 , (*номер регистра*)
Quantity:=14, (*количество регистров*)
ComHandle:=Settings.Port ,(*номер COM-порта*)
TimeOut:=TimeOut , (*Таймаут T#50ms*)
Buffer:=Buffer , (* буфер данных *)
Complete=>cmpl , (* скопировать признак завершения
операции *)
Exception=>err , (* скопировать регистр ошибок *)
ByteCnt=>DataSize ); (*кол-во считанных байтов *)
(*если установлен признак завершения операции, то *)
IF cmpl THEN
IF err=0 THEN (*Если нет ошибок, то получаем данные из буфера типа DWORD*)
DEP[arrDep[i]].c1:=GET_D(buffer[0],buffer[1],buffer[2],buffer[3]);
DEP[arrDep[i]].c2:=GET_D(buffer[4],buffer[5],buffer[6],buffer[7]);
DEP[arrDep[i]].c3:=GET_D(buffer[8],buffer[9],buffer[10],buffer[11]);
DEP[arrDep[i]].c4:=GET_D(buffer[12],buffer[13],buffer[14],buffer[15]);
DEP[arrDep[i]].c5:=GET_D(buffer[16],buffer[17],buffer[18],buffer[19]);
DEP[arrDep[i]].c6:=GET_D(buffer[20],buffer[21],buffer[22],buffer[23]);
DEP[arrDep[i]].c7:=GET_D(buffer[24],buffer[25],buffer[26],buffer[27]);
comm_ok[arrDep[i]]:=1;
ELSE
comm_ok[arrDep[i]]:=0;
END_IF
master1:=0;
i:=i+1;
IF i>devnumb THEN
i:=1;
END_IF
END_IF
END_CASE
IF err <> 0 THEN
enabl := FALSE;
END_IF
END_IF
END_FUNCTION_BLOCK

Еще хотел бы написать еще об одной интересной штучке, подсмотрел на форуме, но хочу сохранить еще раз - логика для отображения времени скана программы:


Простейший принцип - фиксируется время каждого цикла и отнимается от времени предыдущего цикла - сработает на любом другом ПЛК, интересно даже проверить это потом как-нибудь.

Еще одна интересная фишка - есть и в документации и снова как всегда пишу тут чтобы не искать в документации:

Как видно на картинке можно задать разные цвета заливки для блока с восклицательным знаком - при разных условиях цвет будет разный. При этом удобно использовать массив цветов (в данном случае cell_err, причем обратить внимание на тип DINT - цвет требует больше памяти чем просто INT) и цикл для задания цветов для нескольких устройств. Конечно же даже если условий сработает несколько, то цвет останется в итоге по последнему условию, но в данном случае такое поведение не принципиально, потому что при любом раскладе требуется обратить внимание на состоянии ячейки. Чтобы при нормальной работе не отображать восклицательный знак - его показ можно скрыть по условию если цвет будет равен нулю, но в конструкции добавляется NOT - потому что свойство невидимости (или тогда <>0 без NOT)
.cell_err[1]=0
И еще кое-что. Для того чтобы реализовать мигающий красный восклицательный знак, пришлось добавить мигающий бит в программу. Сначала сделал на таймерах ,а потом увидел что есть готовый блок в библиотеке Utils:


пятница, 23 августа 2024 г.

Передача сигнала с IBA PDA в PLC

IBA PDA может собирать кучу сигналов через множество протоколов с разных ПЛК: TCP, UDP, S7, Modbus TCP (но иба не мастер а слейв), Modbus RTU (как мастер та ки слейв через COM порт), OPC DA и другие. Фишка в том что оказывается через OPC можно и отправлять данные в ПЛК, и об этом хоел написать небольшую заметку, чтобы как обычно в случе если снова понадобится, можно было это сделать еще раз. (сейчас смотрю и как будто слишком сложно все, но та кработает. не знаю можно ли упростить, но оставлю именно так как делал сам)

Для настройки передачи используется функция ИБЫ Alarms (OPC output module), где в качестве выходного сигнала выбирается тот который поддерживает записть. На скрине ниже видно как в ИБА Qpanel ввели в специальное поле значение 20, и это значение изменилось (4 график):


 Видно так же то что этот сигнал пишется еще и в виртуальный модуль (7:0)

А кнопка на Qpanel привязывается к этому сигналу (на скрине кстати видно как можно скрыть кнопку Apply, или можно ее текст изменить):

Все. Теперь если с ибы ввести новое значение, то оно передается в ПЛК посредством OPC. 

B еще немного про интересную функцию ИБЫ - technostring, вот так она примерно работает:

То есть можно передавать ASCII символы, которые будут отображаться в анализе в момент передачи. Туда можно передавать например номера рулонов. Как видно на скрине выше передавать на ибу можно строку по TCP протоколу и выделять в строке нужную часть, которая будет отображаться на графике. Заканчиваться строка должна переводом каретки (0x0D). Также можно передать строку в файле - во время сохранения файла показывается та часть первой строки (оканчивающаяся так же переводом каретки) которая настраивается аналогичным образом как и с TCP. В общем все это очень интересно, но для применения в реальности чаще всего врядли понадобится: если не знать что так можно делать, то значит так можно не делать)

воскресенье, 11 августа 2024 г.

Codesys 2.3 немного о визуализации

Мне лень читать документацию, а иногда требуется сделать что-то не совсем очевидное, поэтому решил написать небольшую заметку, чтобы вернуться к ней если понадобится когда-нибудь еще. Была задача добавить визуализацию нескольких однотипных модулей. Рисовать 10, 20 картинок конечно же было бы тупо, а вот нарисовать одну, и привязать к ней промежуточный тег - это правильно. Обычно это называется фейсплейт или faceplate, или шаблон. То есть был сделан шаблон визуализации в Codesys 2.3. 

Чтобы выйти из ситуации, придумал такой план: создал массив с 20 элементами (по числу модулей) со структурой визуализации, в которой записываются интересующие параметры - собирается больше 20 сигналов с каждого модуля. Как это выглядит (создана структура depStruct и создан массив DEP):

вторник, 6 августа 2024 г.

Добавление устройств с протоколом ModBus TCP в ПЛК AllenBradley

Modbus — открытый коммуникационный протокол, основанный на архитектуре ведущий — ведомый (англ. master-slave; в стандарте Modbus используются термины client-server). Широко применяется в промышленности для организации связи между электронными устройствами. Может использоваться для передачи данных через последовательные линии связи RS-485, RS-422, RS-232 и сети TCP/IP (Modbus TCP).
Для того чтобы организовать обмен с ведомым устройством, посредством протокола Modbus, в ПЛК Allenbradley предусмотрена стандартная функция, которую можно добавить, скачав с официального сайта. В скаченном архиве есть английская инструкция по работе с функцией, и файл с расширением L5X, через который импортируется логика функции. Архив с сайта добавил себе в облако.
Последовательность шагов для импорта функции Modbus TCP (все шаги делаются в онлайн режиме):

среда, 31 июля 2024 г.

Открыть чат WhatApp

 Открыть чат WhatsApp для номеров телефонов не в телефонной книге - например если нужно отправить сообщение тому кого нет в вашей телефонной книге