Zentrales "Custum Javascript" für Webfront

Habe - Wetter war ja schlecht - eine Temperatursteuerung im „Nest“ Design nachzubauen versucht. Mit HTML-BOX, Javascript, SVG und Webhook passt das prima (siehe Bild unten - Ist- und Soll-Temperatur werden angezeigt und bei Mausklick wird die Solltemperatur über den Hook entsprechend angepasst).

Da das ganze Java-Zeuch jetzt aber in der HTML Box steckt, würde ich bei 6 dieser Elemente auf einer Seite auch 6x das Script laden. Meine Idee war eine entsprechende .js Datei in das Webfront mit einzubinden, in der alle Funkionen stecken. Hatte da auf eine einfache Erweiterung der index.html gehofft (Zusätzliche <script> Zeile) - geht aber nicht.

Irgendwelche Vorschläge, wo ich JavaScript Funktionen laden lassen kann, die ich in unterschiedlichen HTML Boxen nutze?

Ich hatte mal angefangen ein Modul Webbox
GitHub - Wolbolar/IPSymconWebbox: PHP Modul für IP-Symcon 4.x zum einfachen Visualisieren von Elementen in einem Webseitenelement
Das habe ich erweitert ist aber noch nicht öffentlich. In der Art könnte man das machen, Du hast dann also eine übergeordnete Instanz mit dem Webhook, in der eigentlichen Instanz stellst Du ein wie das Aussehen sein soll, Farbe, Größe usw. werden in der Instanz eingestellt. Das JavaScript wird dann mit der Installation des Moduls mitgeladen und ist dann über die Instanz verfügbar. Wenn Du willst können wir Deine Vorstellungen einfach da mit einbauen dann wäre alles in einem Modul.

Du könntest die JS Datei auch innerhalb eines eigenen Skins ablegen. Evtl. änderst du ja bereits was am Style und könntest dort dann direkt die JS Datei einfügen.

paresy

Danke, werde beides mal testen. Beim Skin hatte ich schon geschaut, aber das Thema Javascript noch nicht gefunden. Dann werde ich jetzt mal genauer suchen :slight_smile:

js Datei abzulegen sehe ich ja noch. Aber in der Skin Doku steht nichts zu der Frage, wie die die js Datei lade (bringt ja nix, wenn ich den Command in der HTML Box unterbringe, dann lade ich ja doch wieder mehrfach.

Das mehrfache Laden ist in dem Sinne dann kein Problem, da der Browser die Datei cached und somit aus dem Cache lädt.

paresy

Habe mich für den Ansatz von paresy entschieden (war irgendwie einfacher :-).

Spannend ist die Nutzung auf dem Handy - In Chrome als Webseite klappt es - in der IP-Symcon App nicht.

In der App sieht man statt der Grafik nur einen schwarzen Kreis. Spannend ist aber, das man in die Grafik tippen kann und sich die Zieltemperatur verändert???

Hallo,

ich finde den Ansatz sehr gelungen.

Wärst Du bereit, Deinen Code zu teilen?

Gruß
Dominic

Wichtig sind die 4 IPS Objekte:

$idGauge = HTML Box für die Anzeige
$valTempIs = aktuelle Temperatur
$valTempDs = Zieltemperatur
$idCTL = Homematic spezifisch (Setzen der Zieltemperatur ist auf einem anderen Objekt als das Auslesen)

Dann braucht es noch einen geeigneten WebHook und eine Erweiterung im CSS Desk genutzten Skins . Als Ereignisse hängen an dem Skript die Änderungen der Objekte für Ist- und Soll-Temperatur (s.u)

PHP Script ===========================================================================
<?
$idGauge = 31437 /[_Develop_test\gaugeTest\GaugeTest]/;
$valTempIs = 44234 /[_Objekte\EG\BM\WZ\HT\THERMALCONTROL_TRANSMIT\ACTUAL_TEMPERATURE]/;
$valTempDs = 16206 /[_Objekte\EG\BM\WZ\HT\THERMALCONTROL_TRANSMIT\SET_TEMPERATURE]/;
$idCTL = 18011 /[_Objekte\EG\BM\WZ\HT\THERMALCONTROL_TRANSMIT]/;
$html = ‚<div id=„g1“><script type=„text/javascript“>
function InitSVG(id,current,target,min,max,size){
var container = document.getElementById(id);
var svg = document.createElementNS(„SVG namespace“, „svg“);
container.parentElement.setAttribute(„class“,„svgContainer“);
svg.setAttribute(„class“,„svgCanvas“);
svg.setAttribute(„height“, (size * 2) + „px“);
svg.setAttribute(„width“, (size * 2) + „px“);
svg.addEventListener(„click“, function(e) {
var rect = e.target.getBoundingClientRect();
var x = e.offsetX-size;
var y = e.offsetY-size;
var deg = Math.atan2(y, x) * (180 / Math.PI); // In radians
if (deg < 120) {deg += 360 };
deg = Math.round((deg - 120)/300 * (max-min)+min,1);
if (deg >= min && deg <= max) {
console.log(deg);
var xmlHttp = new XMLHttpRequest();
theUrl = "http://192.168.245.200:3777/hook/SetTemp?ID=‘ . $idCTL . '&Value=" + deg;
xmlHttp.open( „GET“, theUrl, false ); // false for synchronous request
xmlHttp.send( null );

	 }
});
Gauge(svg,current,target,min,max,size);
container.appendChild(svg);

}

function arcLine(radius,lineSize,arc,innerAdd){
var radiusI = radius-innerAdd-lineSize/2;
var radiusO = radius+lineSize/2;
var gradTobog = 0.0174527777777778;
var curX = radiusIMath.cos(gradTobogarc);
var curY = radiusIMath.sin(gradTobogarc);
var nxtX = radiusOMath.cos(gradTobogarc)-curX;
var nxtY = radiusOMath.sin(gradTobogarc)-curY;
var sPath = " m " + curX + „,“ + curY;
sPath += " l " + nxtX + „,“ + nxtY;
return sPath;
}

function Gauge(mySVG,current,target,min,max,size){

var currentValue = current;
var targetValue = target;

var nsTyp = "http://www.w3.org/2000/svg";
var centerX = size;
var centerY = size;
var radius = size *.75;
var lineSize = size * .15;
var innerAdd = size *.05;
var valMin = min;
var valMax = max;
var valStep =.2;
var arcStart = 120;
var arcEnd = arcStart + 300;

var radiusI = radius-(lineSize/2);
var valStepCount = (valMax-valMin)/valStep;
var arcStep = (arcEnd-arcStart)/valStepCount;

var sPathCenter = " M " + centerX + "," + centerY

var valStart = targetValue;
var valEnd = currentValue;
var dspColor = "svgGaugeBG_red";
if (targetValue &gt; currentValue) {
    valStart = currentValue;
    valEnd = targetValue;
    dspColor = "svgGaugeBG_blue";
}
if (targetValue == currentValue) {
    dspColor = "svgGaugeBG_black";
}

// Background
var radiusO = radius + lineSize/2;
var sPath=sPathCenter + " m " + -radiusO + ",0";
sPath += " a " + radiusO + "," + radiusO + " 0 1,0 " + (2*radiusO) + ",0"
sPath += " a " + radiusO + "," + radiusO + " 0 1,0 " + (-2*radiusO) + ",0"
var gaugeBg = document.createElementNS(nsTyp, "path");
gaugeBg.setAttribute("d", sPath);
gaugeBg.setAttribute( "class", dspColor);
mySVG.appendChild(gaugeBg);

// Backgroud Bars
var curArc = arcStart;
var sPath = "";
for (var curVal = valMin; curVal&lt;= valMax; curVal=curVal+valStep) {
    sPath += sPathCenter + arcLine(radiusI,lineSize,curArc,0);
    curArc += arcStep;
}
var gaugeBgBars = document.createElementNS(nsTyp, "path");
gaugeBgBars.setAttribute("d", sPath);
gaugeBgBars.setAttribute( "class", "svgGaugeBar");
mySVG.appendChild(gaugeBgBars);

var curArc = arcStart+arcStep*(valStart-valMin)/valStep;
var sPath = "";
// Change Temperatur Bars
for (var curVal = valStart; curVal&lt;= valEnd; curVal=curVal+valStep) {
    sPath += sPathCenter + arcLine(radiusI,lineSize,curArc,0);
    curArc += arcStep;
}
var gaugeDiffBars = document.createElementNS(nsTyp, "path");
gaugeDiffBars.setAttribute("d", sPath);
gaugeDiffBars.setAttribute( "class", "svgGaugeBarDiff");
mySVG.appendChild(gaugeDiffBars);

if (targetValue != currentValue) {
    var gaugeStartBars = document.createElementNS(nsTyp, "path");
    var curArc = arcStart+arcStep*(currentValue-valMin)/valStep;
    sPath = sPathCenter + arcLine(radiusI,lineSize,curArc,0);
    gaugeStartBars.setAttribute("d", sPath);
    gaugeStartBars.setAttribute( "class", "svgGaugeBarCurrent");
    mySVG.appendChild(gaugeStartBars);

    if (targetValue&lt;currentValue){
        var curArc = arcStart+arcStep*(targetValue-.75-valMin)/valStep;
    } else {
        var curArc = arcStart+arcStep*(targetValue+.75-valMin)/valStep;
    }
    var gaugeCurrent = document.createElementNS(nsTyp, "text");
    var gradTobog = 0.0174527777777778;
    var curX = (radius-lineSize/2)*Math.cos(gradTobog*curArc);
    var curY = (radius-lineSize/2)*Math.sin(gradTobog*curArc);        
    gaugeCurrent.setAttribute("x", centerX+curX);
    gaugeCurrent.setAttribute("y", centerY+curY);
    gaugeCurrent.style.fontSize = "" + lineSize*.8+"px";
    gaugeCurrent.innerHTML=targetValue;
    gaugeCurrent.setAttribute( "class", "svgGaugeMainText");
    mySVG.appendChild(gaugeCurrent);
        
}
var gaugeEndBars = document.createElementNS(nsTyp, "path");
var curArc = arcStart+arcStep*(targetValue-valMin)/valStep;
sPath = sPathCenter + arcLine(radiusI,lineSize,curArc,innerAdd);
gaugeEndBars.setAttribute("d", sPath);
gaugeEndBars.setAttribute( "class", "svgGaugeBarTarget");
mySVG.appendChild(gaugeEndBars);

var gaugeTarget = document.createElementNS(nsTyp, "text");
gaugeTarget.setAttribute("x", centerX);
gaugeTarget.setAttribute("y", centerY);
gaugeTarget.style.fontSize = "" + radiusI*.8+"px";
gaugeTarget.innerHTML=currentValue;
gaugeTarget.setAttribute( "class", "svgGaugeMainText");
mySVG.appendChild(gaugeTarget);

}
InitSVG(„g1“,’ .
sprintf("%.1f", GetValue($valTempIs)) .
‚,‘ .
sprintf("%.1f", GetValue($valTempDs)) .
‚,6,30,200);
</script></div>‘;
$res = SetValueString($idGauge, $html);
?>

CSS- Erweiterung =========================================
.svgContainer {
position: relative;
height: 0;
width: 100%;
padding: 0;
padding-bottom: 100%;
/* override this inline for aspect ratio other than square */
}
.svgCanvas {
position: absolute;
height: 100%;
width: 100%;
left: 0;
top: 0;
background-color: black;
}
.svgGaugeBar {
stroke: rgb(168, 168, 168);
stroke-width: 1px;
}

.svgGaugeBarCurrent {
stroke: white;
stroke-width: 3px;
}

.svgGaugeBarDiff {
stroke: white;
stroke-width: 1px;
}

.svgGaugeBarTarget {
stroke: white;
stroke-width: 3px;
}

.svgGaugeShadow{
fill: rgb(63, 63, 63);
}

.svgGaugeBG_red {
fill: rgb(255, 128, 0);
}

.svgGaugeBG_blue {
fill: mediumblue;
}

.svgGaugeBG_black {
fill: black;
}

.svgGaugeMainText {
stroke: white;
fill: beige;
text-anchor: middle;
dominant-baseline: central;
font: 1em sans-serif;
}

PHP im WebHook ====================================
?
$object = $_GET[‚ID‘];
$value = $_GET[‚Value‘];
$res = HM_WriteValueFloat($object , „SET_TEMPERATURE“, $value);

?>