Version 1.0

add: support for sensors all up to now
86sw1,86sw2,ctrl_neutral1,ctrl_neutral2,rgbw_light
add: ringvol set ringtone and volume in one step.
add: support for multigatways
add: commandref english and german
add: support if gateway is not reachable
fix: eval all decode json to prevent perl crash
This commit is contained in:
2017-05-22 20:07:54 +02:00
parent e51a88c85b
commit 0be3e06894
3 changed files with 532 additions and 98 deletions

View File

@@ -25,7 +25,7 @@ package main;
use strict;
use warnings;
my $version = "0.21";
my $version = "1.00";
sub XiaomiSmartHome_Device_updateSReading($);
@@ -35,7 +35,7 @@ sub XiaomiSmartHome_Device_Initialize($)
{
my ($hash) = @_;
$hash->{Match} = "^.+magnet|motion|sensor_ht|switch|plug|cube|86sw2";
$hash->{Match} = "^.+magnet|motion|sensor_ht|switch|plug|cube|86sw1|86sw2|ctrl_neutral1|ctrl_neutral2|rgbw_light";
$hash->{DefFn} = "XiaomiSmartHome_Device_Define";
$hash->{SetFn} = "XiaomiSmartHome_Device_Set";
$hash->{UndefFn} = "XiaomiSmartHome_Device_Undef";
@@ -66,6 +66,8 @@ sub XiaomiSmartHome_Device_Set($@)
$setlist .= "motionOffTimer:1,5,10 " if ($hash->{MODEL} eq 'motion');
#$setlist = "open:noArg close:noArg " if ($hash->{MODEL} eq 'magnet');
$setlist .= "power:on,off " if ($hash->{MODEL} eq 'plug');
$setlist .= "ctrl:on,off " if ($hash->{MODEL} eq 'ctrl_neutral1');
$setlist .= "channel_0:on,off channel_1:on,off " if ($hash->{MODEL} eq 'ctrl_neutral2');
if($cmd eq "power")
{
@@ -80,6 +82,45 @@ sub XiaomiSmartHome_Device_Set($@)
return;
}
}
if($cmd eq "ctrl")
{
if($args[0] eq "on")
{
IOWrite($hash,"ctrl","on",$hash);
return;
}
elsif($args[0] eq "off")
{
IOWrite($hash,"ctrl","off",$hash);
return;
}
}
if($cmd eq "channel_0")
{
if($args[0] eq "on")
{
IOWrite($hash,"channel_0","on",$hash);
return;
}
elsif($args[0] eq "off")
{
IOWrite($hash,"channel_0","off",$hash);
return;
}
}
if($cmd eq "channel_1")
{
if($args[0] eq "on")
{
IOWrite($hash,"channel_1","on",$hash);
return;
}
elsif($args[0] eq "off")
{
IOWrite($hash,"channel_1","off",$hash);
return;
}
}
# if($cmd eq "open")
# {
# readingsSingleUpdate($hash, "state", "open", 1 );
@@ -109,11 +150,19 @@ sub XiaomiSmartHome_Device_on_timeout($){
#####################################
sub XiaomiSmartHome_Device_Read($$$){
my ($hash, $msg, $name) = @_;
my $decoded = decode_json($msg);
my $decoded = eval{decode_json($msg)};
if ($@) {
Log3 $name, 1, "$name: DEV_Read> Error while request: $@";
return;
}
my $sid = $decoded->{'sid'};
my $model = $decoded->{'model'};
Log3 $name, 5, "$name: DEV_Read> SID: " . $hash->{SID} . " " . $hash->{TYPE};
my $data = decode_json($decoded->{data});
my $data = eval{decode_json($decoded->{data})};
if ($@) {
Log3 $name, 1, "$name: DEV_Read> Error while request data: $@";
return;
}
readingsBeginUpdate( $hash );
if (defined $data->{status}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Status: " . $data->{status};
@@ -150,7 +199,7 @@ sub XiaomiSmartHome_Device_Read($$$){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Humidity: " . $hum;
readingsBulkUpdate($hash, "humidity", "$hum", 1 );
}
#86sw2 start
#86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 start
if (defined $data->{channel_0}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_0: " . $data->{channel_0};
readingsBulkUpdate($hash, "channel_0", "$data->{channel_0}", 1 );
@@ -159,7 +208,7 @@ sub XiaomiSmartHome_Device_Read($$$){
Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_1: " . $data->{channel_1};
readingsBulkUpdate($hash, "channel_1", "$data->{channel_1}", 1 );
}
#86sw2 end
#86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 end
#plug start
if (defined $data->{load_voltage}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Voltage: " . $data->{load_voltage};
@@ -178,6 +227,32 @@ sub XiaomiSmartHome_Device_Read($$$){
readingsBulkUpdate($hash, "inuse", "$data->{inuse}", 1 );
}
#plug end
#rgbw_light start
if (defined $data->{level}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Level: " . $data->{level};
readingsBulkUpdate($hash, "level", "$data->{level}", 1 );
}
if (defined $data->{hue}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Hue: " . $data->{hue};
readingsBulkUpdate($hash, "hue", "$data->{hue}", 1 );
}
if (defined $data->{saturation}){
Log3 $name, 3, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Saturation: " . $data->{saturation};
readingsBulkUpdate($hash, "saturation", "$data->{saturation}", 1 );
}
if (defined $data->{color_temperature}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Color_temperature: " . $data->{color_temperature};
readingsBulkUpdate($hash, "color_temperature", "$data->{color_temperature}", 1 );
}
if (defined $data->{x}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " X: " . $data->{x};
readingsBulkUpdate($hash, "x", "$data->{x}", 1 );
}
if (defined $data->{y}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Y: " . $data->{y};
readingsBulkUpdate($hash, "y", "$data->{y}", 1 );
}
#rgbw_light end
#cube start
if (defined $data->{rotate}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Rotate: " . $data->{rotate};
@@ -196,12 +271,15 @@ sub XiaomiSmartHome_Device_Read($$$){
sub XiaomiSmartHome_Device_Parse($$) {
my ($io_hash, $msg) = @_;
my $decoded = decode_json($msg);
my $name = $io_hash->{NAME};
my $decoded = eval{decode_json($msg)};
if ($@) {
Log3 $name, 1, "$name: DEV_Parse> Error while request: $@";
return;
}
my $sid = $decoded->{'sid'};
my $model = $decoded->{'model'};
my $name = $io_hash->{NAME};
if (my $io_hash = $modules{XiaomiSmartHome_Device}{defptr}{$sid})
{
Log3 $name, 4, "$name: DEV_Parse> IS DEFINED " . $model . " : " .$sid;
@@ -306,14 +384,171 @@ sub XiaomiSmartHome_Device_Undef($)
}
1;
#####################################
=pod
=item device
=item summary Module to control XiaomiSmartHome Gateway
=begin html
<a name="XiaomiSmartHome_Device"></a>
<h3>XiaomiSmartHome_Device</h3>
<h3>XiaomiSmartHome</h3>
<ul>
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<a name="XiaomiSmartHome"></a>
<br/>
<b>Prerequisite</b>
<ul>
<li>Installation of the following packages: apt-get install libio-socket-multicast-perl libjson-perl libcrypt-cbc-perl</li>
<li>And with CPAN: cpan Crypt::Cipher::AES</li>
</ul>
<br/>
<b>Define</b>
<ul>
<code>define &lt;name&gt; XiaomiSmartHome &lt;IP or Hostname&gt;</code>
<br><br>
Example: <code>define XiaomiSmartHome XiaomiSmartHome 192.168.1.xxx</code>
<br><br>
</ul>
<br/>
<b>Set Developermode on the gateway!</b>
<ul>
<p>Without the developer mode, no communication with the XiaomiSmartHome gateway is possible.
<br/>You need an android or ios device. You must often click on the APP versionsnumber to activate the hidden menu.
<br/>Here is how to turn on the developer mode.
<br/>Android -> https://louiszl.gitbooks.io/lumi-gateway-local-api/content/device_discover.html
<br/>IOS go here -> https://github.com/fooxy/homeassistant-aqara/wiki/Enable-dev-mode
<br/>The password shown in the app must set on the FHEM XioamiSmartHome Gatewaydevice!</p>
</ul>
<br/>
<b>Supported Sensors</b>
<ul>
<li>magnet: Window/Door magnetic sensor</li>
<li>motion: Human body motion sensor</li>
<li>sensor_ht: Temperatur and humidity sensor</li>
<li>switch: Wireless sensor switch</li>
<li>plug: Smart socket</li>
<li>cube: Cube sensor</li>
<li>86sw1: Wireless switch single</li>
<li>86sw2: Wireless switch double</li>
<li>ctrl_neutral1: Single bond ignition switch</li>
<li>ctrl_neutral2: Double bond ignition switch</li>
<li>rgbw_light: Smart lights (report only)</li>
</ul>
<br/>
<b>Heartbeat</b>
<ul>
<li>The XiaomiSmartHome Gateway send every 10 seconds a heartbeat</li>
<li>The XiaomiSmartHome Devices send every 60 minutes</li>
<li>The Reading heartbeat will show the SID if a heartbeat received</li>
</ul>
<br/>
<b>Set: Gateway</b>
<ul>
<li>password: without password no write to the gateway is possible. Use the MI APP to find the password</li>
<li>RGB(Colorpicker): set the color</li>
<li>PCT(Slider): set the brightness in percent</li>
<li>ringtone: set the ringtone 0-8,13,21-29,10001-.. | 10000 = off</li>
<li>volume: set the volume 1-100, (100 is very loud)</li>
<li>ringvol: set ringtone and volume in on step e.g. set [GWNAME] ringvol 21 10</li>
</ul>
<br/>
<b>Set: Devices</b>
<ul>
<li>motionOffTimer: (only motionsensor)
<br/>You can set a motion Off Timer Attribut on the motion sensor device. You can set 1, 5 or 10 seconds after
<br/>the motion sensors will automatically set to off.
<br/>Background: The motionsensors does not send off immediately.
<br/>The Motionsensor send a no_motion after 120, 180, 300, 600, 1200 seconds no motion is detected.</li>
<li>Power: (only smart soket) on off switch a plug on or off</li>
<li>ctrl: (only single wirless switch) on off switch </li>
<li>channel_0: (only double wirless switch) on off switch </li>
<li>channel_1: (only double wirless switch) on off switch </li>
</ul>
</ul>
=end html
=begin html_DE
<a name="XiaomiSmartHome"></a>
<h3>XiaomiSmartHome</h3>
<ul>
<i>XiaomiSmartHome</i> Steuern des XiaomiSmartHome Gateway und deren verbundener Sensoren.
<a name="XiaomiSmartHome"></a>
<br/>
<b>Vorraussetzungen</b>
<ul>
<li>Diese Pakete m&uumlssen installiert sein: apt-get install libio-socket-multicast-perl libjson-perl libcrypt-cbc-perl</li>
<li>Und mit CPAN: cpan Crypt::Cipher::AES</li>
</ul>
<br/>
<b>Define</b>
<ul>
<code>define &lt;name&gt; XiaomiSmartHome &lt;IP oder Name&gt;</code>
<br><br>
Example: <code>define XiaomiSmartHome XiaomiSmartHome 192.168.1.xxx</code>
<br><br>
</ul>
<br/>
<b>Entwicklermodus am Gatway setzen!</b>
<ul>
<p>Ohne Entwicklermodus ist keine Komunikation mit dem Gateway m&oumlglich.
<br/>Zum setzen des Entwicklermoduses braucht man ein android oder ios Ger&aumlt mit installierter MI APP.
<br/>Um das versteckte Men&uuml zu &oumlffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<br/>Hier finden Sie eine Anleitung mit Bildern.
<br/>Android -> https://louiszl.gitbooks.io/lumi-gateway-local-api/content/device_discover.html
<br/>IOS -> https://github.com/fooxy/homeassistant-aqara/wiki/Enable-dev-mode
<br/>Das Passwort welches in der MI APP angezeigt wird muss im FHEM XiaomiSmartHome Gateway Device gesetzt werden!</p>
</ul>
<br/>
<b>Unterstütze Sensoren</b>
<ul>
<li>magnet: Magnetischer Fenster/T&uumlr Sensor</li>
<li>motion: Bewegungsmelder</li>
<li>sensor_ht: Temperatur und Luftdruck</li>
<li>switch: Funkschalter</li>
<li>plug: Schaltbare Funksteckdose</li>
<li>cube: W&uumlrfel Sensor</li>
<li>86sw1: Einfacher Wandfunkschalter</li>
<li>86sw2: Wandfunkschalter doppelt</li>
<li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li>
<li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li>
<li>rgbw_light: RBGW Lampe (nur Anzeige)</li>
</ul>
<br/>
<b>Heartbeat</b>
<ul>
<li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li>
<li>Jedes XiaomiSmartHome Devices sendet alle 60 Minuten einen heartbeat</li>
<li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim empfang eines Heartbeat aktualisiert</li>
</ul>
<br/>
<b>Set: Gateway</b>
<ul>
<li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&oumlglich. Das Passwort findet man in der MI APP</li>
<li>RGB(Colorpicker): Einstellen der LED Farbe des Gateways</li>
<li>PCT(Slider): Einstellen der Helligkeit des Gateways</li>
<li>ringtone: Wiedergeben eines Arlarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</li>
<li>volume: Einstellen der Lautst&aumlrke des Arlarmtones 1-100, (100 ist sehr laut!)</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges verändern der Lautst&aumlrke set [GWNAME] ringvol 21 10</li>
</ul>
<br/>
<b>Set: Devices</b>
<ul>
<li>motionOffTimer: (nur Bewegungsmelder)
<br/>Durch setzen des Parameters ist es m&oumlglich das das Reading des Bewegungsmelder nach 1, 5 oder 10 Sekunden
<br/>automatisch wieder auf off gestellt wird.
<br/>Hintergrund: Der Bewegungsmelder sendet kein selber kein off.
<br/>Der Bewegungsmelder sendet no_motion nach 120, 180, 300, 600, 1200 Sekunden wenn keine Bewegung festgestellt wurde.</li>
<li>Power: (nur Funksteckdose) on off Funktsteckdose ein oder ausschalten</li>
<li>ctrl: (nur Funkschalter) on off Funkschalter </li>
<li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
<li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
</ul>
</ul>
=end html_DE
=cut