diff --git a/ChangeLog.md b/ChangeLog.md
index 16029f76..bd5b58d4 100644
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -11,6 +11,7 @@
* added numeric, verbose, and required options to JSON and use "null" for unset or replacement value
* allow static ".json" files being served by HTTP port
* allow passing raw value when writing name/value pairs
+* enhanced static HTML user interface to dynamic
## Changed files
https://github.com/john30/ebusd/compare/v1.2.0...master
diff --git a/contrib/html/img/bai.svg b/contrib/html/img/bai.svg
new file mode 100644
index 00000000..d8cca718
--- /dev/null
+++ b/contrib/html/img/bai.svg
@@ -0,0 +1,851 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/html/img/buffer.svg b/contrib/html/img/buffer.svg
new file mode 100644
index 00000000..367d83fb
--- /dev/null
+++ b/contrib/html/img/buffer.svg
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/contrib/html/index.html b/contrib/html/index.html
index caa196aa..7e4e7d86 100644
--- a/contrib/html/index.html
+++ b/contrib/html/index.html
@@ -11,74 +11,6 @@
-
-
DCF
-
??? °C
-
Datum Zeit
-
-
Source
-
-
EHP
-
?? °C
-
??? bar
-
?? °C
-
???
-
T6 °C
-
?? bar
-
T5 °C
-
??
-
???
-
???
-
T1 °C
-
?? bar
-
???
-
???
-
???
-
T2 °C
-
T4 °C
-
?? bar
-
???
-
???
-
-
-
-
Storage
-
?? °C
-
?? °C
-
?? °C
-
-
-
Heating 2
-
?? °C
-
???
-
???
-
?? %
-
?? %
-
-
-
-
Heating 4
-
?? °C
-
???
-
???
-
?? %
-
?? %
-
-
-
@@ -156,19 +88,12 @@ jsPlumb.ready(function() {
width: 12,
height: 12
},
- maxConnections: -1,
+ maxConnections: 1,
isSource: true,
connectorStyle: connectorPaintStyle,
hoverPaintStyle: endpointHoverStyle,
connectorHoverStyle: connectorHoverStyle,
- dragOptions: {},
- xoverlays: [
- [ "Label", {
- location: [0.5, 1.5],
- label: "out",
- cssClass: "endpointSourceLabel"
- }]
- ]
+ dragOptions: {}
},
// the definition of target endpoints (will appear when the user drags a connection)
targetEndpoint = {
@@ -182,40 +107,20 @@ jsPlumb.ready(function() {
height: 12
},
hoverPaintStyle: endpointHoverStyle,
- maxConnections: -1,
+ maxConnections: 1,
dropOptions: { hoverClass: "hover", activeClass: "active" },
isTarget: true,
- connector: [ "Flowchart", { stub: [20, 20], gap: 6, cornerRadius: 5, alwaysRespectStubs: true } ],
- xoverlays: [
- [ "Label", {
- location: [0.5, -0.5],
- label: "in",
- cssClass: "endpointTargetLabel"
- }]
- ]
+ connector: [ "Flowchart", { stub: [20, 20], gap: 6, cornerRadius: 5, alwaysRespectStubs: true } ]
},
init = function(connection) {
connection.getOverlay("label").setLabel(connection.endpoints[0].getParameter('name'));
};
- var _addEndpoints = function(divId, anchors) {
+ var addEndpoints = function(divId, anchors, needConnections) {
for (var i = 0; i < anchors.length; i++) {
var anchor = anchors[i];
var anchUUID = divId + anchor.name;
var endpoint = anchor.target ? targetEndpoint : sourceEndpoint;
- var overlays = endpoint.xoverlays.slice(1);
- var label = anchor.label ? anchor.label : anchor.name;
- if (false && label) {
- var location = anchor.target ? [0.5, -0.5] : [0.5, 0.5];
- if (Array.isArray(anchor.anchor)) {
- location = [0.5-3*anchor.anchor[2], 0.5-2*anchor.anchor[3]];
- }
- overlays[overlays.length] = ["Label", {
- location: location,
- label: label,
- cssClass: anchor.target ? "endpointTargetLabel" : "endpointSourceLabel"
- }];
- }
if (anchor.distance && endpoint.connector) {
endpoint = jsPlumbUtil.clone(endpoint);
if (Array.isArray(anchor.distance)) {
@@ -228,9 +133,12 @@ jsPlumb.ready(function() {
endpoint.connector[1].stub[anchor.target?1:0] += anchor.distance;
}
}
+ if (anchor.hasOwnProperty('connectWith') && needConnections) {
+ needConnections.push(new Array(anchUUID).concat(anchor.connectWith)); // to-circuit, to-endpoint[, item-circuit, item-name[, item-parts]]
+ }
instance.addEndpoint(divId, endpoint, {
- anchor: anchor.anchor, uuid: anchUUID, overlays: overlays,
- parameters:{name:anchor.name}
+ anchor: anchor.anchor, uuid: anchUUID,
+ parameters:{name:anchor.name, priority:anchor.priority}
});
}
};
@@ -256,61 +164,11 @@ jsPlumb.ready(function() {
var sourceFlow, sourceReturn, hwcReturn, ehpFlow, hcFlow, hwcFlow, hcReturn, mixFlow, mixReturn, storHwcFlow, storHwcReturn;
// suspend drawing and initialise.
instance.batch(function() {
- _addEndpoints("source", [
- {name:"Output", anchor:[0.25, 0, 0, -1], label: "Source"},
- {name:"Input", anchor:[0.75, 0, 0, -1], target:true, label: "Source"},
- ]);
- _addEndpoints("ehp", [
- {name:"SourceOutput", anchor:[0.12, 0, 0, -1], label: "Source"},
- {name:"SourceInput", anchor:[0.22, 0, 0, -1], target:true, label: "Source", distance:[0,60]},
- {name:"HwcReturn", anchor:[0.53, 0, 0, -1], target:true, distance:[0,80,0.3]},
- {name:"HcReturn", anchor:[0.78, 0, 0, -1], target:true, distance:[0,60,0.42]},
- {name:"Flow", anchor:[0.88, 0, 0, -1]}
- ]);
- _addEndpoints("valve", [
- {name:"Flow", anchor:"Top", target:true},
- {name:"HwcFlow", anchor:"Right"},
- {name:"HcFlow", anchor:"Left"}
- ]);
- _addEndpoints("storage", [
- {name:"HwcOutput", anchor:[0, 0.06, -1, 0]},
- {name:"HwcInput", anchor:[1, 0.06, 1, 0], target:true, distance:[0,0,0.8]},
- {name:"HwcFlow", anchor:[0, 0.24, -1, 0], target:true},
- {name:"HwcReturn", anchor:[0, 0.43, -1, 0]},
- {name:"MixFlow", anchor:[1, 0.47, 1, 0]},
- {name:"HcFlow", anchor:[0, 0.53, -1, 0], target:true},
- {name:"MixReturn", anchor:[1, 0.62, 1, 0], target:true, distance:[0,0,0.7]},
- {name:"HcReturn", anchor:[0, 0.67, -1, 0]}
- ]);
- _addEndpoints("mc", [
- {name:"Flow", anchor:[0, 0.82, -1, 0], target:true, distance:[0,0,0.7]},
- {name:"Return", anchor:[0, 0.96, -1, 0]}
- ]);
- _addEndpoints("hwc", [
- {name:"Return", anchor:[1, 0.82, 1, 0]},
- {name:"Flow", anchor:[0, 0.82, -1, 0], target:true, distance:[40,0,0.5]}
- ]);
// listen for new connections; initialise them the same way we initialise the connections at startup.
instance.bind("connection", function(connInfo, originalEvent) {
init(connInfo.connection);
});
- // make all the window divs draggable
- instance.draggable(jsPlumb.getSelector(".ebus .circuit"), { grid: [20, 20] });
-
- // connections
- sourceFlow = instance.connect({uuids: ["sourceOutput", "ehpSourceInput"], editable: true});
- sourceReturn = instance.connect({uuids: ["ehpSourceOutput", "sourceInput"], editable: true});
- hwcReturn = instance.connect({uuids: ["storageHwcReturn", "ehpHwcReturn"], editable: true});
- ehpFlow = instance.connect({uuids: ["ehpFlow", "valveFlow"], editable: true});
- hcFlow = instance.connect({uuids: ["valveHcFlow", "storageHcFlow"], editable: true});
- hwcFlow = instance.connect({uuids: ["valveHwcFlow", "storageHwcFlow"], editable: true});
- hcReturn = instance.connect({uuids: ["storageHcReturn", "ehpHcReturn"], editable: true});
- mixFlow = instance.connect({uuids: ["storageMixFlow", "mcFlow"], editable: true});
- mixReturn = instance.connect({uuids: ["mcReturn", "storageMixReturn"], editable: true});
- storHwcFlow = instance.connect({uuids: ["storageHwcOutput", "hwcFlow"], editable: true});
- storHwcReturn = instance.connect({uuids: ["hwcReturn", "storageHwcInput"], editable: true});
-
instance.bind("click", function(conn, originalEvent) {
if (conn.hasType("hot")) {
conn.toggleType("hot");
@@ -333,165 +191,355 @@ jsPlumb.ready(function() {
instance.bind("connectionMoved", function(params) {
console.log("connection " + params.connection.id + " was moved");
});
- sourceFlow.setType("hot");
+ /*sourceFlow.setType("hot");
sourceReturn.setType("cold");
mixFlow.setType("hot");
mixReturn.setType("cold");
storHwcFlow.setType("hot");
- storHwcReturn.setType("off");
- });
+ storHwcReturn.setType("off");*/
- //jsPlumb.fire("jsPlumbDemoLoaded", instance);
- var heat = false, water = false;
- var switchActions = {
- broadcasthwStatus: function(fields){
- console.log("action broadcasthwStatus:"+fields);
- if (!fields) return;
- var val = fields[0].value;
- if (val=='on') {
- water = true;
- ehpFlow.addType("hot");
- hcFlow.removeType("hot");
- hwcFlow.addType("hot");
- hcReturn.removeType("cold");
- hwcReturn.addType("cold");
- } else {
- water = false;
- hwcFlow.removeType("hot");
- hwcReturn.removeType("cold");
- if (!heat) {
- ehpFlow.removeType("hot");
+ var heat = false, water = false;
+ var switchActions = {
+ broadcasthwStatus: function(fields){
+ console.log("action broadcasthwStatus:"+fields);
+ if (!fields) return;
+ var val = fields[0].value;
+ if (val=='on') {
+ water = true;
+ ehpFlow.addType("hot");
hcFlow.removeType("hot");
+ hwcFlow.addType("hot");
hcReturn.removeType("cold");
- }
- }
- },
- bcStatus: function(fields) {
- console.log("action bcStatus:"+fields);
- if (!fields) return;
- var val = fields[3].value;
- if (val=='03 2c 00 00') { // heat
- heat = true;
- ehpFlow.addType("hot");
- hwcFlow.removeType("hot");
- hcFlow.addType("hot");
- hwcReturn.removeType("cold");
- hcReturn.addType("cold");
- } else {
- water = false;
- hcFlow.removeType("hot");
- hcReturn.removeType("cold");
- if (!water) {
- ehpFlow.removeType("hot");
+ hwcReturn.addType("cold");
+ } else {
+ water = false;
hwcFlow.removeType("hot");
hwcReturn.removeType("cold");
+ if (!heat) {
+ ehpFlow.removeType("hot");
+ hcFlow.removeType("hot");
+ hcReturn.removeType("cold");
+ }
+ }
+ },
+ bcStatus: function(fields) {
+ console.log("action bcStatus:"+fields);
+ if (!fields) return;
+ var val = fields[3].value;
+ if (val=='03 2c 00 00') { // heat
+ heat = true;
+ ehpFlow.addType("hot");
+ hwcFlow.removeType("hot");
+ hcFlow.addType("hot");
+ hwcReturn.removeType("cold");
+ hcReturn.addType("cold");
+ } else {
+ water = false;
+ hcFlow.removeType("hot");
+ hcReturn.removeType("cold");
+ if (!water) {
+ ehpFlow.removeType("hot");
+ hwcFlow.removeType("hot");
+ hwcReturn.removeType("cold");
+ }
}
}
+ };
+ var buildText = function(parts, fields) {
+ var ret = '';
+ if (parts) {
+ parts = parts.split(' ');
+ for (var i=0; i0) ret += ', ';
+ if (isNaN(parts[i])) {
+ if (parts[i]=='\\n')
+ ret += " ";
+ else
+ ret += parts[i];
+ } else if (fields && fields.hasOwnProperty(parts[i])){
+ var field = fields[parts[i]];
+ ret += field.hasOwnProperty('value')&&field.value!=null?field.value:'?';
+ if (field.unit) {
+ ret += ' '+field.unit;
+ }
+ } else {
+ ret += '?';
+ }
+ }
+ } else if (fields) {
+ for (var i=0; i0) ret += ', ';
+ var field = fields[i];
+ ret += field.hasOwnProperty('value')&&field.value!=null?field.value:'?';
+ if (field && field.unit) {
+ ret += ' '+field.unit;
+ }
+ }
+ } else {
+ ret += '?';
+ }
+ return ret;
}
- };
- var running = false, firstrun = true;
- var since = 0;
- var needUris = new Array();
- var startNeeded = function() {
- for (var i=0; i=needConnections.length) {
+ first = false;
+ i = -1;
+ }
continue;
}
- var message = circuit[mname];
- var lastup = message.lastup;
- if (lastup>since) {
- since = lastup;
- }
- var fields = message.fields;
- var key = cname+mname;
- var needed = false;
- if (switchActions.hasOwnProperty(key)) {
- switchActions[key](fields);
- needed = true;
- }
- var elems = $$('div[data-id="'+key+'"]');
- if (elems.length>0) {
- needed = true;
- } else console.log(key+':'+fields);
- if (needed && firstrun) {
- needUris[needUris.length] = cname+'/'+mname;
- }
- if (!fields) {
- continue;
- }
- each(elems, function(elem) {
- var ret = '';
- var parts = elem.getAttribute('data-parts');
- if (parts) {
- parts = parts.split(' ');
- for (var i=0; i0) ret += ', ';
- if (isNaN(parts[i])) {
- if (parts[i]=='\\n')
- ret += " ";
- else
- ret += parts[i];
- } else {
- var field = fields[parts[i]];
- if (field) {
- ret += field.value;
- if (field.unit) {
- ret += ' '+field.unit;
- }
- } else console.log("undefined field "+parts[i]+" in "+cname+" "+mname);
- }
- }
- } else {
- for (var i=0; i0) ret += ', ';
- var field = fields[i];
- ret += field.value;
- if (field.unit) {
- ret += ' '+field.unit;
- }
+ var avail = new Array();
+ var best = 99;
+ endpoints.each(function(endpoint) {
+ if (endpoint.getParameter('name')==data[2] && !endpoint.isFull()) {
+ var prio = endpoint.getParameter('priority');
+ if (avail.length==0 || (isNaN(prio)?prio:99)0 ? avail[0] : null;
+ } else {
+ dst = data[1]+data[2];
+ }
+ needConnections.splice(i--, 1);
+ if (!dst) continue;
+ if (instance.getEndpoint(src).isTarget) {
+ src = dst;
+ dst = data[0];
+ }
+ var type = 'off';//TODO dst.indexOf("Flow")>=0?'hot':'cold';
+ var conn = instance.connect({uuids: [src, dst], editable: true, type: type});
+ if (conn && data.length>4 && data[3]) { // add label
+ connectionItems.push({conn: conn, data: data});
+ var cmessages = allMessages[data[3]];
+ var message = cmessages[data[4]];
+ var over = conn.getOverlay("label");
+ over.setLabel(buildText(data.length>5?data[5]:null, message.fields));
+ var key = data[3]+'/'+data[4];
+ if (!needUris[key]) {
+ needUris.push(key);
+ }
}
}
- running = false;
- if (firstrun) {
- startNeeded();
+ // request all shown values and enable automatic polling
+ for (var i=0; isince) {
+ since = lastup;
+ }
+ var fields = message.fields;
+ var key = cname+'/'+mname;
+ var needed = false;
+ /*if (switchActions.hasOwnProperty(key)) {
+ switchActions[key](fields);
+ needed = true;
+ }*/
+ var elems = $$('div[data-id="'+key+'"]');
+ if (elems.length>0) {
+ needed = true;
+ } else console.log(key+':'+fields);
+ if (!fields) {
+ continue;
+ }
+ each(elems, function(elem) {
+ elem.innerHTML = buildText(elem.getAttribute('data-parts'), fields);
+ });
+ }
+ }
+ running = false;
+ },
+ onFailure: function() {
+ console.log("failed");
+ running = false;
+ },
+ onException: function(trans,e) {
+ console.log(e);
+ running = false;
+ }
+ });
+ };
+ startRequest();
+ new PeriodicalExecuter(startRequest, 15);
+ });
});
diff --git a/contrib/html/items/broadcast.json b/contrib/html/items/broadcast.json
new file mode 100644
index 00000000..b49da740
--- /dev/null
+++ b/contrib/html/items/broadcast.json
@@ -0,0 +1,10 @@
+ {
+ "title": "DCF",
+ "bounds": [10,0,54,48],
+ "image": "dcf.svg",
+ "image-pos": [10, 10],
+ "items": [
+ {"name": "datetime", "parts": "0", "top": 0, "left": 1},
+ {"name": "datetime", "parts": "2 1", "top": 0.45, "left": 1}
+ ]
+ }
diff --git a/contrib/html/items/ehp.json b/contrib/html/items/ehp.json
new file mode 100644
index 00000000..8c5f3c4e
--- /dev/null
+++ b/contrib/html/items/ehp.json
@@ -0,0 +1,125 @@
+{
+ "title": "Wärmepumpe",
+ "bounds": [140,172,144,286],
+ "image": "ehp.svg",
+ "sub": [
+ {
+ "name": "source",
+ "title": "Quelle",
+ "bounds": [-130,108,80,100],
+ "endpoints": [
+ {"name": "Flow", "anchor": [0.25, 0, 0, -1], "label": "Source", "connectWith": ["ehp", "SourceInput", "ehp", "SourceTempInput", "0"]},
+ {"name": "Return", "anchor": [0.75, 0, 0, -1], "target": true, "label": "Source", "connectWith": ["ehp", "SourceOutput", "ehp", "SourceTempOutput", "0"]}
+ ]
+ },
+ {
+ "name": "valve",
+ "condition": [["ehp", "HydraulicScheme", 4, "ehp", "HydraulicScheme", 3]],
+ "title": "Valve",
+ "bounds": [200,16,25,31],
+ "image": "valve.svg",
+ "endpoints": [
+ {"name": "Flow", "anchor": "Top", "target": true, "connectWith": ["ehp", "HcFlow", "ehp", "FlowTemp", "0"]},
+ {"name": "HwcFlow", "anchor": "Right", "connectWith": ["storage", "HwcInput"], "updates": [
+ {"type": ["hot", "off"], "condition": [["ehp", "Hc1Pump", "on"], ["ehp", "HwcHcValve", "on"]]}
+ ]},
+ {"name": "HcFlow", "anchor": "Left", "connectWith": ["storage", "HcInput", "ehp", "HcFlowTemp", "0"], "updates": [
+ {"type": ["cold", "off"], "condition": [["ehp", "Hc1Pump", "on"], ["ehp", "HwcHcValve", "off"]]}
+ ]}
+ ],
+ "items": [
+ {"circuit": "ehp", "name": "HwcHcValve", "topc": 0.5, "leftc": 0.5}
+ ]
+ },
+ {
+ "name": "storage",
+ "condition": [["ehp", "HydraulicScheme", 4]],
+ "title": "Speicher",
+ "bounds": [390,-48,134,334],
+ "image": "storage.svg",
+ "endpoints": [
+ {"name": "HwcFlow", "anchor": [0, 0.06, -1, 0]},
+ {"name": "HwcReturn", "anchor": [1, 0.06, 1, 0], "target": true, "distance": [0,0,0.8]},
+ {"name": "HwcInput", "anchor": [0, 0.24, -1, 0], "target": true},
+ {"name": "HwcOutput", "anchor": [0, 0.43, -1, 0]},
+ {"name": "HcFlow", "anchor": [1, 0.47, 1, 0]},
+ {"name": "HcInput", "anchor": [0, 0.53, -1, 0], "target": true},
+ {"name": "HcReturn", "anchor": [1, 0.62, 1, 0], "target": true, "distance": [0,0,0.7]},
+ {"name": "HcOutput", "anchor": [0, 0.67, -1, 0]}
+ ],
+ "items": [
+ {"circuit": "ehp", "name": "HwcTemp", "parts": "0", "topc": 0.12, "left": 0.04},
+ {"circuit": "ehp", "name": "StorageTempTop", "parts": "0", "topc": 0.48, "left": 0.04},
+ {"circuit": "ehp", "name": "StorageTempBottom", "parts": "0", "topc": 0.62, "left": 0.04}
+ ]
+ },
+ {
+ "name": "storage",
+ "condition": [["ehp", "HydraulicScheme", 3]],
+ "title": "Wasserspeicher",
+ "bounds": [390,47,134,239],
+ "image": "buffer.svg",
+ "endpoints": [
+ {"name": "HwcFlow", "anchor": [0, 0.06, -1, 0]},
+ {"name": "HwcReturn", "anchor": [1, 0.06, 1, 0], "target": true, "distance": [0,0,0.8]},
+ {"name": "HwcInput", "anchor": [0, 0.15, -1, 0], "target": true},
+ {"name": "HwcOutput", "anchor": [0, 0.85, -1, 0]}
+ ],
+ "items": [
+ {"circuit": "ehp", "name": "HwcTemp", "parts": "0", "topc": 0.12, "left": 0.04}
+ ]
+ },
+ {
+ "name": "storage",
+ "condition": [["ehp", "HydraulicScheme", 2]],
+ "title": "Pufferspeicher",
+ "bounds": [390,47,134,239],
+ "image": "buffer.svg",
+ "endpoints": [
+ {"name": "HcFlow", "anchor": [1, 0.15, 1, 0]},
+ {"name": "HcInput", "anchor": [0, 0.15, -1, 0], "target": true, "connectWith": ["ehp", "HcFlow", "ehp", "FlowTemp", "0"]},
+ {"name": "HcReturn", "anchor": [1, 0.85, 1, 0], "target": true, "distance": [0,0,0.7]},
+ {"name": "HcOutput", "anchor": [0, 0.85, -1, 0]}
+ ],
+ "items": [
+ {"circuit": "ehp", "name": "StorageTempTop", "parts": "0", "topc": 0.15, "left": 0.04},
+ {"circuit": "ehp", "name": "StorageTempBottom", "parts": "0", "topc": 0.85, "left": 0.04}
+ ]
+ }
+ ],
+ "endpoints": [
+ {"name": "SourceOutput", "anchor": [0.12, 0, 0, -1], "label": "Source", "updates": [
+ {"type": ["cold", "off"], "condition": [["ehp", "Source", "on"]]}
+ ]},
+ {"name": "SourceInput", "anchor": [0.22, 0, 0, -1], "target": true, "label": "Source", "distance": [0,60], "updates": [
+ {"type": ["hot", "off"], "condition": [["ehp", "Source", "on"]]}
+ ]},
+ {"name": "HwcReturn", "anchor": [0.53, 0, 0, -1], "target": true, "distance": [0,80,0.3], "connectWith": ["storage", "HwcOutput"], "updates": [
+ {"type": ["hot", "off"], "condition": [["ehp", "Hc1Pump", "on"], ["ehp", "HwcHcValve", "on"]]}
+ ]},
+ {"name": "HcReturn", "anchor": [0.78, 0, 0, -1], "target": true, "distance": [0,60,0.42], "connectWith": ["storage", "HcOutput", "ehp", "HcReturnTemp", "0"], "updates": [
+ {"type": ["cold", "off"], "condition": [["ehp", "Hc1Pump", "on"], ["ehp", "HwcHcValve", "off"]]}
+ ]},
+ {"name": "HcFlow", "anchor": [0.88, 0, 0, -1], "priority": 1, "updates": [
+ {"type": ["hot", "off"], "condition": [["ehp", "Hc1Pump", "on"]]}
+ ]}
+ ],
+ "items": [
+ {"name": "SourcePress", "parts": "0", "topc": 0.2, "left": 0.01},
+ {"name": "Source", "topc": 0.53, "leftc": 0.12},
+ {"name": "HcPress", "parts": "0", "topc": 0.2, "left": 0.5},
+ {"name": "HwcHcValve", "topc": 0.4, "leftc": 0.65},
+ {"name": "Hc1Pump", "topc": 0.53, "leftc": 0.665},
+ {"name": "Backup", "topc": 0.54, "leftc": 0.9},
+ {"name": "TempOutput", "parts": "0", "left": 0.2, "topc": 0.68},
+ {"name": "CompPressHigh", "parts": "0", "left": 0.6, "topc": 0.68},
+ {"name": "ActualEnvironmentPower", "parts": "0", "leftc": 0.12, "topc": 0.81},
+ {"name": "Comp", "leftc": 0.5, "topc": 0.81},
+ {"name": "HeatPumpStatus", "left": 1, "topc": 0.81},
+ {"name": "TempInput", "parts": "0", "left": 0.2, "topc": 0.94},
+ {"name": "CondensorTemp", "parts": "0", "left": 0.65, "topc": 0.81},
+ {"name": "CompPressLow", "parts": "0", "left": 0.6, "topc": 0.94},
+ {"name": "YieldEnvironmentEnergy", "parts": "0", "left": 0, "top": 1},
+ {"name": "PowerCut", "parts": "cut: 0", "left": 0.5, "top": 1}
+ ]
+}
diff --git a/contrib/html/items/hwc.json b/contrib/html/items/hwc.json
new file mode 100644
index 00000000..e3fed370
--- /dev/null
+++ b/contrib/html/items/hwc.json
@@ -0,0 +1,14 @@
+ {
+ "title": "Warmwasser",
+ "bounds": [510,40,174,52],
+ "image": "hwc.svg",
+ "endpoints": [
+ {"name": "Flow", "anchor": [0, 0.82, -1, 0], "target": true, "distance": [40,0,0.5], "connectWith": [null, "HwcFlow"]},
+ {"name": "Return", "anchor": [1, 0.82, 1, 0], "connectWith": [null, "HwcReturn"]}
+ ],
+ "items": [
+ {"name": "OperatingMode", "topc": 0.2, "left": 0.6},
+ {"circuit": "ehp", "name": "CirPump", "topc": 0.8, "leftc": 0.85},
+ {"circuit": "cp", "name": "Mode", "parts": "1 0", "top": 1, "left": 0.6}
+ ]
+ }
diff --git a/contrib/html/items/mc.json b/contrib/html/items/mc.json
new file mode 100644
index 00000000..d72d151c
--- /dev/null
+++ b/contrib/html/items/mc.json
@@ -0,0 +1,19 @@
+ {
+ "title": "Mischer",
+ "bounds": [820,120,116,212],
+ "image": "mc.svg",
+ "endpoints": [
+ {"name":"Flow", "anchor": [0, 0.82, -1, 0], "target": true, "distance": [0,0,0.7], "connectWith": [null, "HcFlow"]},
+ {"name":"Return", "anchor": [0, 0.96, -1, 0], "connectWith": [null, "HcReturn"]},
+ {"name":"HcFlow", "anchor": [1, 0.82, 1, 0], "target": true},
+ {"name":"HcReturn", "anchor": [1, 0.96, 1, 0]}
+ ],
+ "items": [
+ {"name": "Status", "parts": "2", "top": 0.04, "left": 0.04},
+ {"circuit": "uih", "name": "HcName2", "top": 0.25, "leftc": 0.5},
+ {"name": "Mode", "parts": "1 0", "topc": 0.4, "leftc": 0.5},
+ {"circuit": "ehp", "name": "Hc2Pump", "topc": 0.56, "leftc": 0.22},
+ {"circuit": "ehp", "name": "Mixer1DutyCycle", "topc": 0.73, "leftc": 0.24},
+ {"name": "Status", "parts": "1 0", "topc": 0.9, "leftc": 0.4}
+ ]
+ }
diff --git a/contrib/html/items/mc4.json b/contrib/html/items/mc4.json
new file mode 100644
index 00000000..50bd00ac
--- /dev/null
+++ b/contrib/html/items/mc4.json
@@ -0,0 +1,19 @@
+{
+ "title": "Mischer 4",
+ "bounds": [980,120,116,212],
+ "image": "mc.svg",
+ "endpoints": [
+ {"name":"Flow", "anchor": [0, 0.82, -1, 0], "target": true, "distance": [0,0,0.7], "connectWith": [null, "HcFlow"]},
+ {"name":"Return", "anchor": [0, 0.96, -1, 0], "connectWith": [null, "HcReturn"]},
+ {"name":"HcFlow", "anchor": [1, 0.82, 1, 0], "target": true},
+ {"name":"HcReturn", "anchor": [1, 0.96, 1, 0]}
+ ],
+ "items": [
+ {"name": "Status", "parts": "2", "top": 0.04, "left": 0.04},
+ {"circuit": "uih", "name": "HcName4", "top": 0.25, "leftc": 0.5},
+ {"name": "Mode", "parts": "1 0", "topc": 0.4, "leftc": 0.5},
+ {"name": "HcPumpPort", "topc": 0.56, "leftc": 0.22},
+ {"name": "MixerDutyCycle", "topc": 0.73, "leftc": 0.24},
+ {"name": "Status", "parts": "1 0", "topc": 0.9, "leftc": 0.4}
+ ]
+}
diff --git a/contrib/html/items/rcc.json b/contrib/html/items/rcc.json
new file mode 100644
index 00000000..b6c69ca8
--- /dev/null
+++ b/contrib/html/items/rcc.json
@@ -0,0 +1,10 @@
+{
+ "title": "Regler",
+ "bounds": [851,30,54,48],
+ "image": "rc.svg",
+ "image-pos": [10,0],
+ "items": [
+ {"circuit": "uih", "name": "HcName2", "top": 0.1, "leftc": 0.5},
+ {"name": "RoomTemp", "parts": "0", "top": 1, "left": 0}
+ ]
+}
diff --git a/contrib/html/items/rcc4.json b/contrib/html/items/rcc4.json
new file mode 100644
index 00000000..b4df05ea
--- /dev/null
+++ b/contrib/html/items/rcc4.json
@@ -0,0 +1,10 @@
+{
+ "title": "Regler 4",
+ "bounds": [1011,30,54,48],
+ "image": "rc.svg",
+ "image-pos": [10,0],
+ "items": [
+ {"circuit": "uih", "name": "HcName4", "top": 0.1, "leftc": 0.5},
+ {"name": "RoomTemp", "parts": "0", "top": 1, "left": 0}
+ ]
+}