snowdd1 / homebridge-knx-de

German Issue/Discussion forum for homebridge-knx
https://github.com/snowdd1/homebridge-knx
20 stars 4 forks source link

Musik Steuerung #27

Closed MrWichtig closed 7 years ago

MrWichtig commented 7 years ago

Hi

ist es möglich Musik mittels homebridge nun auch zu steuern?

Musik EIN/AUS klappt ja bereits......würde aber auch gerne Lautstärke steuern wollen.

habe Squeezeboxen im Einsatz und die würden mittels "DPT1" Lauter/Leiser oder in "%"...Absolute Lautstärke steuern lassen.

evtl. ist das mit den sogenannten Handlern möglich?

@snowdd1 wird wahrscheinlich in die Rubrik Frage fallen.... :-)....bitte verschieben demnach.....thx

snowdd1 commented 7 years ago

Hi auch,
Du kannst theoretisch einfach ein Characteristic Volume (in Prozent) zu dem Service hinzufügen. Allerdings wird wahrscheinlich kaum eine App (außer Elgato Eve) dir das auch anzeigen. Und Siri wird auch nicht drauf hören.

Ich habe gerdae gesehen, dass es einen neuen Service Speaker in iOS10 gibt, der hat Standardcharacteristics Mute (könnte auch an/aus sein! Ist Bool/DPT1) und eben Volume, vielleicht erkennt das ja eine App besser als wenn Du einen Switch oder eine Steckdose als Basis nimmst.

Gutes Gelingen! Berichte mal ob das geklappt hat!

MrWichtig commented 7 years ago

wäre das so richtig in der knx_config.json?

        {
            "DeviceName": "Musik Testraum",
            "Services": [
                {
                    "ServiceType": "Speaker",
                    "ServiceName": "Musik Testraum",
                    "Characteristics": [
                        {
                            "Type": "On",
                            "Set": [
                                "20/1/1"
                            ],
                            "Volume": [
                                "20/1/11"
                            ]
                        }
                    ],
                    "subtype": ""
                }
            ],
            "UUID": ""
        },
snowdd1 commented 7 years ago

Eher so:

        {
            "DeviceName": "Musik Testraum",
            "Services": [
                {
                    "ServiceType": "Speaker",
                    "ServiceName": "Musik Testraum",
                    "Characteristics": [
                        {
                            "Type": "Mute",
                            "Set": [
                                "20/1/1"
                            ]
                         },
                         {
                            "Type": "Volume",
                            "Set": [
                                "20/1/11"
                            ]
                        }
                    ]
                }
            ]
        },
MrWichtig commented 7 years ago

Danke!

habe es ausprobiert (in mehreren Sprachvarianten :-) )...aber ausser Rückmeldungen "Tut mir leid...ich habe das nicht verstanden.Kannst............" habe ich nicht bekommen.

das wird dann glaube ich noch eine weile dauern was Musik generell betrifft.....

ABER...in Eve wird zumindest auf Grund des Service "Speaker" ein richtiges Logo angezeigt ;-)

ChrisSthler commented 7 years ago

kannst du es den über die Home APP oder EVE Bedienen oder geht es nur mit Siri nicht

MrWichtig commented 7 years ago

JEIN.....

EVE:

bei Schrittweise: hier verziehe ich den Balken nur ganz gering z:b.: von 0% auf 5% und der Radio dreht sich auf 100% obwohl ich bei mir definiert habe im KNX dass die Schrittgröße 2 beträgt.

bei Lautstärke Dimmen: hier verstelle ich auch nur ganz gering und ich habe fast das selbe Ergebnis wie bei Schrittweise. Mit dem Unterschied, dass es "gedimmt" also 2-3 sek braucht bis die Lautstärke auf 100 ist.

bei Absolut setzen: kann ich zwischen 0% und 100% in EVE verschieben. Die Lautstärke (lt. Squeezebox Anzeige) ist 11maximum....also Lautstärke 0-11 möglich. Auch nicht der "Bringer" :-)

Homekit APP:

ChrisSthler commented 7 years ago

okay klingt ja sehr ernüchternd dann kann ich meinen "Switch" zum ein schalten auch noch lassen... Schade das von Apple (Home App) selbst nicht alles schon "unterstützt" bzw. wenigstens angezeigt wird.

werden mir trotzdem mal einen Speaker im Test raum Anlegen und schauen wie das mit dem Volume Funktionieren könnte. Vielleicht kann man des ja von der KNX Seite Begrenzen das es nur alle Paar Sekunden um 5% oder so hoch geht und dann dementsprechend immer die aktuelle Lautstärke wieder zurück auf die Homebridge schreibt... nur so eine Idee

PS: über welchen DPT setzt du normal die Lautstärke? beim mir ist es dimmen dpt3

snowdd1 commented 7 years ago

@MrWichtig
Wenn die Squeezebox einen Wert 0..11 braucht, passt natürlich ein Wert 0..100 bzw DPT5.001 =0..255 nicht so ganz, dafür müsste man wieder einen kleinen Handler schreiben der das passend umrechnet.

"Schrittweise" geht in HomeKit eigentlich nie, das Konzept gibt es dort gar nicht. Es wird immer ein Zielwert definiert, kein höher, lauter, offener, tiefer, leiser, geschlossener

MrWichtig commented 7 years ago

OK,

ich dachte schon ich kann mich vor dem Thema "Handler" und "Add ins" drücken! :-)

aber so wie es aussieht wird man zukünftig um die homebridge Steuerung verbal "auszureizen" nicht drum herum kommen. Wie schon ein paar mal geschrieben bin ich nicht gerade der Experte was die Programmierung im JSON usw. betrifft. bis vor wenigen Monaten hatte ich nichtmal einen Raspi. Aber mein Eifer hat nicht nachgelassen :-)

so....dann möchte ich einmal probieren lt. Deiner Anleitung hier einen Handler für die Volume zu basteln. wäre toll wenn Du kurz Feedback geben könntest ob ich das im großen so richtig verstanden habe? :-)

Vorab zwei Fragen: 1.) kann man den Handler-Namen frei definieren? z.B.: "Squeezebox" oder ist das wo verankert/vorgegeben?

2.) welche Bausteine aus Deiner Example AddIns braucht man denn wirklich? ich habe mir diese angesehen und die ist schon sehr groß um nur einen Jalousie Wert umzusetzen?!

/* Sample module - Simple handler for rolling shutter actuator  
 * This sample shows how additional values can be taken into account.
 * 
 */
'use strict';
/**
 * @type {HandlerPattern}
 */
var HandlerPattern = require('./handlerpattern.js');
var log = require('debug')('GiraJalousieActuator');

/**
 * @class A custom handler for the GIRA 216100 "Jalousie Aktor" (rolling shutter/blinds actuator)
 * @extends HandlerPattern
 */
class GiraJalousieActuator extends HandlerPattern {

    /*******************************************************************************************************************
     * onKNXValueChange is invoked if a Bus value for one of the bound addresses is received
     * 
     */
    onKNXValueChange(field, oldValue, knxValue) {
        // value for HomeKit
        var newValue;
        log('INFO: onKNXValueChange(' + field + ", "+ oldValue + ", "+ knxValue+ ")");
        if (field==="TargetPosition") {
            // TargetPosition is DPT5.001 Percentage (0..255)
            // need to convert to (0..100) first
            // Homekit is using %-open, meaning 0% is closed/down

            newValue = 100 - knxValue*100/255;

            if (newValue>this.myAPI.getValue("CurrentPosition")) {
                // newValue is higher, shutter's moving up
                this.myAPI.setValue("PositionState", 1); //up
            } else if (newValue<this.myAPI.getValue("CurrentPosition")){
                // newValue is higher, shutter's moving down
                this.myAPI.setValue("PositionState", 0); //down
            }
            this.myAPI.setValue("TargetPosition", newValue);
            if (this.timer){
                // avoid resetting Target Position through a timer
                clearTimeout(this.timer);
                this.timer = undefined;
            }
            this.lastCommand = 'target';
        } else if (field==="CurrentPosition") {
            // Current Position is sent by the actuator if the Movement has stopped a new postion is reached

            // CurrentPosition is DPT5.001 Percentage (0..255)
            // need to convert to (0..100) first
            // Homekit is using %-open, meaning 0% is closed/down
            newValue = 100 - knxValue*100/255;

            this.myAPI.setValue("CurrentPosition", newValue); // inform homekit
            this.myAPI.setValue("PositionState", 2); //stopped

            if (this.lastCommand==='move') {
                // return to stopped immediately, and set the Target to Current
                this.myAPI.setValue("TargetPosition", this.myAPI.getValue("CurrentPosition"));
            } else {
                if (!this.timeout) {
                    this.timeout = this.myAPI.getLocalConstant("TimeOutSecs")*1000 || 60000;
                }
                if (this.timer){
                    clearTimeout(this.timer); // start a new one
                }
                this.timer = setTimeout(function() {
                    log('Idle Timer reached! Assume motion stopped and target position was not used, so we set it to current position');
                    this.myAPI.setValue("TargetPosition", this.myAPI.getValue("CurrentPosition"));
                    this.timer = undefined;
                }.bind(this), this.timeout );
            }
        } else if (field==="ShutterMove") {
            // this isn't a characteristic, we need this extra object to catch switch use, too
            // The actuator is lowering the rolling shutters if a 1 is received, and 
            // raises on a 0
            this.lastCommand = 'move';
            switch (knxValue) {
            case 0:
                this.myAPI.setValue("TargetPosition", 100); // top position, so home shows "opening"
                this.myAPI.setValue("PositionState", 0); //up
                break;
            case 1:
                this.myAPI.setValue("TargetPosition", 0); // low position, so home shows "closing"
                this.myAPI.setValue("PositionState", 1); //down
                break;
            } // switch
        } //if
    } // onBusValueChange

    /*******************************************************************************************************************
     * onHKValueChange is invoked if HomeKit is changing characteristic values
     * 
     */
    onHKValueChange(field, oldValue, newValue) {
        // homekit will only send a TargetPosition value, so we do not care about (non-) potential others
        if (field==="TargetPosition") {
            log('INFO: onHKValueChange(' + field + ", "+ oldValue + ", "+ newValue + ")");
            // update the PositionState characteristic:     
            // get the last current Position
            var lastPos = this.myAPI.getValue("CurrentPosition");
            if (newValue>lastPos) {
                // newValue is higher, shutter's moving up
                this.myAPI.setValue("PositionState", 1); //up
            } else if (newValue<lastPos){
                // newValue is higher, shutter's moving down
                this.myAPI.setValue("PositionState", 0); //down
            }
            var knxValue = (255-newValue*255/100);
            log('INFO: onHKValueChange after calc ('  + knxValue+ ")");
            this.myAPI.knxWrite("TargetPosition", knxValue, "DPT5"); // send the new position to the KNX bus
        }

    } // onHKValueChange
} // class  
module.exports= GiraJalousieActuator;
snowdd1 commented 7 years ago

Es gibt eine Anleitung dazu ...
https://github.com/snowdd1/homebridge-knx/blob/master/handler-add-in.md#structure

Im wesentlichen gibt es zwei Methoden in der Klasse, die man "mit Leben füllen" muss. Wieviel da jeweils rein muss, ist abhängig von der gestellten Aufgabe. Ein Mini-Mapper ist z.B. mein Contact-Sensor-Beispiel:

class ContactSensor extends HandlerPattern {

    /*******************************************************************************************************************
     * onKNXValueChange is invoked if a Bus value for one of the bound addresses is received
     * 
     */
    onKNXValueChange(field, oldValue, knxValue) {
        // value for HomeKit
        var newValue;
        log('INFO: onKNXValueChange(' + field + ", "+ oldValue + ", "+ knxValue+ ")");
        if (field==="ContactSensorState") {
            if (this.myAPI.getLocalConstant("Reverse")) {
                newValue = 1-knxValue;
            } else {
                newValue = knxValue;
            }
            this.myAPI.setValue("ContactSensorState", newValue);
        } //if
    } // onBusValueChange

    /*******************************************************************************************************************
     * onHKValueChange is invoked if HomeKit is changing characteristic values
     * 
     */
    onHKValueChange(field, oldValue, newValue) {
        log('STRANGE-THIS-SERVICE-IS-NOT-EXPECTED-TO-BE-WRITEABLE: onHKValueChange(' + field + ", "+ oldValue + ", "+ newValue + ")");
    } // onHKValueChange
} // class  
module.exports= ContactSensor;

In der Anleitung findest Du insbesondere folgende API-Aufrufe, die Du brauchen kannst:

In dem Jalousie-Beispiel ist auch noch ein Timer drin (um nach Ablauf der max. Fahrtzeit sicherzustellen, dass wieder TargetPosition und CurrentPosition übereinstimmen, ansonsten zeigt Home immer öffnend/schließend an), sowie ein nicht in HomeKit vorkommendes Feld "ShutterMove" (Langzeitbetrieb) um der Jalousie über KNX einen Befehl "Fahren" zu geben (i.d.R. langer Tastendruck am Schalter) - der muss für HomeKit in einen Zielprozentwert umgerechnet werden, und beim Anhalten muss der aktuelle Wert als Zielwert gesetzt werden...
Dein Beispiel dürfte ungleich einfacher sein, eher so wie das oben.

Und nennen kannst Du ihn wie Du magst, es sollte der Sinn daraus hervorgehen, und eine (deutsche) Anleitung wäre super, siehe hier, da haben die anderen Autoren auch schon ihre Anleitungen hinterlegt!

snowdd1 commented 7 years ago

Ist das noch akut oder kann das zu?

MrWichtig commented 7 years ago

@snowdd1

...Akut nicht.........offen für mich (aber ich denke auch zukünftig für andere Leute) auf alle Fälle. Aber wie schon gesagt müsste ich hier von Grund auf einmal das checken mit der "add ins" Konfiguration. Hier werde ich mich wohl schon intensiver beschäftigen müssen mit meinem derzeitigen Programming Know How :-) . Sprich es wird noch dauern.

...ABER kann natürlich "closed" werden.

thx Wolfi

MrWichtig commented 7 years ago

@ChrisSthler hast Du das mit der Namensgebung "Musik" schon hinbekommen?....ich hatte ja auch mal kurzfristig das Problem, dass wenn ich sagte "Schalte Musik Wohnen EIN" sich die APP öffnete.

das war wie ich den Wortlaut "Musik" nicht im ServiceName drinnen stehen gehabt habe.

wenn das Wort "Musik XXX" ebenfalls angeführt ist dann wird bei mir auch die Squeezebox gestartet.

siehe Beispiel unten "Musik Testraum"

    {
            "DeviceName": "Musik Testraum",
            "Services": [
                {
                    "ServiceType": "Speaker",
                    "ServiceName": "Musik Testraum",
                    "Characteristics": [
                        {
                            "Type": "On",
                            "Set": [
                                "20/1/1"
                            ],
                            "Volume": [
                                "20/1/11"
                            ]
                        }
                    ],
                    "subtype": ""
                }
            ],
            "UUID": ""
        },

EDIT: Formatierung -- snowdd1

snowdd1 commented 7 years ago

ServiceName ist das, worauf Siri (wenn überhaupt) hört. DeviceName ist nur Deko, ganz wenige Apps zeigen das überhaupt noch an.

ChrisSthler commented 7 years ago

also setzte gerade mein test system neu auf (ohne KnxD).

meine config sieht ja immer so aus.

DeviceName = Raum (wohnen, Küche usw) ServiceName = Musik Licht etc. ServiceType = des (passende) gerät dazu "Speaker" usw.

aber egal ob ich ServiceType also "Speaker" , "Switch" oder was auch immer mache sobald mein ServiceName Das schlüssel Worte Musik enthält leitet der mich auf die Apple Musik App um getestet habe ich es mit Watch, 2 iPhone und 2 iPads. immer des gleiche Ergebnis... heist mein ServiceName aber (wie bei mir Aktuelle) "Lautsprecher macht er es egal was der Servicetype ist...

PS: die GAs sind natürlich immer die gleichen...