본문 바로가기

3D Printer/OctoPrint

OctoPrint Plugin 만들기 #2 (UI 수정)

옥토 프린트 플러그인 만들기 (챔버 매니저)


□ UI 수정



1. Control Mode가 「ON/OFF」 또는 「PID」 일 경우, 컨트롤 비활성화



2. Control Mode가 「Manual」 일 경우에만 컨트롤 활성화





[ chambermanager._tab.jinja2 ]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
<div class="control-group">
    <h4>{{ _('Temperature') }}</h4>
    <table>
        <tr>
            <td width="200" valign="center">
                <label class="control-label" for="tempControlMode">{{ _('Control Mode') }}</label>
            </td>
            <td width="400">
                <div class="tempControlOptions">
                    <div class="btn-group" data-toggle="buttons-radio" id="tempControlMode">
                        <!-- ko foreach: tempControlOptions -->
                        <button type="button" class="btn distance" style="width: 130px;padding: 3px 0;height: 30px" data-bind="text: $data, click: function() { $root.changeControlMode($data) }, css: { active: $root.tempControlMode() === $data }, attr: { id: 'tempControlMode_' + $data }"></button>
                        <!-- /ko -->
                    </div>
                </div>
            </td>
        </tr>
        <tr>
            <td width="200"><label class="control-label" for="settings-tempControlTarget">{{ _('Ambient') }}</label></td>
            <td width="400">
                <table><tr>
                    <td width="120" class="temperature_actual" data-bind="html: 'Actual : ' + formatTemperature(tempControlActual()), attr: {title: formatTemperature(tempControlActual())}"></td>
                    </td>
                    <td class="temperature_target">
                        <div class="input-prepend input-append">
                            <button type="button" class="btn btn-input-dec" data-bind="attr : {'disabled' : $root.disableControl}, click: $root.tempControlDecrementTarget" title="{{ _('Fine adjust: -1°C') }}"><i class="fa fa-minus"></i></button>
                            <input type="number" min="0" max="999" class="input-mini input-nospin" style="width: 30px" data-bind="attr : {'disabled' : $root.disableControl}, value: tempControlTarget(), valueUpdate: 'input'">
                            <span class="add-on">&deg;C</span>
                            <button type="button" class="btn btn-input-inc" data-bind="attr : {'disabled' : $root.disableControl}, click: $root.tempControlIncrementTarget" title="{{ _('Fine adjust: +1°C') }}"><i class="fa fa-plus"></i></button>
                            <button type="submit" class="btn btn-primary" data-bind="attr : {'disabled' : $root.disableControl}" title="{{ _('Set') }}"><i class="fa fa-check"></i></button>
                        </div>
                    </td>
                </tr></table>
            </td>
        </tr>
    </table>
 
 
    
    
</div>
 
<br>
<div class="control-group">
    <h4>{{ _('Doors') }}</h4>
    <table>
        <tr>
            <td width="200" valign="center"><label class="control-label" for="settings-doorControlAngle">{{ _('Angle') }}</label></td>
            <td width="400" align="center">
                <div id="control-door-angle" class="jog-panel">
                    <input type="number" style="width: 350px" data-bind="slider: {min: 0, max: 90, step: 1, value: doorControlAngle, tooltip: 'hide', disabled: $root.disableControl}">
                    <button class="btn btn-block" style="width: 390px" data-bind="attr : {'disabled' : $root.disableControl}, click: function() { $root.sendDoorControlAngle() }"><span data-bind="text: doorControlAngle()"></span></button>
                </div>
            </td>
        </tr>
        <tr>
            <td><label class="control-label" for="settings-doorControlPosition">{{ _('Position') }}</label></td>
            <td align="center">
            
                <div class="doorControlPosOptions">
                    <div class="btn-group" data-toggle="buttons-radio" id="doorControlModePosition">
                        <!-- ko foreach: doorControlPosOptions -->
                        <button type="button" class="btn distance" style="width: 130px;padding: 3px 0;height: 30px" data-bind="text: $data, click: function() { $root.doorControlPosValue($data) }, css: { active: $root.doorControlPosValue() === $data }, attr: { id: 'doorControlModePosition_' + $data, 'disabled' : $root.disableControl}"></button>
                        <!-- /ko -->
                    </div>
                </div>
            
            </td>
        </tr>
    </table>
</div>
 
<br>
<div class="control-group">
    <h4>{{ _('Fans') }}</h4>
    <table>
        <tr>
            <th width="200"> </th>
            <th width="200"><h4>Ventilator</h4></th>
            <th width="200"><h4>Filter</h4></th>
        </tr>
    </table>
    <table>
        <tr>
            <td width="200" valign="center"><label class="control-label" for="settings-fansControlSpeed">{{ _('Speed') }}</label></td>
            <td width="200" align="center">
                <div id="control-fan-ventil-speed" class="jog-panel">
                    <input type="number" style="width: 153px" data-bind="slider: {min: 0, max: 100, step: 1, value: fanControlVentilSpeed, tooltip: 'hide'}">
                    <button class="btn btn-block" style="width: 169px" data-bind="attr : {'disabled' : $root.disableControl}, click: function() { $root.sendFanControlVentilSpeed() }"><span data-bind="text: fanControlVentilSpeed() + '%'"></span></button>
                </div>
            </td>
            <td width="200" align="center">
                <div id="control-fan-filter-speed" class="jog-panel">
                    <input type="number" style="width: 153px" data-bind="slider: {min: 0, max: 100, step: 1, value: fanControlFilterSpeed, tooltip: 'hide'}">
                    <button class="btn btn-block" style="width: 169px" data-bind="attr : {'disabled' : $root.disableControl}, click: function() { $root.sendFanControlFilterSpeed() }"><span data-bind="text: fanControlFilterSpeed() + '%'"></span></button>
                </div>
            </td>
        </tr>
    </table>
</div>
 
    
<br>
<div class="control-group">
    <h4>{{ _('Lights') }}</h4>
    <table>
        <tr>
            <td width="200">
                <label class="control-label" for="lightControlMode">{{ _('Control Mode') }}</label>
            </td>
            <td width="400">
                <div class="tempControlOptions">
                    <div class="btn-group" data-toggle="buttons-radio" id="lightControlMode">
                        <!-- ko foreach: lightControlOptions -->
                        <button type="button" class="btn distance" style="width: 130px;padding: 3px 0;height: 30px" data-bind="text: $data, click: function() { $root.lightControlMode($data) }, css: { active: $root.lightControlMode() === $data }, attr: { id: 'lightControlMode_' + $data }"></button>
                        <!-- /ko -->
                    </div>
                </div>
            </td>
        </tr>
    </table>
</div>
 
 
cs



[chambermanager.js]


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
$(function() {
    function ChamberManagerViewModel(parameters) {
        var self = this;
        
        self.settings = parameters[0];
        
        self.disableControl = ko.observable(false);
        
        self.tempControlOptions = ko.observableArray(['Manual','ON/OFF','PID']);
        self.tempControlMode = ko.observable('ON/OFF');
        self.tempControlTarget = ko.observable(26);
        self.tempControlTargetUpdate = ko.observable(26);
        self.tempControlActual = ko.observable(25.5);
        
        self.doorVentilMaxPos = ko.observable(undefined);
        self.doorVentilMinPos = ko.observable(undefined);
        self.doorFilterMaxPos = ko.observable(undefined);
        self.doorFilterMinPos = ko.observable(undefined);
        
        self.doorControlOptions = ko.observableArray(['Manual','Auto']);
        self.doorControlMode = ko.observable('Auto');
        self.doorControlVentilAngle = ko.observable(undefined);
        self.doorControlFilterAngle = ko.observable(undefined);
        self.doorControlPosOptions = ko.observableArray(['OPEN','UNKNOWN','CLOSE']);
        self.doorControlPosValue = ko.observable('UNKNOWN');
        self.doorControlAngle = ko.observable(90);
 
        self.fanControlOptions = ko.observableArray(['Manual','Auto']);
        self.fanControlMode = ko.observable('Auto');
        self.fanControlVentilSpeed = ko.observable(100);
        self.fanControlFilterSpeed = ko.observable(100);
        
        self.lightControlOptions = ko.observableArray(['ON','OFF','Auto']);
        self.lightControlMode = ko.observable('Auto');
        self.lightControlSensitive = ko.observable(undefined);
 
    
        self.changeControlMode = function(mode) {
            try {
                if(mode === 'Manual') {
                    self.tempControlMode('Manual');
                    self.doorControlMode('Manual');
                    self.fanControlMode('Manual');
                    self.settings.settings.plugins.chambermanager.tempControlMode('Manual');
                    self.settings.settings.plugins.chambermanager.doorControlMode('Manual');
                    self.settings.settings.plugins.chambermanager.fanControlMode('Manual');
                    self.disableControl(false);
                }
                if(mode === 'ON/OFF') {
                    self.tempControlMode('ON/OFF');
                    self.doorControlMode('Auto');
                    self.fanControlMode('Auto');
                    self.settings.settings.plugins.chambermanager.tempControlMode('ON/OFF');
                    self.settings.settings.plugins.chambermanager.doorControlMode('Auto');
                    self.settings.settings.plugins.chambermanager.fanControlMode('Auto');
                    self.disableControl(true);
                }
                if(mode === 'PID') {
                    self.tempControlMode('PID');
                    self.doorControlMode('Auto');
                    self.fanControlMode('Auto');
                    self.settings.settings.plugins.chambermanager.tempControlMode('PID');
                    self.settings.settings.plugins.chambermanager.doorControlMode('Auto');
                    self.settings.settings.plugins.chambermanager.fanControlMode('Auto');
                    self.disableControl(true);
                }
                if(mode === 'Auto') {
                    self.tempControlMode('PID');
                    self.doorControlMode('Auto');
                    self.fanControlMode('Auto');
                    self.settings.settings.plugins.chambermanager.tempControlMode('PID');
                    self.settings.settings.plugins.chambermanager.doorControlMode('Auto');
                    self.settings.settings.plugins.chambermanager.fanControlMode('Auto');
                    self.disableControl(true);
                }
            } catch(ex) {
                alert(ex);
            }
            self.settings.saveData();            
        }
 
        
        self.tempControlDecrementTarget = function() {
            var value = self.tempControlTarget();
 
            try {
                value = parseInt(value);
                if (value <= 0return;
                self.tempControlTarget(value - 1);
            } catch (ex) {
                // do nothing
            }
        }
        
        self.tempControlIncrementTarget = function() {
            var value = self.tempControlTarget();
            console.log('test');
            log.debug('test');
            
           try {
                value = parseInt(value);
                if (value >= 999return;
                self.tempControlTarget(value + 1);
            } catch (ex) {
                // do nothing
            }
        }
 
        // This will get called before the ChamberManagerViewModel gets bound to the DOM, but after its
        // dependencies have already been initialized. It is especially guaranteed that this method
        // gets called _after_ the settings have been retrieved from the OctoPrint backend and thus
        // the SettingsViewModel been properly populated.
        self.onBeforeBinding = function() {
            self.bindFromSettings();
        }
        
        self.onSettingsBeforeSave = function() {
            self.bindFromSettings();
        }
        
        
        self.bindFromSettings = function () {
            
            try {
            
                self.tempControlMode(self.settings.settings.plugins.chambermanager.tempControlMode());
                self.tempControlTarget(self.settings.settings.plugins.chambermanager.tempControlTarget());
                
                self.doorVentilMaxPos(self.settings.settings.plugins.chambermanager.doorVentilMaxPos());
                self.doorVentilMinPos(self.settings.settings.plugins.chambermanager.doorVentilMinPos());
                self.doorFilterMaxPos(self.settings.settings.plugins.chambermanager.doorFilterMaxPos());
                self.doorFilterMinPos(self.settings.settings.plugins.chambermanager.doorFilterMinPos());
 
                self.doorControlMode(self.settings.settings.plugins.chambermanager.doorControlMode());
                self.doorControlAngle(self.settings.settings.plugins.chambermanager.doorControlAngle());
                self.doorControlPosValue(self.settings.settings.plugins.chambermanager.doorControlPosValue());
 
                self.fanControlMode(self.settings.settings.plugins.chambermanager.fanControlMode());
                self.fanControlVentilSpeed(self.settings.settings.plugins.chambermanager.fanControlVentilSpeed());
                self.fanControlFilterSpeed(self.settings.settings.plugins.chambermanager.fanControlFilterSpeed());
                
                self.lightControlMode(self.settings.settings.plugins.chambermanager.lightControlMode());
                self.lightControlSensitive(self.settings.settings.plugins.chambermanager.lightControlSensitive());
                
                if(self.tempControlMode() != 'Manual') {
                    self.disableControl(true);
                }
                else {
                    self.disableControl(false);
                }
            
            } catch(ex) {
                alert(ex);
            }
            
        }
    
        
    }
 
    // This is how our plugin registers itself with the application, by adding some configuration
    // information to the global variable OCTOPRINT_VIEWMODELS
    OCTOPRINT_VIEWMODELS.push({
        construct: ChamberManagerViewModel,
        dependencies: ["settingsViewModel"],
        elements: ["#tab_plugin_chambermanager"]
    });
});
cs