Apple HomeKit (Siri) mit IP-Symcon verbinden

-Neu: Änderungen von Zuständen werden sofort zurückgemeldet. (Freue mich auf Feedback!)
-Neu: Rudimentäre Tests sind nun für alle unterstützten Geräte vorhanden

(Das neue Switch Color Gerät ist noch nicht korrekt funktionsfähig…)

paresy

Ich werd es gleich mal testen, hatte bisher nur die anderen Module im Einsatz und arbeite aktuell mit Homebridge und Diversen Plugins.

Mit deinem Modul diese dinge abzulösen wäre klasse, da ich eh alle Geräte im IPS habe.

Geht das auch unter Windows?

Ja, geht überall. Brauchst aber die aktuelle Beta von der 5.0

paresy

Nach dem Update bekomme ich:

17.05.2018 22:15:18 | 45121 | ERROR   | FlowHandler          | Kann Daten nicht zur Instanz #45121 weiterleiten: <br />
<b>Fatal error</b>:  Uncaught Exception: Missing function notifyCharacteristicOn in Accessory HAPAccessorySwitch in /var/lib/symcon/modules/HomeKit/HomeKitBridge/hap.php:180
Stack trace:
#0 /var/lib/symcon/modules/HomeKit/HomeKitBridge/hap.php(25): HAPService->doExport(101, Object(HAPAccessorySwitch))
#1 /var/lib/symcon/modules/HomeKit/HomeKitBridge/manager.php(68): HAPAccessory->doExport(2)
#2 /var/lib/symcon/modules/HomeKit/HomeKitBridge/session.php(1248): HomeKitManager->getAccessories()
#3 /var/lib/symcon/modules/HomeKit/HomeKitBridge/session.php(229): HomeKitSession->getAccessories(Array)
#4 /var/lib/symcon/modules/HomeKit/HomeKitBridge/module.php(159): HomeKitSession->processData(';\x00b\x9C2\x92B	\x88\xA9i\xE2\xD6\x90\xBB...')
#5 /-(3): HomeKitBridge->ReceiveData('{"DataID":"{7A1...')
#6 {main}
  thrown in <b>/var/lib/symcon/modules/HomeKit/HomeKitBridge/hap.php</b> on line <b>180</b><br />

@traxanos: Ein Fix dafür ist online. Danke!

paresy

Hallo an Alle,

seit dem letzten Homekit Update lassen sich zwar meine Homematic Schalter etc. bedienen aber Switch Variablen funktionieren nicht mehr, Die Variable wird nicht aktualisiert. gestern ging es noch.

Nachtrag: Ich hab den Ordner von gestern zurückgesichert nun geht es wieder.

Schau ich mir an - Danke fürs Feedback :slight_smile:

paresy

Hi musste auch ein revert machen. Es fehlen Dateien. z.B. autoload.php in den helper folder.

Oh das aktuelle Symcon setzt Bionic vorraus :smiley: Nach dem Update auf Bionic inkl Symcon, konnte Homekit mit Git-Submodules aktualisiert werden und nun geht wieder alles.

Ähh… Wie meinst du das? Ich glaub ich stehe auf dem Schlauch…

paresy

Hallo Zusammen,

ich habe mal versucht die Accessorys Window bzw. WindowCovering von KaiS’s Pull Requests anzupassen um es nach dem neusten Update zum laufen zu bringen, komme aber leider nicht weiter.
Im Homebridge Configurator wird mir in der Auswahl „Fenster“ angezeigt und ich kann die Variablen auch hinzufügen, sieht soweit auch alles gut aus nur es erscheint kein Fenster in HomKit :confused:
Hat jemand eine Idee?


<?php

declare(strict_types=1);

class HAPAccessoryWindow extends HAPAccessoryBase
{
    use HelperSetDevice;

    public function __construct($data)
    {
        parent::__construct(
            $data,
            [
                new HAPServiceAccessoryInformation(),
                new HAPServiceWindow()
            ]
        );
    }
	
	public function notifyCharacteristicTargetPosition()
    {
        return [$this->data['TargetPosition']];
    }
	
	public function readCharacteristicTargetPosition()
    {
        return GetValue($this->data['TargetPosition']);
    }
	
	public function notifyCharacteristicCurrentPosition()
    {
        return [$this->data['CurrentPosition']];
    }

    public function readCharacteristicCurrentPosition()
    {
        return GetValue($this->data['CurrentPosition']);
    }

	public function notifyCharacteristicPositionState()
    {
        return [$this->data['PositionState']];
    }
	
	public function readCharacteristicPositionState()
    {
       return GetValue($this->data['PositionState']);
    }
	
	public function writeCharacteristicTargetPosition($value)
    {
        self::setDevice($this->data['TargetPosition'], $value);
    }
	
	public function writeCharacteristicCurrentPosition($value)
    {
        self::setDevice($this->data['CurrentPosition'], $value);
    }

    public function writeCharacteristicPositionState($value)
    {
		self::setDevice($this->data['CurrentPosition'], $value);
    }
}

class HAPAccessoryConfigurationWindow
{
	use HelperSetDevice;
	
	public static function getPosition()
	{
		return 90;
	}
	
	public static function getCaption()
	{
       return 'Window';
	}
		
	public static function getColumns()
	{
		return [
			[
				'label' => 'TargetPosition',
				'name'  => 'TargetPosition',
				'width' => '150px',
				'add'   => 0,
				'edit'  => [
					'type' => 'SelectVariable'
				]
			],
			[
				'label' => 'CurrentPosition',
				'name'  => 'CurrentPosition',
				'width' => '150px',
				'add'   => 0,
				'edit'  => [
					'type' => 'SelectVariable'
				]
			],
			[
				'label' => 'PositionState',
				'name'  => 'PositionState',
				'width' => '150px',
				'add'   => 0,
				'edit'  => [
					'type' => 'SelectVariable'
				]
			]
		];
	}
		
	public static function getStatus($data)
	{
		if (!IPS_VariableExists($data['TargetPosition'])) {
			return 'TargetPosition missing';
		}
		if (!IPS_VariableExists($data['CurrentPosition'])) {
			return 'CurrentPosition missing';
		}
		if (!IPS_VariableExists($data['PositionState'])) {
			return 'PositionState missing';
		}
		$variableTargetPosition = IPS_GetVariable($data['TargetPosition']);
		$variableCurrentPosition = IPS_GetVariable($data['CurrentPosition']);
		$variablePositionState = IPS_GetVariable($data['PositionState']);
		if ($variableTargetPosition['VariableType'] != 1 /* Integer */) {
			return 'TargetPosition: Integer required';
		}
		if ($variableCurrentPosition['VariableType'] != 1 /* Integer */) {
			return 'CurrentPosition: Integer required';
		}
		if ($variablePositionState['VariableType'] != 1 /* Integer */) {
			return 'PositionState: Integer required';
		}
		if ($variableTargetPosition['VariableCustomAction'] != '') {
			$profileAction = $variableTargetPosition['VariableCustomAction'];
		} else {
			$profileAction = $variableTargetPosition['VariableAction'];
		}
		if (!($profileAction > 10000)) {
			return 'TargetDoorState: Action required';
		}
		return 'OK';
	}

	public static function getTranslations()
	{
		return [
			'de' => [
				'Window'    => 'Fenster',
				'VariableID'            => 'VariablenID',
				'Variable missing'      => 'Variable fehlt',
				'Int required'          => 'Int benötigt',
				'Profile required'      => 'Profil benötigt',
				'Unsupported Profile'   => 'Falsches Profil',
				'OK'                    => 'OK'
			]
		];
	}
}
HomeKitManager::registerAccessory('Window');

P.s.: Die Rückmeldung von Zuständen funktioniert bei mir bisher sehr gut! :slight_smile:

Hier mal meine Accessories die bei mir funktionieren:
contactSensor.php


<?php

declare(strict_types=1);

class HAPAccessoryContactSensor extends HAPAccessoryBase
{
    public function __construct($data)
    {
        parent::__construct(
            $data,
            [
                new HAPServiceAccessoryInformation(),
                new HAPServiceContactSensor()
            ]
        );
    }

    public function notifyCharacteristicContactSensorState()
    {
        return [
            $this->data['VariableID']
        ];
    }

    public function readCharacteristicContactSensorState()
    {
        switch (GetValue($this->data['VariableID'])) {
            case 0:
                return HAPCharacteristicContactSensorState::ContactNotDetected;
            case 1:
                return HAPCharacteristicContactSensorState::ContactDetected;
        }
        return HAPCharacteristicContactSensorState::ContactDetected;
    }
}

class HAPAccessoryConfigurationContactSensor
{
    public static function getPosition()
    {
        return 111;
    }

    public static function getCaption()
    {
        return 'Contact Sensor';
    }

    public static function getColumns()
    {
        return [
            [
                'label' => 'VariableID',
                'name'  => 'VariableID',
                'width' => '250px',
                'add'   => 0,
                'edit'  => [
                    'type' => 'SelectVariable'
                ]
            ]
        ];
    }

    public static function getStatus($data)
    {
        if (!IPS_VariableExists($data['VariableID'])) {
            return 'Variable missing';
        }

        $targetVariable = IPS_GetVariable($data['VariableID']);

//        if ($targetVariable['VariableType'] != 1 /* Integer */ && $targetVariable['VariableType'] != 2 /* Float */) {
//            return 'Int/Float required';
//        }

        return 'OK';
    }

    public static function getTranslations()
    {
        return [
            'de' => [
                'Contact Sensor'    => 'Fensterkontakt',
                'VariableID'            => 'VariablenID',
                'Variable missing'      => 'Variable fehlt',
                'Int/Float required'    => 'Int/Float benötigt',
                'OK'                    => 'OK'
            ]
        ];
    }
}

HomeKitManager::registerAccessory('ContactSensor');

securitySystem.php


<?php

declare(strict_types=1);

class HAPAccessorySecuritySystem extends HAPAccessoryBase
{
    use HelperSetDevice;

    public function __construct($data)
    {
        parent::__construct(
            $data,
            [
                new HAPServiceAccessoryInformation(),
                new HAPServiceSecuritySystem()
            ]
        );
    }

    public function notifyCharacteristicSecuritySystemCurrentState()
    {
        return [
            $this->data['VariableID']
        ];
    }

    public function readCharacteristicSecuritySystemCurrentState()
    {
        return GetValue($this->data['VariableID']);
		
    }

    public function notifyCharacteristicSecuritySystemTargetState()
    {
        return [
            $this->data['VariableID']
        ];
    }

    public function readCharacteristicSecuritySystemTargetState()
    {
        return GetValue($this->data['VariableID']);
    }

    public function writeCharacteristicSecuritySystemTargetState($value)
    {
        self::setDevice($this->data['VariableID'], $value);
    }
}

class HAPAccessoryConfigurationSecuritySystem
{
	use HelperSetDevice;
	
    public static function getPosition()
    {
        return 99;
    }

    public static function getCaption()
    {
        return 'Security System';
    }

    public static function getColumns()
    {
        return [
            [
                'label' => 'VariableID',
                'name'  => 'VariableID',
                'width' => '250px',
                'add'   => 0,
                'edit'  => [
                    'type' => 'SelectVariable'
                ]
            ]
        ];
    }

    public static function doMigrate(&$data)
    {
        if (!isset($data['VariableID'])) {
            $data['VariableID'] = $data['SecuritySystemTargetState'];
            unset($data['SecuritySystemCurrentState']);
            unset($data['SecuritySystemTargetState']);
            return true;
        }
        return false;
    }

    public static function getStatus($data)
    {
        if (!IPS_VariableExists($data['VariableID'])) {
            return 'Variable missing';
        }

        $targetVariable = IPS_GetVariable($data['VariableID']);

        if ($targetVariable['VariableType'] != 1 /* Integer */) {
            return 'Int required';
        }


        if ($targetVariable['VariableCustomAction'] != '') {
            $profileAction = $targetVariable['VariableCustomAction'];
        } else {
            $profileAction = $targetVariable['VariableAction'];
        }

        if (!($profileAction > 10000)) {
            return 'Action required';
        }

        return 'OK';
    }

    public static function getTranslations()
    {
        return [
            'de' => [
                'Security System'    => 'Alarmanlage',
                'VariableID'            => 'VariablenID',
                'Variable missing'      => 'Variable fehlt',
                'Int required'          => 'Int benötigt',
                'Profile required'      => 'Profil benötigt',
                'Unsupported Profile'   => 'Falsches Profil',
                'OK'                    => 'OK'
            ]
        ];
    }
}

HomeKitManager::registerAccessory('SecuritySystem');

lockMechanism.php


<?php

declare(strict_types=1);

class HAPAccessoryLockMechanism extends HAPAccessoryBase
{
    use HelperSetDevice;

    public function __construct($data)
    {
        parent::__construct(
            $data,
            [
                new HAPServiceAccessoryInformation(),
                new HAPServiceLockMechanism()
            ]
        );
    }

    public function notifyCharacteristicLockCurrentState()
    {
        return [
            $this->data['VariableID']
        ];
    }

    public function readCharacteristicLockCurrentState()
    {
        return GetValue($this->data['VariableID']);
		
    }

    public function notifyCharacteristicLockTargetState()
    {
        return [
            $this->data['VariableID']
        ];
    }

    public function readCharacteristicLockTargetState()
    {
        return GetValue($this->data['VariableID']);
    }

    public function writeCharacteristicLockTargetState($value)
    {
        self::setDevice($this->data['VariableID'], $value);
    }
}

class HAPAccessoryConfigurationLockMechanism
{
	use HelperSetDevice;
	
    public static function getPosition()
    {
        return 110;
    }

    public static function getCaption()
    {
        return 'Lock Mechanism';
    }

    public static function getColumns()
    {
        return [
            [
                'label' => 'VariableID',
                'name'  => 'VariableID',
                'width' => '250px',
                'add'   => 0,
                'edit'  => [
                    'type' => 'SelectVariable'
                ]
            ]
        ];
    }

    public static function doMigrate(&$data)
    {
        if (!isset($data['VariableID'])) {
            $data['VariableID'] = $data['LockTargetState'];
            unset($data['LockCurrentState']);
            unset($data['LockTargetState']);
            return true;
        }
        return false;
    }

    public static function getStatus($data)
    {
        if (!IPS_VariableExists($data['VariableID'])) {
            return 'Variable missing';
        }

        $targetVariable = IPS_GetVariable($data['VariableID']);

        if ($targetVariable['VariableType'] != 1 /* Integer */) {
            return 'Int required';
        }


        if ($targetVariable['VariableCustomAction'] != '') {
            $profileAction = $targetVariable['VariableCustomAction'];
        } else {
            $profileAction = $targetVariable['VariableAction'];
        }

        if (!($profileAction > 10000)) {
            return 'Action required';
        }

        return 'OK';
    }

    public static function getTranslations()
    {
        return [
            'de' => [
                'Lock Mechanism'    => 'Schloss',
                'VariableID'            => 'VariablenID',
                'Variable missing'      => 'Variable fehlt',
                'Int required'          => 'Int benötigt',
                'Profile required'      => 'Profil benötigt',
                'Unsupported Profile'   => 'Falsches Profil',
                'OK'                    => 'OK'
            ]
        ];
    }
}

HomeKitManager::registerAccessory('LockMechanism');

speaker.php (wird noch nicht offiziell von Apple supported aber mit der Eve App z.B. funktioniert es schon. Ich nutze es um meine Sonos Lautsprecher beim verlassen abzuschalten)


<?php

declare(strict_types=1);

class HAPAccessorySpeaker extends HAPAccessoryBase
{
    use HelperSwitchDevice;

    public function __construct($data)
    {
        parent::__construct(
            $data,
            [
                new HAPServiceAccessoryInformation(),
                new HAPServiceSpeaker()
            ]
        );
    }

    public function notifyCharacteristicMute()
    {
        return [
            $this->data['VariableID']
        ];
    }

    public function readCharacteristicMute()
    {
        switch (GetValue($this->data['VariableID'])) {
            case 0:
                return HAPCharacteristicMute::MuteOn;
            case 1:
                return HAPCharacteristicMute::MuteOff;
        }
        return HAPCharacteristicMute::MuteOff;
    }

    public function writeCharacteristicMute($value)
    {
		 switch ($value) {
            case HAPCharacteristicMute::MuteOn:
                $value = 0;
                break;
            case HAPCharacteristicMute::MuteOff:
                $value = 1;
                break;
        }

        self::switchDevice($this->data['VariableID'], $value);
    }
}

class HAPAccessoryConfigurationSpeaker
{
    use HelperSwitchDevice;

    public static function getPosition()
    {
        return 112;
    }

    public static function getCaption()
    {
        return 'Speaker';
    }

    public static function getColumns()
    {
        return [
            [
                'label' => 'VariableID',
                'name'  => 'VariableID',
                'width' => '250px',
                'add'   => 0,
                'edit'  => [
                    'type' => 'SelectVariable'
                ]
            ]
        ];
    }

    public static function getStatus($data)
    {
        return self::getSwitchCompatibility($data['VariableID']);
    }

    public static function getTranslations()
    {
        return [
            'de' => [
                'Speaker'               => 'Lautsprecher',
                'VariableID'            => 'VariablenID',
                'Variable missing'      => 'Variable fehlt',
                'Bool required'         => 'Bool benötigt',
                'Action required'       => 'Aktion benötigt',
                'OK'                    => 'OK'
            ]
        ];
    }
}

HomeKitManager::registerAccessory('Speaker');

Falls du mich meinst:

Bei einem Git pull waren die Helpers leer was zu einem Fehler geführt hat. Darauf hin habe ich versucht das Update über die GUI zu machen. Leider ging das nicht, weil Symcon zu alt war, obwohl ich die letzte Version installiert hatte.

Nach genauer Prüfung habe ich herausgefunden, dass das Update zurück gehalten wurde, da einige Pakete, die nur in Bionic enthalten sind, nicht installiert werden konnten. Darauf hin habe ich 16.04 auf die 18.04 hochgehoben (Was mir ganz recht war)

Nun geht alles inkl. des git submodule für die helper :smiley:

Ah, du hattest manuell einen Git pull gemacht. Da wir mittlerweile ein Submodule drin haben wäre ein „git submodule init && git submodule update“ notwendig gewesen. Und ja, die 5.0er benötigt mittlerweile Ubuntu 18.04 :slight_smile:

paresy

Moin Leute!

Nur ganz kurz, da ich ne Zeitlang weg war. Hab ich richtig gesehen, dass derzeit nur Boolean Variablen in das Modul eingebunden werden können?

Danke und viele Grüße!

Wo hast du das gelesen und was willst du denn „machen“?

@Maccy: Magst du ggf. PRs erstellen für die von dir vorgeschlagenen Accessories?

paresy

Naja eigentlich nur mal meine Temperatur auslesen bzw einstellen. Das Problem:

Wenn ich im Konfigurator die variablen hinterlege. Sagt er mir im Status „Bool Required“. Des weiteren wird mir nach dem hinzufügen in die Homeapp auch nur eine Variable Namens „Wohnzimmer“ und eine entsprechende Temperatur angezeigt. Die Schlafzimmer Variable aber nicht. Hier mal ein Screenshot

Meine Rollos lassen sich einbinden aber leider nur mit einem Status (Aber hab ja gelesen, dass es hier noch nicht richtig funktioniert)

Ah. In der Legacy Konsole fehlen Beschriftungsfelder. Das korrigiere ich. Schau dir es mal in der webbasierten Konsole an. Dort gibt es für die Tabellen noch mehr Beschreibung. Temperatursensoren gehen; Soll-Temperaturen noch nicht.

paresy

Ahhh! Perfekt Danke! Das erklärt auch, warum das Wohnzimmer, trotz löschens, noch drin war!

Funktioniert :slight_smile:

Eins noch bzgl. der Garage:

Ich öffne meine Garage mit einem herkömmlichen Fibaro Switch. Kann ich diesen auch als Garagentoröffner einbinden und mit dem Befehl „Siri öffne die Garage“ öffnen? Wenn ja, welche Variablen muss ich einpflegen?