Создание пользовательских прототипов классов

Здравствуйте! Хотя и стандарт ES5 не поддерживает ключевое слово class, тем не менее там есть возможность создавать классы с помощью прототипов.
Однако же при попытке сохранить правило с таким прототипом получаю такую ошибку:

 Script error: Error: Device with given ID already exists
/sbuild-nonexistent/go/pkg/mod/github.com/wirenboard/go-duktape@v0.0.0-20210723134114-881337fff8cb/api.go:124
anon native strict preventsyield
anon /etc/wb-rules/global-setting.js:147 preventsyield

фрагмент кода:

function Heater(set_temp, room_temp, rely_control, button_control, memory_cell, header_control) {
        this.set_temp = set_temp;
        this.room_temp = room_temp;
        this.rely_control = rely_control;
        this.button_control = button_control;
        this.memory_cell = memory_cell;
        this.header_control = header_control;
}

Heater.prototype.setMode = function(mode) {
    heaterState[this.memory_cell] = mode;
    getControl(this.control_header).setValue(heaterState[this.memory_cell]);
}

Heater.prototype.getMode = function() {
    return heaterState[this.memory_cell];
}

В чем может быть проблема?

Добрый день.

Приведенный кусок отлично сохраняется, а ошибка говорит, как правило о том что пытетесь создать устройство (виртуальное) когда оно уже есть. Для существующего устройства (любого) нужно добавлять контролы (прверив, что оно существует!), вот так: Как дабавить кнопку в панель устройств к действующему устройству? - #2 от пользователя BrainRoot

дело в том, что последняя строчка из сообщения об ошибке ссылается именно на строку с объявлением прототипа и я подумал что это как то связано. Спасибо, попробую разобраться

Ну и дайте скрипт, воспроизводящий ошибку целиком.

до этого было реализовано немного по другому, но часть с defineVirtualDevice я не менял.

var heaterState = new PersistentStorage("heater-states", {global: true});
var lightState = new PersistentStorage("light-states", {global: true});

heaterState["baniaMediumHeater"] = "auto";
heaterState["baniaTamburHeater"] = "auto";
heaterState["baniaMainHeater"] = "auto";
heaterState["baniaWaterPrepareHeater"] = "auto";

lightState["baniaOutdoorLight"] = "auto";

var mainHeaterOn = "wb-mr6c_214/K3";
var mediumHeaterOn = "wb-mr6c_214/K4";
var tamburHeaterOn = "wb-mr6c_214/K5";
var waterPrepareHeaterOn = "wb-mr6c_214/K6";

var restRoomTemp = "wb-msw-v3_49/Temperature";
var waterPrepareTemp = "wb-ms_187/Temperature";

var globalHeaterButton = "global-heater/GlobalHeaterButton";
var mainHeaterButton = "rest-room/MainHeaterButton";
var mediumHeaterButton = "rest-room/MediumHeaterButton";
var tamburHeaterButton = "rest-room/TamburHeaterButton";
var waterPrepareHeaterButton = "rest-room/WaterPrepareHeaterButton";

var restRoomTempSet = "rest-room/MainHeaterControl";
var waterPrepareTempSet = "rest-room/WaterPrepareHeaterControl";

defineVirtualDevice('rest-room', {
    title: 'RestRoom' ,
    readonly: false, 
    cells: {
        HeaderRestRoom: {
            title: "header",
            type: "text",
            value: "Комната отдыха"
        },
        TemperatureRestRoom: {
            title: "Temperature",
            type: "temperature",
            value: dev["wb-msw-v3_49/Temperature"]
	    },
        HumidityRestRoom: {
            title: "Humidity",
            type: "rel_humidity",
            value: dev["wb-msw-v3_49/Humidity"]
	    },
        MainHeaterControl: {
            type: "range",
            value: 22,
            min: 5,
            max: 30
        },
        MainHeaterButton: {
            type: "pushbutton",
            value: false
        },
        MediumHeaterButton: {
            type: "pushbutton",
            value: false
        }, 
        TamburHeaterButton: {
            type: "pushbutton",
            value: false
        },              
        OutdoorLightButton: {
            type: "pushbutton",
            value: false
        },
        OutdoorLightHeader: {
            title: "header",
            type: "text",
            value: lightState["baniaOutdoorLight"]
        },
        MainHeaterHeader: {
            title: "header",
            type: "text",
            value: heaterState["baniaMainHeater"]
        },
        MediumHeaterHeader: {
            title: "header",
            type: "text",
            value: heaterState["baniaMediumHeater"]
        },          
        TamburHeaterHeader: {
            title: "header",
            type: "text",
            value: heaterState["baniaTamburHeater"]
        },
        HeaderWaterPrepare: {
            title: "header",
            type: "text",
            value: "Комната водоподготовки"
        },    
        WaterPrepareHeaterControl: {
            type: "range",
            value: 22,
            min: 5,
            max: 30
        },        
        WaterPrepareHeaterButton: {
            type: "pushbutton",
            value: false
        },
        WaterPrepareHeaterHeader: {
            title: "header",
            type: "text",
            value: heaterState["baniaWaterPrepareHeater"]
        },
        TemperatureWaterPrepareRoom: {
            title: "Temperature",
            type: "temperature",
            value: dev["wb-ms_187/Temperature"]
	    },
        HumidityWaterPrepareRoom: {
            title: "Humidity",
            type: "rel_humidity",
            value: dev["wb-ms_187/Humidity"]
	    },
        TemperatureBarrel1: {
            title: "Temperature",
            type: "temperature",
            value: dev["wb-ms_187/External Sensor 1"]
	    },
        TemperatureBarrel2: {
            title: "Temperature",
            type: "temperature",
            value: dev["wb-ms_187/External Sensor 2"]
	    },              
        HeaderUnderfloor: {
            title: "header",
            type: "text",
            value: "Подвал"
        },       
        TemperatureUnderfloor: {
            title: "Temperature",
            type: "temperature",
            value: dev["wb-ms_239/Temperature"]
	    },
        HumidityUnderfloor: {
            title: "Humidity",
            type: "rel_humidity",
            value: dev["wb-ms_239/Humidity"]
	    }
    }
})

function Heater(set_temp, room_temp, rely_control, button_control, memory_cell, header_control) {
        this.set_temp = set_temp;
        this.room_temp = room_temp;
        this.rely_control = rely_control;
        this.button_control = button_control;
        this.memory_cell = memory_cell;
        this.header_control = header_control;
}

Heater.prototype.setMode = function(mode) {
    heaterState[this.memory_cell] = mode;
    getControl(this.control_header).setValue(heaterState[this.memory_cell]);
}

Heater.prototype.getMode = function() {
    return heaterState[this.memory_cell];
}

Heater.prototype.checkState = function() {
    switch(heaterState[this.memory_cell]) {
        case "auto":
            if((this.room_temp < (this.set_temp - 0.5)) && !this.heater_control) this.heater_control = true;
            if((this.room_temp < (this.set_temp + 0.5)) && this.heater_control) this.heater_control = false;
            else this.heater_control = false;
            break;
        case "On":
            this.heater_control = true;
            break;
        case "Off":
            this.heater_control = false;
            break;
    }
}


function buttonsLogic(heater) {
    defineRule({
        when: function() {
            return dev[heater.button_control];
        },
        then: function() {
            switch(heater.getMode()) {
                case "auto":
                    heater.setMode("On");
                    break;
                case "On":
                    heater.setMode("Off");
                    break;
                case "Off":
                    heater.setMode("Auto");
                    break;
            }    
        }
    });
}



var MainHeater = new Heater(restRoomTempSet, restRoomTemp, mainHeaterOn, mainHeaterButton, "baniaMainHeater", "rest-room/MainHeaterHeader");
var MediumHeater = new Heater(restRoomTempSet, restRoomTemp, mediumHeaterOn, mediumHeaterButton, "baniaMeduimHeater", "rest-room/MediumHeaterHeader");
var TamburHeater = new Heater(restRoomTempSet, restRoomTemp, tamburHeaterOn, tamburHeaterButton, "baniaTamburHeater", "rest-room/TamburHeaterHeader");
var WaterPrepareHeater = new Heater(waterPrepareTempSet, waterPrepareTemp, waterPrepareHeaterOn, waterPrepareHeaterButton, "baniaWaterPrepareHeater", "rest-room/WaterPrepareHeaterHeader");

buttonsLogic(MainHeater);
buttonsLogic(MediumHeater);
buttonsLogic(TamburHeater);
buttonsLogic(WaterPrepareHeater);

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

Да всегда пожалуйста! Просто ошибка достаточно типовая, но редкая, а тут как раз опыт решает.
Ну и как писал - надо (ну, желательно) перед созданием устройства проверять, нет ли его уже.

Как приятно пообщаться с умным человеком. Так что вам спасибо. И, кстати, в планах переделать движок, так что будут и классы и функции работы с сетью нативные и прочее.

будут и классы и функции работы с сетью нативные и прочее

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

Планов много, но времени как обычно не хватает. Сейчас актуален переезд на bullseye, потом расширения корня. А правила ждут своей очереи.

Лора сейчас используется просто как транспорт для Modbus, ну и модуль в контроллере работает просто шлюзом. То есть ничего кроме WB-MSW соответствущей комплектации к нему не подключить. Если для поиграться - можно Z-wave, у него интеграция полноценнаяя.

Благодарю! Крайне приятно.

Эта тема была автоматически закрыта через 7 дней после последнего ответа. В ней больше нельзя отвечать.