Apple HomeKit: Anbindung an IPS auf Basis der HomeBridge von nfarina

Mit den Apple TV 3 habe ich auch noch nichts hinbekommen, willkommen im Club

Zeit fürs 4er. Das lohnt auch von den anderen Features. Bei mir läufst auch direkt von unterwegs.

Das kleine reicht. Hab das große und mein Speicher ist kaum voll.

Kann mir mal einer seine module.php aus dem Verzeichnis HomeKitService aus dem IPS Modulverzeichnis posten ?

Hallo xxxchris,

hier meine module.php:

<?
class HomeKitService extends IPSModule {
	
	public function Create() {
		// Diese Zeile nicht löschen.
		parent::Create();
		
	}
	public function ApplyChanges() {
		// Diese Zeile nicht löschen
		parent::ApplyChanges();
		
		
	}
	public function GetValue(string $characteristic, string $homeKitValueType, $defaultValue, integer $homeKitEnumValueCount) {
		// value is directly configured in this instance config form, e.g. temperature display units
		if ($this->HasProperty($characteristic)) return $this->ReadPropertyInteger($characteristic);
		
		// not (yet) implemented in php module
		if (!$this->HasProperty($characteristic . "VariableId")) return $defaultValue;
		
		$variableId = $this->ReadPropertyInteger($characteristic . "VariableId");
		
		// variable not configured in this instance
		if ($variableId == 0) return $defaultValue;
		
		$variable = IPS_GetVariable($variableId);
		$value = $this->GetHomeKitValue($variable, $characteristic, $homeKitValueType, $homeKitEnumValueCount);
		return $value;
	}
	
	public function SetValue(string $characteristic, string $homeKitValueType, $homeKitValue) {
		// value is directly configured in this instance config form, e.g. temperature display units
		if ($this->HasProperty($characteristic)) return $this->SetProperty($characteristic, $homeKitValue);
		
		// not (yet) implemented in php module
		if (!$this->HasProperty($characteristic . "VariableId")) return;
		
		$variableId = $this->ReadPropertyInteger($characteristic . "VariableId");
		
		// variable not configured in this instance
		if ($variableId == 0) return;
		
		$variable = IPS_GetVariable($variableId);
		$variableObject = IPS_GetObject($variableId);
		$ipsValue = $this->GetIPSValue($variable, $characteristic, $homeKitValue, $homeKitValueType);
		
		// request associated action for the specified variable and value
		if ($variable["VariableCustomAction"] > 0)
			IPS_RunScriptEx($variable["VariableCustomAction"], array("VARIABLE" => $variableId, "VALUE" => $ipsValue));
		else
			IPS_RequestAction($variableObject["ParentID"], $variableObject["ObjectIdent"], $ipsValue);
	}
	
	private function GetIPSValue($variable, $characteristic, $homeKitValue, $homeKitValueType) {
		$variableProfile = $variable['VariableProfile']
			? IPS_GetVariableProfile($variable['VariableProfile'])
			: NULL;
		
		$ipsValueString = "";
		switch($homeKitValueType) {
			case "Boolean":
				$ipsValueString = boolval($homeKitValue)
					? $this->ReadPropertyString($characteristic . "ValueTrue")
					: $this->ReadPropertyString($characteristic . "ValueFalse");
				break;
			case "Percent":
				$maxValue = $this->ReadPropertyFloat($characteristic . "MaxValue");
				$targetValue = ($homeKitValue / 100) * $maxValue;
				$ipsValueString = strval($targetValue);
				break;
			case "Integer":
			case "Float":
				$ipsValueString = strval($homeKitValue);
				break;
			case "Enum":
				$ipsValueString = $this->ReadPropertyString($characteristic . "Value" . $homeKitValue);
				break;
		}
		
		if ($ipsValueString == "") return $homeKitValue;
		
		switch ($variable["VariableType"]) {
			case 0: // boolean
				return boolval($ipsValueString);
			case 1: // integer
				return intval($ipsValueString);
			case 2: // float
				return $variableProfile && $variableProfile["Digits"] == 0
					? intval($ipsValueString)
					: floatval($ipsValueString);
			case 3: // string
				return $ipsValueString;
			default:
				return $homeKitValue;
		}
	}
	
	private function GetHomeKitValue($variable, $characteristic, $homeKitValueType, $homeKitEnumValueCount) {
		$value = GetValue($variable["VariableID"]);
		$valueString = strval($value);
		
		switch ($homeKitValueType) {
			case "Boolean":
				return $valueString == $this->ReadPropertyString($characteristic . "ValueTrue");
			case "Percent":
				$maxValue = $this->ReadPropertyFloat($characteristic . "MaxValue");
				$targetValue = ($value / $maxValue) * 100;
				return intval($targetValue);
			case "Float":
				return floatval($value);
			case "Int":
				return intval($value);
			case "Enum":
				if ($homeKitEnumValueCount <= 0) return $value;
				
				for($i = 0; $i < $homeKitEnumValueCount; $i++) {
					$ipsValue = $this->ReadPropertyString($characteristic . "Value" . $i);
					if ($ipsValue == $valueString) return $i;
				}
				
				// value not found
				return $value;
			default:
				return $value;
		}
	}
	
	private function HasProperty($propertyName) {
		$instanceId = $this->InstanceID;
		$configuration = json_decode(IPS_GetConfiguration($instanceId));
		return array_key_exists($propertyName, $configuration);
	}
	
	private function SetProperty($propertyName, $propertyValue) {
		$instanceId = $this->InstanceID;
		IPS_SetProperty($instanceId, $propertyName, $propertyValue);
		IPS_ApplyChanges($instanceId);
	}
}
?>

Axel

Jetzt habe ich mal ein neues Homebridge Accessoire eingerichtet und als Zielvariable eine bereits vorhandene Variable eingetragen: kein Problem Alles OK

Lege ich aber eine neue Variable an und zwar egal wo und verweise auf diese, erhalte ich wieder meine alte Fehlermeldung.

Axel

Danke, habe befürchtet, dass mein Skript in Ordnung ist und daran lag es auch nicht.
Dafür war die KeyMatic Instanz selbst scheinbar nicht korrekt angelegt. Hab eine neue HomeMatic Device Instanz für die KeyMatic angelegt.
Anschließend auf das neues ‚STATE‘ verwiesen. Mit der neuen Instanz funktioniert alles.

Ich habe einen Fehlerverdacht:

Mein Plan war es eine virtuelle Variable über die Homebridge anzusprechen, und über die Statusänderung ein beliebiges Skript zu triggern.
Offensichtlich kann man aber nur solche Variablen als Zielvariablen angeben, die sich unter einer bestehenden Instanz befinden, also z.b. unterhalb eines FS20 Empfängers. Und es darf auch nur eine Variable sein, die bei der Erstellung der Instanz automatisch mit erzeugt wird.

Axel

Ja, das passt zu dem was ich beobachtet habe.
Wenn der Autor des Plugins/Moduls nur mal wieder Zeit hätte um seine Architektur zu erläutern.

Sorry Leute,

dem muss ich insofern widersprechen, da ich nur selbst angelegte Variablen benutze…:eek:

Ich gebe Dir aber insofern recht, als das es sehr schön wäre wenn der Autor des Moduls hier mal ein paar Fragen beantworten könnte…:slight_smile:

Joachim

Welche Services nutzt du mit den selbst angelegten Variablen? Bei mir werden selbst Angelegte nicht mit Werten befüllt bei den Services dir ich nutze.
Habe zum Beispiel versucht über eine Zwischenvariable den Wert für den Rolladen umzudrehen, da momentan bei rauf immer runtergefahren wird und bei runter immer raufgefahren wird. Bei FS20 scheint das anders zu sein als bei den HM mit den notwendigen Werten.
Das hat mit der selbst angelegten Zwischenvariable aber nicht funktioniert.

…was genau hat nicht funktioniert? Gab es eine Fehlermeldung oder war nur die Funktion nicht gegeben?

Joachim

Keine FM. Variable wird nicht gesetzt, aber die eigene Aktion der Variable wird aufgerufen. Sehr Strange. Bei der Variable steht letzte Änderung auf NIE. Aber beim Skript dann die Uhrzeit, wenn der Service die Variable ändert.

…ja, was das Thema angeht hatte ich auch einige „Überraschungsmomente“…insbesondere hat mir die Anmerkung mit der Rückmeldung zu denken gegeben…

Ich war sehr verwundert, das der $_IPS[‚SENDER‘] ein „RunScript“ war und nicht „Variable“.

Meistens verwende ich derzeit die Funktion „LightBulb“. Es wäre von daher wirklich sehr hilfreich, wenn Andre sich mal zur grundsätzlichen Funktion äußern würde…:wink:

Joachim

Ich habe das Problem, dass ich die Zielvariable zwar schreiben kann, wird diese aber von IP-Symcon verändert, wird der Status an EVE nicht übertragen.

[Symcon] 43050: Calling JSON-RPC method HKSLightBulb_GetValue with params [52412,„On“,„Boolean“,false,-1]
[Symcon] 43050: Called JSON-RPC method ‚HKSLightBulb_GetValue‘ with response: „1“
[Symcon] 43050: callback…

Das obige Beispiel zeigt eine Variable, deren Boolscher Wert „True“ ist. In Eve wird dennoch der Status „AUS“ angezeigt.

Fehler gefunden:

in der SymconAccessory.js folgendes ändern:

switch (valueType) {
case ‚Boolean‘:
result = res.result>0;
break;
case ‚Integer‘:
case ‚Enum‘:
case ‚Percent‘:
result = parseInt(res.result);
break;
case ‚Float‘:
result = parseFloat(res.result);
break;
default:
result = res.result;
break;
}

Die Boolean - Werte dürfen nicht als Integer zurückgeliefert werden.

Hallo Timo,

das war mir auch schon als „Fehler“ aufgefallen, hatte es aber im Gegensatz zu Dir nicht einordnen können…:wink:

Wo findet man die Datei?

Joachim

find / -name SymconAccessory.js -print
[emoji16]

Hallo Chris,

in der Raspberry Pi Version habe ich es damit nicht gefunden…:frowning:

In der Windows-Version habe ich zwar die Datei gefunden, aber finde einen solchen Abschnitt nicht wie Timo ihn beschrieben hat…
Muss der in Gänze dort eingefügt werden? Wenn ja, wo?

Joachim

Nur der Case Boolean muss rein. Der Rest ist schon drin weiter unten. Bei mir ist die Datei irgendwo in debian unter usr/lib/…
Bin gerade nicht am Rechner. Deswegen kann ich nicht gucken

Danke für den Tipp, gefunden![emoji2]