homebridge-smartsystem 6.8.13 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.vscode/launch.json +15 -4
- package/MIXINS-GUIDE.md +210 -0
- package/README.md +32 -0
- package/SETTINGS-UPDATE.md +195 -0
- package/TESTING-GUIDE.md +220 -0
- package/WEBSOCKET-API.md +303 -0
- package/accessories/accessory.js +20 -4
- package/accessories/accessory.ts +19 -4
- package/accessories/bulb.js +0 -5
- package/accessories/bulb.ts +1 -5
- package/accessories/dimmer.js +11 -3
- package/accessories/dimmer.ts +11 -4
- package/accessories/garagedoor.js +19 -9
- package/accessories/garagedoor.ts +21 -9
- package/accessories/lock.js +11 -3
- package/accessories/lock.ts +10 -3
- package/accessories/temperature.js +10 -2
- package/accessories/temperature.ts +9 -2
- package/accessories/windowcovering.js +30 -14
- package/accessories/windowcovering.ts +29 -15
- package/config.json +57 -19
- package/duotecno/types.js +48 -2
- package/duotecno/types.ts +75 -1
- package/package.json +12 -4
- package/raspberry-pi-setup.sh +80 -0
- package/server/HA-API.js +4 -1
- package/server/HA-API.ts +4 -1
- package/server/HB.js +6 -1
- package/server/HB.ts +5 -1
- package/server/mDNS.js +168 -0
- package/server/mDNS.ts +198 -0
- package/server/platform.js +7 -0
- package/server/platform.ts +8 -0
- package/server/proxy.js +58 -19
- package/server/proxy.ts +31 -3
- package/server/smartapp.js +397 -18
- package/server/smartapp.ts +432 -20
- package/server/socapp.js +2 -1
- package/server/socapp.ts +2 -1
- package/server/views/assets/Duotecno_logo_black.svg +10 -0
- package/server/views/assets/Duotecno_logo_white.svg +10 -0
- package/server/views/device-details.ejs +139 -0
- package/server/views/device-list.ejs +44 -0
- package/server/views/footer.ejs +0 -1
- package/server/views/head.ejs +9 -0
- package/server/views/homekit.ejs +2 -9
- package/server/views/link-details.ejs +2 -15
- package/server/views/link-list.ejs +2 -9
- package/server/views/login.ejs +8 -9
- package/server/views/master-detail.ejs +3 -9
- package/server/views/master-list.ejs +3 -10
- package/server/views/nav.ejs +44 -11
- package/server/views/node-details.ejs +1 -8
- package/server/views/power-binding.ejs +3 -10
- package/server/views/power-rule.ejs +3 -10
- package/server/views/power.ejs +8 -15
- package/server/views/proxy.ejs +1 -8
- package/server/views/scripts.ejs +10 -0
- package/server/views/service-list.ejs +2 -9
- package/server/views/settings.ejs +61 -22
- package/server/views/style.ejs +49 -5
- package/server/views/switch-details.ejs +2 -9
- package/server/views/switch-list.ejs +2 -9
- package/server/webapp.js +150 -11
- package/server/webapp.ts +166 -14
- package/{index.spec.js → testHB.js} +1 -1
- package/{run.js → testProxy.js} +2 -2
- package/{run.ts → testProxy.ts} +1 -1
- package/testWS.js +137 -0
- package/testWS.ts +174 -0
- package/run9998.js +0 -7
- package/run9998.ts +0 -6
- package/run9999.js +0 -7
- package/run9999.ts +0 -6
- /package/{index.spec.ts → testHB.ts} +0 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
5
|
+
</head>
|
|
6
|
+
|
|
7
|
+
<body>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
9
|
+
|
|
10
|
+
<form method="POST" action="/devices">
|
|
11
|
+
<input type="hidden" name="daction" value="save">
|
|
12
|
+
<input type="hidden" name="id" value="<%= id %>">
|
|
13
|
+
<h1>
|
|
14
|
+
Device #<%= id+1 %>
|
|
15
|
+
<button class="right btn waves-effect waves-light" type="submit" name="action" value="cancel">Back</button>
|
|
16
|
+
<button class="right btn waves-effect waves-light" type="submit" name="action" value="delete">Delete</button>
|
|
17
|
+
<button class="right btn waves-effect waves-light" type="submit" name="action" value="change">Save</button>
|
|
18
|
+
</h1>
|
|
19
|
+
|
|
20
|
+
<div class="row">
|
|
21
|
+
<div class="input-field col s12">
|
|
22
|
+
<input placeholder="Device Name" id="name" name="name" type="text"
|
|
23
|
+
value="<%= (device.name) %>">
|
|
24
|
+
<label for="name">Name</label>
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="row">
|
|
29
|
+
<div class="input-field col s5">
|
|
30
|
+
<select name="master" id="master">
|
|
31
|
+
<% for (let m of masters) { %>
|
|
32
|
+
<option value="<%= m.getURL() %>" <%= (m.same(device.masterAddress, device.masterPort)) ? "selected" : "" %>><%= m.getURL() %></option>
|
|
33
|
+
<% } %>
|
|
34
|
+
</select>
|
|
35
|
+
<label for="master">Master of device unit</label>
|
|
36
|
+
</div>
|
|
37
|
+
</div>
|
|
38
|
+
|
|
39
|
+
<div class="row">
|
|
40
|
+
<div class="input-field col s5">
|
|
41
|
+
<input placeholder="0" id="unit" name="unit" type="text"
|
|
42
|
+
value="<%= hex(device.logicalNodeAddress) %>;<%= hex(device.logicalAddress) %><%= (device.unitName) ? (' (' + device.unitName + ')') : '' %>">
|
|
43
|
+
<label for="unit">Duotecno node;unit (example: 0xfc;0x12) or search unit name</label>
|
|
44
|
+
</div>
|
|
45
|
+
<div class="input-field col s5">
|
|
46
|
+
<select name="unitSelector" id="unitSelector">
|
|
47
|
+
<option value="">Select a unit</option>
|
|
48
|
+
<% for (let u of units) { %>
|
|
49
|
+
<option value="<%= u.node.master.getURL()+"-"+u.logicalNodeAddress+"/"+u.logicalAddress %>"
|
|
50
|
+
<%= ((u.node.master.config.address == device.masterAddress) && (u.node.master.config.port == device.masterPort) && (u.logicalNodeAddress == device.logicalNodeAddress) && (u.logicalAddress == device.logicalAddress)) ? "selected" : "" %>
|
|
51
|
+
><%= u.name %></option>
|
|
52
|
+
<% } %>
|
|
53
|
+
</select>
|
|
54
|
+
<label for="unitSelector">or Pick a unit</label>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<div class="row">
|
|
59
|
+
<div class="input-field col s6">
|
|
60
|
+
<select name="powerSource" id="powerSource">
|
|
61
|
+
<option value="none" <%= (!device.powerSource || device.powerSource === 'none') ? 'selected' : '' %>>Non-measured (Estimated)</option>
|
|
62
|
+
<option value="p1" <%= (device.powerSource === 'p1') ? 'selected' : '' %>>P1 Meter</option>
|
|
63
|
+
<option value="shelly" <%= (device.powerSource === 'shelly') ? 'selected' : '' %>>Shelly PM</option>
|
|
64
|
+
<option value="smappee" <%= (device.powerSource === 'smappee') ? 'selected' : '' %>>Smappee</option>
|
|
65
|
+
</select>
|
|
66
|
+
<label for="powerSource">Power Source</label>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
|
|
70
|
+
<div class="row" id="channelRow" style="display: <%= (device.powerSource && device.powerSource !== 'none') ? 'block' : 'none' %>">
|
|
71
|
+
<div class="input-field col s6">
|
|
72
|
+
<input placeholder="Channel/Register" id="powerChannel" name="powerChannel" type="text"
|
|
73
|
+
value="<%= device.powerChannel || '' %>">
|
|
74
|
+
<label for="powerChannel">Power Channel (e.g., "0", "0+1+2")</label>
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<div class="row" id="estimatedRow" style="display: <%= (!device.powerSource || device.powerSource === 'none') ? 'block' : 'none' %>">
|
|
79
|
+
<div class="input-field col s6">
|
|
80
|
+
<input placeholder="Estimated Power (W)" id="estimatedPower" name="estimatedPower" type="number"
|
|
81
|
+
value="<%= device.estimatedPower || 0 %>">
|
|
82
|
+
<label for="estimatedPower">Estimated Power (Watts)</label>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
85
|
+
|
|
86
|
+
<div class="row">
|
|
87
|
+
<div class="input-field col s6">
|
|
88
|
+
<input placeholder="Device ID (auto-calculated)" id="deviceId" name="deviceId" type="text"
|
|
89
|
+
value="<%= device.id %>" readonly>
|
|
90
|
+
<label for="deviceId">Device ID (node * 256 + unit)</label>
|
|
91
|
+
</div>
|
|
92
|
+
</div>
|
|
93
|
+
|
|
94
|
+
</form>
|
|
95
|
+
<%- include('/views/footer'); -%>
|
|
96
|
+
|
|
97
|
+
</body>
|
|
98
|
+
|
|
99
|
+
<%- include('/views/scripts'); -%>
|
|
100
|
+
<script>
|
|
101
|
+
const select = document.getElementById("unitSelector");
|
|
102
|
+
if (select) {
|
|
103
|
+
select.addEventListener("change", function() {
|
|
104
|
+
const parts = this.value.split("-");
|
|
105
|
+
const unitParts = parts[1].split("/");
|
|
106
|
+
const node = parseInt(unitParts[0]);
|
|
107
|
+
const unit = parseInt(unitParts[1]);
|
|
108
|
+
|
|
109
|
+
document.getElementById("unit").value = hex(node) + ";" + hex(unit);
|
|
110
|
+
document.getElementById("master").value = parts[0];
|
|
111
|
+
|
|
112
|
+
// Update device ID
|
|
113
|
+
const deviceId = (node * 256) + unit;
|
|
114
|
+
document.getElementById("deviceId").value = deviceId;
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Power source selection
|
|
119
|
+
const powerSourceSelect = document.getElementById("powerSource");
|
|
120
|
+
if (powerSourceSelect) {
|
|
121
|
+
powerSourceSelect.addEventListener("change", function() {
|
|
122
|
+
const channelRow = document.getElementById("channelRow");
|
|
123
|
+
const estimatedRow = document.getElementById("estimatedRow");
|
|
124
|
+
|
|
125
|
+
if (this.value === "none") {
|
|
126
|
+
channelRow.style.display = "none";
|
|
127
|
+
estimatedRow.style.display = "block";
|
|
128
|
+
} else {
|
|
129
|
+
channelRow.style.display = "block";
|
|
130
|
+
estimatedRow.style.display = "none";
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function hex(nr) {
|
|
136
|
+
return "0x" + nr.toString(16).padStart(2, '0');
|
|
137
|
+
}
|
|
138
|
+
</script>
|
|
139
|
+
</html>
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
5
|
+
</head>
|
|
6
|
+
|
|
7
|
+
<body>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
9
|
+
|
|
10
|
+
<form method="POST" action="/devices">
|
|
11
|
+
<h1>
|
|
12
|
+
Devices
|
|
13
|
+
<button class="right btn waves-effect waves-light" type="submit" name="action" value="add">Add device</button>
|
|
14
|
+
</h1>
|
|
15
|
+
|
|
16
|
+
<table>
|
|
17
|
+
<thead>
|
|
18
|
+
<tr>
|
|
19
|
+
<th>Name</th><th>ID</th><th>Duotecno Unit</th><th>node/unit</th><th>Measured</th><th>Relay</th>
|
|
20
|
+
</tr>
|
|
21
|
+
</thead>
|
|
22
|
+
|
|
23
|
+
<tbody>
|
|
24
|
+
<% for (let inx in devices) { let device = devices[inx]; %>
|
|
25
|
+
<tr>
|
|
26
|
+
<td><a href="/devices/edit/<%= inx %>"><%= device.name %></a></td>
|
|
27
|
+
<td><a href="/devices/edit/<%= inx %>"><%= device.id %></a></td>
|
|
28
|
+
<td><a href="/devices/edit/<%= inx %>"><%= device.unit?.name || "--" %></a></td>
|
|
29
|
+
<td><a href="/devices/edit/<%= inx %>"><%= hex(device.logicalNodeAddress) %>/<%= hex(device.logicalAddress) %></a></td>
|
|
30
|
+
<td><%= device.measured ? '✓' : '✗' %></td>
|
|
31
|
+
<td><%= device.relay ? 'ON' : 'OFF' %></td>
|
|
32
|
+
</tr>
|
|
33
|
+
<% } %>
|
|
34
|
+
</tbody>
|
|
35
|
+
</table>
|
|
36
|
+
|
|
37
|
+
</form>
|
|
38
|
+
|
|
39
|
+
<%- include('/views/footer'); -%>
|
|
40
|
+
</body>
|
|
41
|
+
|
|
42
|
+
<%- include('/views/scripts'); -%>
|
|
43
|
+
|
|
44
|
+
</html>
|
package/server/views/footer.ejs
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
<meta charset="UTF-8">
|
|
2
|
+
<link type="text/css" rel="stylesheet" href="/files/min.css" media="screen,projection"/>
|
|
3
|
+
|
|
4
|
+
<!--Let browser know website is optimized for mobile-->
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
6
|
+
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
7
|
+
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
8
|
+
|
|
9
|
+
<%- include('/views/style'); -%>
|
package/server/views/homekit.ejs
CHANGED
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
16
9
|
|
|
17
10
|
<form method="POST" action="/homekit">
|
|
18
11
|
<input type="hidden" name="daction" value="save">
|
|
@@ -1,20 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
12
|
-
<style>
|
|
13
|
-
div.select-wrapper input.select-dropdown {
|
|
14
|
-
font-size: 16px !important;
|
|
15
|
-
height: 3rem !important;
|
|
16
|
-
}
|
|
17
|
-
</style>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
18
5
|
</head>
|
|
19
6
|
|
|
20
7
|
<body>
|
|
@@ -24,7 +11,7 @@
|
|
|
24
11
|
<input type="hidden" name="daction" value="save">
|
|
25
12
|
<input type="hidden" name="id" value="<%= id %>">
|
|
26
13
|
<h1>
|
|
27
|
-
Link #<%= id %>
|
|
14
|
+
Link #<%= id+1 %>
|
|
28
15
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="cancel">Back</button>
|
|
29
16
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="delete">Delete</button>
|
|
30
17
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="change">Save</button>
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
16
9
|
|
|
17
10
|
<form method="POST" action="/links">
|
|
18
11
|
<h1>
|
package/server/views/login.ejs
CHANGED
|
@@ -1,20 +1,19 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
8
|
<nav>
|
|
16
9
|
<div class="nav-wrapper">
|
|
17
|
-
<a href="/"
|
|
10
|
+
<a href="/" class="brand-logo left" style="display: flex; align-items: center; gap: 20px; margin: 2px 0 0 2px">
|
|
11
|
+
<img src="/files/Duotecno_logo_white.svg" alt="Duotecno" style="height: 46px; width: auto">
|
|
12
|
+
<div style="display: flex; flex-direction: column; line-height: 1.2; margin-top: 12px">
|
|
13
|
+
<span style="font-size: 1.3rem; font-weight: bolder;">Duotecno Gateway</span>
|
|
14
|
+
<span style="font-size: 0.7rem; font-weight: 300;">Configuration Interface</span>
|
|
15
|
+
</div>
|
|
16
|
+
</a>
|
|
18
17
|
</div>
|
|
19
18
|
</nav>
|
|
20
19
|
|
|
@@ -1,19 +1,13 @@
|
|
|
1
1
|
|
|
2
|
-
|
|
3
2
|
<!DOCTYPE html>
|
|
4
3
|
<html>
|
|
5
4
|
<head>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<!--Let browser know website is optimized for mobile-->
|
|
9
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
10
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
11
|
-
|
|
12
|
-
<%- include('/views/style'); -%>
|
|
5
|
+
<%- include('/views/head'); -%>
|
|
13
6
|
</head>
|
|
14
7
|
|
|
15
8
|
<body>
|
|
16
|
-
<%- include('/views/nav'); -%>
|
|
9
|
+
<%- include('/views/nav', this); -%>
|
|
10
|
+
|
|
17
11
|
<form method="POST" action="/masters">
|
|
18
12
|
<input type="hidden" name="daction" value="save">
|
|
19
13
|
<h1>
|
|
@@ -1,19 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
1
|
<!DOCTYPE html>
|
|
4
2
|
<html>
|
|
5
3
|
<head>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
<!--Let browser know website is optimized for mobile-->
|
|
9
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
10
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
11
|
-
|
|
12
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
13
5
|
</head>
|
|
14
6
|
|
|
15
7
|
<body>
|
|
16
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
9
|
+
|
|
17
10
|
<form method="POST" action="/masters/new">
|
|
18
11
|
<h1>
|
|
19
12
|
Masters
|
package/server/views/nav.ejs
CHANGED
|
@@ -1,20 +1,53 @@
|
|
|
1
1
|
<nav>
|
|
2
2
|
<div class="nav-wrapper">
|
|
3
|
-
<a href="/
|
|
4
|
-
|
|
5
|
-
<
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
3
|
+
<a href="/" class="brand-logo left" style="display: flex; align-items: center; gap: 20px; margin: 2px 0 0 2px">
|
|
4
|
+
<img src="/files/Duotecno_logo_white.svg" alt="Duotecno" style="height: 46px; width: auto">
|
|
5
|
+
<div style="display: flex; flex-direction: column; line-height: 1.2; margin-top: 12px">
|
|
6
|
+
<span style="font-size: 1.3rem; font-weight: bolder;">Duotecno Gateway</span>
|
|
7
|
+
<span style="font-size: 0.7rem; font-weight: 300;">Configuration Interface</span>
|
|
8
|
+
</div>
|
|
9
|
+
</a>
|
|
10
|
+
|
|
11
|
+
<!-- Hamburger Menu Icon (Mobile Only) -->
|
|
12
|
+
<a href="#" data-target="mobile-menu" class="sidenav-trigger right"><i class="material-icons">menu</i></a>
|
|
13
|
+
|
|
14
|
+
<!-- Desktop Menu -->
|
|
15
|
+
<ul class="right hide-on-med-and-down">
|
|
16
|
+
<li <% if (request === "masters") { %>class="active"<% } %>><a href="/masters">Masters</a></li>
|
|
17
|
+
<li <% if (request === "services") { %>class="active"<% } %>><a href="/services">Services</a></li>
|
|
18
|
+
<li <% if (request === "proxy") { %>class="active"<% } %>><a href="/proxy">Proxy</a></li>
|
|
19
|
+
<li <% if (request === "links") { %>class="active"<% } %>><a href="/links">Links</a></li>
|
|
20
|
+
<li <% if (request === "devices") { %>class="active"<% } %>><a href="/devices">Devices</a></li>
|
|
21
|
+
<% if (hasSmappee) { %><li <% if ((request === "power") && (type === "smappee")) { %>class="active"<% } %>><a href="/power?type=smappee">Smappee</a></li><% } %>
|
|
22
|
+
<% if (hasP1) { %><li <% if ((request === "power") && (type === "p1")) { %>class="active"<% } %>><a href="/power?type=p1">P1</a></li><% } %>
|
|
23
|
+
<% if (hasShelly) { %><li <% if ((request === "power") && (type === "shelly")) { %>class="active"<% } %>><a href="/power?type=shelly">Shelly</a></li><% } %>
|
|
24
|
+
<li <% if (request === "switches") { %>class="active"<% } %>><a href="/switches">Switches</a></li>
|
|
25
|
+
<li <% if (request === "settings") { %>class="active"<% } %>><a href="/settings">Settings</a></li>
|
|
14
26
|
</ul>
|
|
15
27
|
</div>
|
|
16
28
|
</nav>
|
|
17
29
|
|
|
30
|
+
<!-- Mobile Slide-out Menu -->
|
|
31
|
+
<ul class="sidenav" id="mobile-menu">
|
|
32
|
+
<li><div class="user-view">
|
|
33
|
+
<div class="background blue darken-2"></div>
|
|
34
|
+
<span class="white-text name">Duotecno Gateway</span>
|
|
35
|
+
</div></li>
|
|
36
|
+
<li <% if (request === "masters") { %>class="active"<% } %>><a href="/masters">Masters</a></li>
|
|
37
|
+
<li <% if (request === "services") { %>class="active"<% } %>><a href="/services">Services</a></li>
|
|
38
|
+
<li><div class="divider"></div></li>
|
|
39
|
+
<li <% if (request === "devices") { %>class="active"<% } %>><a href="/devices">Devices</a></li>
|
|
40
|
+
<li <% if (request === "links") { %>class="active"<% } %>><a href="/links">Links</a></li>
|
|
41
|
+
<li <% if (request === "switches") { %>class="active"<% } %>><a href="/switches">Switches</a></li>
|
|
42
|
+
<li><div class="divider"></div></li>
|
|
43
|
+
<% if (hasSmappee) { %><li <% if ((request === "power") && (type === "smappee")) { %>class="active"<% } %>><a href="/power?type=smappee">Smappee</a></li><% } %>
|
|
44
|
+
<% if (hasP1) { %><li <% if ((request === "power") && (type === "p1")) { %>class="active"<% } %>><a href="/power?type=p1">P1 Meter</a></li><% } %>
|
|
45
|
+
<% if (hasShelly) { %><li <% if ((request === "power") && (type === "shelly")) { %>class="active"<% } %>><a href="/power?type=shelly">Shelly PM</a></li><% } %>
|
|
46
|
+
<li><div class="divider"></div></li>
|
|
47
|
+
<li <% if (request === "proxy") { %>class="active"<% } %>><a href="/proxy">Proxy</a></li>
|
|
48
|
+
<li <% if (request === "settings") { %>class="active"<% } %>><a href="/settings">Settings</a></li>
|
|
49
|
+
</ul>
|
|
50
|
+
|
|
18
51
|
<% if (notReady) { %>
|
|
19
52
|
<h2>Not ready</h2>
|
|
20
53
|
<div>
|
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
16
9
|
|
|
17
10
|
<form method="POST" action="/power">
|
|
18
11
|
<input type="hidden" name="daction" value="bchange">
|
|
@@ -20,7 +13,7 @@
|
|
|
20
13
|
<input type="hidden" name="type" value="<%= type %>">
|
|
21
14
|
|
|
22
15
|
<h1>
|
|
23
|
-
Binding #<%= id %>
|
|
16
|
+
Binding #<%= id+1 %>
|
|
24
17
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="cancel">Back</button>
|
|
25
18
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="bdelete">Delete</button>
|
|
26
19
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="bchange">Save</button>
|
|
@@ -1,25 +1,18 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
16
9
|
|
|
17
10
|
<form method="POST" action="/power">
|
|
18
11
|
<input type="hidden" name="daction" value="change">
|
|
19
12
|
<input type="hidden" name="id" value="<%= id %>">
|
|
20
13
|
<input type="hidden" name="type" value="<%= type %>">
|
|
21
14
|
<h1>
|
|
22
|
-
Power rule #<%= id %>
|
|
15
|
+
Power rule #<%= id+1 %>
|
|
23
16
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="cancel">Back</button>
|
|
24
17
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="delete">Delete</button>
|
|
25
18
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="change">Save</button>
|
package/server/views/power.ejs
CHANGED
|
@@ -1,31 +1,24 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
16
9
|
|
|
17
10
|
<form method="POST" action="/power">
|
|
18
11
|
<input type="hidden" name="daction" value="save">
|
|
19
12
|
<input type="hidden" name="type" value="<%= type %>">
|
|
20
13
|
<h1>
|
|
21
|
-
Power measuring - <%= type %>
|
|
14
|
+
Power measuring - <%= cap(type) %>
|
|
22
15
|
<button class="right btn waves-effect waves-light" type="submit" name="action" value="save">Save</button>
|
|
23
16
|
</h1>
|
|
24
17
|
|
|
25
18
|
<div class="row">
|
|
26
19
|
<div class="input-field col s12">
|
|
27
20
|
<input placeholder="xx.xx.xx.xx" id="address" name="address" type="text" value="<%= config.address %>">
|
|
28
|
-
<label for="address"
|
|
21
|
+
<label for="address"><%= cap(type) %> Address</label>
|
|
29
22
|
</div>
|
|
30
23
|
</div>
|
|
31
24
|
|
|
@@ -33,7 +26,7 @@
|
|
|
33
26
|
<div class="row">
|
|
34
27
|
<div class="input-field col s12">
|
|
35
28
|
<input id="uid" name="uid" type="text" value="<%= config.uid %>">
|
|
36
|
-
<label for="uid"
|
|
29
|
+
<label for="uid"><%= cap(type) %> UID</label>
|
|
37
30
|
</div>
|
|
38
31
|
</div>
|
|
39
32
|
<% } %>
|
|
@@ -42,7 +35,7 @@
|
|
|
42
35
|
<div class="row">
|
|
43
36
|
<div class="input-field col s12">
|
|
44
37
|
<input placeholder="xx.xx.xx.xx, ..." id="addresses" name="addresses" type="text" value="<%= config.addresses %>">
|
|
45
|
-
<label for="addresses">
|
|
38
|
+
<label for="addresses">Extra <%= type %> addresses (komma separated)</label>
|
|
46
39
|
</div>
|
|
47
40
|
</div>
|
|
48
41
|
<% } %>
|
|
@@ -54,7 +47,7 @@
|
|
|
54
47
|
<thead>
|
|
55
48
|
<tr>
|
|
56
49
|
<th>Type</th><th>Channel</th><th>Result</th><th>Power</th>
|
|
57
|
-
<th>Low...Mid...High</th><th>Current Unit</th>
|
|
50
|
+
<th style="text-align: center">Low ... Mid ... High</th><th>Current Unit</th>
|
|
58
51
|
</tr>
|
|
59
52
|
</thead>
|
|
60
53
|
|
|
@@ -75,7 +68,7 @@
|
|
|
75
68
|
(rule.current == 0) ? 'low' : '--'
|
|
76
69
|
))) %></a></td>
|
|
77
70
|
<td><a href="/power/rule/<%= inx %>?type=<%= type%>"><%= ((rule.power) ? rule.power : '-') %></a></td>
|
|
78
|
-
<td><a href="/power/rule/<%= inx %>?type=<%= type%>"
|
|
71
|
+
<td style="text-align: center"><a href="/power/rule/<%= inx %>?type=<%= type%>">... <%= rule.low %> ... <%= rule.high %> ...</a></td>
|
|
79
72
|
<td><%= hex(rule.actions[0].logicalNodeAddress) %>;<%= hex(rule.actions[0].logicalAddress) %></td>
|
|
80
73
|
</tr>
|
|
81
74
|
<% } %>
|
package/server/views/proxy.ejs
CHANGED
|
@@ -1,14 +1,7 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
package/server/views/scripts.ejs
CHANGED
|
@@ -5,7 +5,17 @@
|
|
|
5
5
|
Array.prototype.forEach.call(document.getElementsByClassName("indeterminate"), element => {
|
|
6
6
|
element.indeterminate = true;
|
|
7
7
|
});
|
|
8
|
+
|
|
9
|
+
// Initialize all Materialize components
|
|
8
10
|
M.AutoInit();
|
|
11
|
+
|
|
12
|
+
// Explicitly initialize sidenav for mobile menu
|
|
13
|
+
const sidenavElems = document.querySelectorAll('.sidenav');
|
|
14
|
+
M.Sidenav.init(sidenavElems, {
|
|
15
|
+
edge: 'right',
|
|
16
|
+
draggable: true
|
|
17
|
+
});
|
|
18
|
+
|
|
9
19
|
const msg = `<%= (typeof message === 'undefined') ? '' : message %>`;
|
|
10
20
|
if (msg) M.toast({html: msg});
|
|
11
21
|
console.log("Ready to rock & roll");
|
|
@@ -1,18 +1,11 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
<!--Let browser know website is optimized for mobile-->
|
|
7
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
|
8
|
-
<link rel="shortcut icon" href="/files/favicon.ico" type="image/x-icon" />
|
|
9
|
-
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
|
|
10
|
-
|
|
11
|
-
<%- include('/views/style'); -%>
|
|
4
|
+
<%- include('/views/head'); -%>
|
|
12
5
|
</head>
|
|
13
6
|
|
|
14
7
|
<body>
|
|
15
|
-
<%- include('/views/nav'); -%>
|
|
8
|
+
<%- include('/views/nav', this); -%>
|
|
16
9
|
|
|
17
10
|
<form method="POST" action="/units/save">
|
|
18
11
|
<h1>
|