Внутри контроллера команды и значения между каналами передаются в унифицированном виде (см itemCmd) Но для управления реальными устройствами, данные необходимо конвертировать из унифицированного вида в формат, который понимает устройство и наоборот
Для этого существует механизм преобразований, который может производить как конвертацию значений так и переобразования между командами и значениями
Первое место, где используются преобразования - это интеграция Modbus v2. см настройка_modbus это обьясняется тем, что в Modbus все взаимодействие с устройством происходит через регистры, в которые пишутся, либо, из которых считываются числовые значения.
Предусмотрено два типа преобразований - преобразования команды и преобразование значения
Также, существуют два направления преобразования - прямое (когда из унифицированного вида создается значение для записи в устройство) и обратное - когда считанное из устройства значение преобразуется в унифицированный вид
Преобразование определяется при помощи JSON обьекта «map» который добавляется в описание регистра устройства в разделе конфигурирования modbus. Разберем на примерах:
"fanspeed" :{"reg":40000,"map":{"val":[1,255,1,5],"cmd":[["OFF",0]]},"id":7},
прямое преобразование:
При управлении fanspeed (напрямую, в нотации <item>/fanspeed/set или через суффикс №7 (fan) в нотации <item>/fan), сперва произойдет попытка преобразования команды
В случае, если передана команда OFF, в регистр 40000 будет записано значение 0 В противном случае, осуществляется попытка преобразовать переданное значение, конвертировав его из шкалы 1-255 в шкалу 1-5 если в результате преобразований будет получено число - произойдет запись в указанный регистр модбас.
при считывании значения из регистра, будет происходить обратное преобразование
При этом, те же правила применяются в обратном направлении. Сначала производится попытка преобразовать полученное из регистра значение в команду. В случае неуспеха - в число.
В примере выше - если считано значение 0 - оно будет преобразовано в команду OFF в случае не успешного преобразования в команду будет осуществлено обратное преобразование значения из шкалы 1-5 в шкалу 1-255
Следует отметить, что если преобразование типа «val» не указано, то число, прочитанное из регистра, будет передано на выход без преобразования - именно в том виде, как оно было прочитано из регистра. При этом, преобразование считается выполненным успешно и «сценарий по умолчанию» (def) выполнен не будет.
Данное поведение можно отменить, задав null для преобразования значения, как указано в примере ниже. Это приведет к тому, что при невозможности преобразовать полученное значение в команду, преобразование в число производиться не будет и отработает «сценарий по умолчанию» (def)
"acon":{"reg":40003,"map":{"cmd":[1,["OFF",0]],"val":null,"def":40001},"id":8},
Для этого примера преобразования будут действовать следующим образом:
Прямое:
Команда OFF приведет к записи 0 в регистр 40003 Любая другая команда или значение будут проигнорированы
Обратное:
Если из регистра 40003 считан ноль, он будет преобразован в команду OFF.
любые другие значения будут проигнорированы. Преобразование при этом будет считаться не успешным. и будет выполнен «сценарий по умолчанию», заданный в параметре «def» обьекта «map».
Этот параметр (используется только для обратных преобразований modbus) применяется в том случае, если для считанного из регистра значения не удалось применить преобразование. В этом случае, можно использовать значение, считанное из иного регистра.
Параметр def может иметь либо цифровое либо строковое значение. В случае цифрового значения - задается номер регистра. в случае строкового значения - задается имя параметра. Логика работы сценария по умолчанию немного разная для данных двух случаев.
цифровое значение:
Контроллер пытается найти считанное из modbus значение в текущем буфере (на тот случай, если данное значение было считано в одном цикле опроса командой чтения нескольких последовательных регистров)
Если значение не было считано, регистр считывается отдельно. Для примера выше, требуется, чтобы номер регистра (40001), также, был определен. Например, таким образом:
"acmode" :{"reg":40001,"map":{"cmd":[["FAN_ONLY",1],["HEAT",4],["COOL",2],["AUTO",8]]},"id":8},
Соответственно, в случае если значение регистра 40003 не нулевое (сработал «сценарий по умолчанию») - будет прочитан регистр 40001, полученное из него значение будет преобразовано к соответствующей команде, результат данного преобразования будет возвращен как результат преобразования первого параметра (acon)
Данное поведение, тем не менее, не отменяет стандартной логики того, что когда произойдет опрос регистра 40001 (если его опрос задан в параметре poll устройства) - будут произведены все преобразования из параметра acmode, которые будут переданы на обработку, если acmode описан в разделе items файла конфигурации.
строковое значение:
В этом случае, используется последнее, ранее считанное, значение, сохраненное в параметре, имя которого указано в параметре def. Для данного значения, производятся преобразования, определенные для данного параметра и их результат возвращается как результат преобразования первого параметра.
В примере ниже, если значение coil 0 равно нулю - обратное преобразование сразу вернет команду OFF
Иначе, так как преобразование в число отменено (val=null), преобразование для параметра pwr будет считаться не успешным и контроллер посмотрит ранее считанное значение регистра 1, из параметра описанного в acmode, применит все указанные для регистра acmode преобразования и их результат вернет для параметра pwr
важно: параметр acmode должен быть описан в разделе items, даже если сам по себе он ни для каких действий более не используется. достаточно в данном описании поставить пустой JSON обьект - именно в нем контроллер сохраняет ранее считанные значения)
"pwr":{"coil":0,"map":{"cmd":[1,["OFF",0]],"val":null, "def":"acmode"},"id":1}, "acmode":{"reg":1,"map":{"cmd":[["FAN_ONLY",4],["HEAT",2],["COOL",1],["DRY",3],["AUTO",5]],"val":null},"id":1},
В простейшем случае, в параметре val задается массив, содержащий 4 значения
"val":[вход_мин, вход_макс, выход_мин, выход_макс]
например
"val":[1, 5, 1, 255]
В случае прямого преобразования, числа 1,2,3,4,5 будут преобразованы к 1, 64, 128, 195, 255 В случае обратного - числа из интервала 1-64 к 1, 65-128 к 2, 129-195 к 3, 196-254 к 4 и 255 к 5
NEW если входное значение не укладывается в указанные границы - преобразование считается не успешным. То есть в примере выше, если на вход преобразования придет число 0 или 6 то оно не сработает.
можно определить значения, которые будут являться результатом преобразования если. входное значение меньше минимума или больше максимума диапазона преобразования
"val":[вход_мин, вход_макс, выход_мин, выход_макс, вход<мин_прямое, вых<мин_обратное, вход>макс_прямое, вых>макс_обратное]
соответственно, используя данный синтаксис, можно доработать пример выше таким образом, что значение 0 будет транслироваться в 0 как в прямом так и в обратном направлении
"val":[1, 5, 1, 255, 0, 0]
Параметры подставляемые при срабатывании ограничений не обязательны. Если какие-то требуется пропустить - можно указать null
данный шаблон в случае прямого преобразования позволяет провести трансляцию стандартных команд OFF, LOW, MEDIUM, HIGH в значения 0, 20, 128, 255 соответственно
Для обратного преобразования: Значения 0, 1-127, 128-254, 255 преобразуются в OFF, LOW, MEDIUM, HIGH
"fanspeed":{"reg":42,"type":"u8l","id":7,"map":{"cmd":"fan"}},