Вот о чем я говорил . после создания устройства обновите страницу, а то иногда теряется переключатель доступа к редактированию . Для того что бы увидеть результат округления и ограничения по лимиту нужно уйти из поля или закрыть доступ к редактированию т.е. чтобы значение опубликовалось в MQTT и сработало правило подписки
// Объект для хранения созданных виртуальных устройства "Test"
var oTest = {
Test_1: null, // Экземпляр виртуального устройства "Test_1"
Test_2: null, // Экземпляр виртуального устройства "Test_2"
};
// Объект с переменными необходимыми при создании экземпляра виртуального устройства "Мой тест 1"
var TestDevice_1 = {
NameVD: "MuTest_1",
NameEN: "MuTest",
NameRU: "Мой тест",
nTopic: "/Mu_Test",
nSwitch: "/swAccessEdit",
Precision: 2,
LimitMax: 1000,
LimitMin: 10,
};
// Объект с переменными необходимыми при создании экземпляра виртуального устройства "Мой тест 2"
var TestDevice_2 = {
NameVD: "MuTest_2",
NameEN: "MuTest 2",
NameRU: "Мой тест 2",
nTopic: "/Mu_Test",
nSwitch: "/swAccessEdit",
Precision: 3,
LimitMax: 100,
LimitMin: 10,
};
//-------------------------------------СОЗДАНИЕ ВИРТУАЛЬНОГО УСТРОЙСТВА-----------------------------------------------------------//
// Функция создание виртуального устройства "Мой тест"
function vdMuTest(DeviceParam) {
try {
this.NameVD = DeviceParam.NameVD; // Имя виртуального устройства (Мой тест)
this.NameEN = DeviceParam.NameEN; // Имя выводимое в Web UI при анг.языке интерфейса
this.NameRU = DeviceParam.NameRU; // Имя выводимое в Web UI при рус.языке интерфейса
this.Precision = Math.pow(10, DeviceParam.Precision); // Требуемая точность отображения (знак после запятой) в виджете WEB UI
this.LimitMax = DeviceParam.LimitMax; // Верхний предел вводимого значения
this.LimitMin = DeviceParam.LimitMin; // Нижний предел вводимого значения
this.Topic = DeviceParam.nTopic; // Отслеживаемый топик ввода значения
this.Switch = DeviceParam.nSwitch; // Переключатель для включения доступа к переменным
this.vDeviceTest = null; // Свойство для хранения экземпляра виртуального устройства
this.RuleChangeValue = null; // Свойство для хранения экземпляра правила подписки на изменение значения в WEB UI
this.RuleChangeEdit = null; // Свойство для хранения экземпляра правила подписки на открытие доступа к редактированию
} catch (error) {
log.error("GT try vdMuTes {}, ERR = {}", DeviceParam.NameVD, error);
}
}
//-------------------------------------СОЗДАНИЕ ВИРТУАЛЬНОГО УСТРОЙСТВА В MQTT и WEB UI-------------------------------------------//
// Функция создания экземпляра виртуального устройства (мой тест) в MQTT и WEB UI
vdMuTest.prototype.CreateVirtualDevice = function () {
try {
var self = this; // Сохраняем ссылку на контекст
return defineVirtualDevice(this.NameVD, {
// имя виджета в GUI
title: {
en: "Device " + this.NameEN,
ru: "Устройство " + this.NameRU,
},
cells: {
//Разделитель для WEB_GUI
Separator: {
title: { en: "", ru: "" },
type: "text",
value: "--------------------------- ТЕСТ 1 Wirenboard -----------------------",
forceDefault: true,
readonly: true,
order: 1,
},
// Пробуем ограничить встроенными средствами
WB_Test: {
title: {
en: "WB test limit and round",
ru: "WB тест ограничения и округления",
},
type: "value",
value: 150,
min: 0,
max: 65534,
precision: 0.1,
forceDefault: true,
readonly: true,
order: 2,
},
//Разделитель для WEB_GUI
Separator2: {
title: { en: "", ru: "" },
type: "text",
value: "-----------ТЕСТ 2 реализация через правило------------",
forceDefault: true,
readonly: true,
order: 3,
},
// Тест 2 ограничиваем через правило
Mu_Test: {
title: {
en: "test limit and round ",
ru: "Тест ограничения и округления 10 <x> 1000",
},
type: "value",
value: 0,
readonly: true,
order: 4,
},
// Переключатель для доступа к редактированию калибровочной таблицы из WEB UI
swAccessEdit: {
title: { en: "Access EDIT", ru: "Доступ к редактированию" },
type: "switch",
value: "false",
forceDefault: true,
order: 5,
},
},
});
} catch (error) {
log.error(
"GT try CreateVirtualDevice: = {}, error = {}",
self.NameVD,
error
);
}
};
//--------------------------СОЗДАНИЕ ЭКЗЕМПЛЯРОВ ПРАВИЛ ПОДПИСОК НА ИЗМЕНЕНИЕ ЗНАЧЕНИЙ--------------------------------------------//
//Функция подписки на изменения значения в топике и не дает ввести неправильное значение в WEB UI, а также округляет его но требуемой величины
vdMuTest.prototype.GetValue = function (RuleName) {
try {
var self = this; // Сохраняем ссылку на текущий контекст
// Единичное копирование и расчет переменных при создании устройства
//..................
return defineRule(RuleName + "_" + this.NameVD, {
// Функция подписки на изменение значения топика "/Mu_Test", физическое значение уставки ... в WEB UI
whenChanged: self.NameVD + self.Topic, // "/Mu_Test"
then: function (newValue, devName, cellName) {
log("newValue = " + newValue);
newValue =
Math.round(newValue * self.Precision) / self.Precision; // Быстрое преобразование в число c округлением до заданной точности
log("Round newValue = " + newValue);
// Проверка введенного кода и его ограничение до расчета (иначе незатухающие изменения - "качели")
if (newValue > self.LimitMax) {
// Проверяем выход за пределы и если больше то ограничиваем ввод
newValue = self.LimitMax;
//dev[devName + "/" + cellName] = newValue; // Верхним значением лимита
} else if (newValue < self.LimitMin) {
// Если значение меньше 0 то ограничиваем
newValue = self.LimitMin;
//dev[devName + "/" + cellName] = newValue; // Нижним значением лимита или 0
}
dev[devName + "/" + cellName] = newValue;
},
});
} catch (error) {
log.error("GT try GetValue: Device = {}, ERR = {}", self.NameVD, error);
}
};
// Функция подписки на изменения переключателя в WEB UI и включения доступа к редактированию значений
vdMuTest.prototype.EnableSettingsEdit = function (RuleName) {
try {
var self = this; // Сохраняем ссылку на текущий контекст
return defineRule(RuleName + "_" + this.NameVD, {
whenChanged: self.NameVD + self.Switch, // топик, при изменении которого сработает правило
then: function (newValue, devName, cellName) {
var isEdit = +!newValue; // Быстрая конвертация в число
// Открываем доступ к полям ввода в WEB UI
dev[devName + "/WB_Test#readonly"] = isEdit;
dev[devName + "/Mu_Test#readonly"] = isEdit;
// при закрытии доступа ...... Что то делаем
if (!newValue) {
//...... Что то делаем
}
},
});
} catch (error) {
log.error(
"GT try EnableSettingsEdit: Device = {}, ERR = {}",
self.NameVD,
error
);
}
};
//---------------------СОЗДАНИЕ ЭКЗЕМПЛЯРОВ ВИРТУАЛЬНЫХ УСТРОЙСТВ-------------------------------------------------//
// Функция создает экземпляр виртуального устройства с необходимыми для его работы подписками на топики MQTT
function CreateDevice_Test(PropertyNameTest, CreateDataTest) {
try {
// Создание экземпляра виртуального устройства Тест
if (PropertyNameTest === null) {
PropertyNameTest = new vdMuTest(CreateDataTest);
}
// Создание виртуального устройства "ТЕСТ" в MQTT и WEB UI
if (PropertyNameTest.vDeviceTest === null) {
PropertyNameTest.vDeviceTest =
PropertyNameTest.CreateVirtualDevice();
}
// Создание подписки на изменение значения поля в WEB UI ссылку на объект записываем в поле экземпляра
if (PropertyNameTest.RuleChangeValue === null) {
PropertyNameTest.RuleChangeValue =
PropertyNameTest.GetValue("RuleGetValue");
}
// Создание подписки на изменение переключателя для доступа к редактированию ссылку на объект записываем в поле экземпляра
if (PropertyNameTest.RuleChangeEdit === null) {
PropertyNameTest.RuleChangeEdit =
PropertyNameTest.EnableSettingsEdit("RuleChangedEnSetEdit");
}
} catch (error) {
log.error(
"GT try CreateDevice_Test: Device = {}, error = {}",
CreateDataTest.NameVD,
error
);
}
}
CreateDevice_Test(oTest.Test_1, TestDevice_1); // Вызов функции создания виртуального устройства "Тест_1"
//CreateDevice_Test (oTest.Test_2, TestDevice_2); // Вызов функции создания виртуального устройства "Тест_2"
LimitAndPrcisionTest.zip (2,9 КБ)