First version with read and write to physical modul
added: UpdateAll UpdateSingle After MiGateway define all connected devices to the gateway are added to FHEM with there status Cleanup logging lines [PRE] added for support for switch sensor motion, magnet, sensorht filed devStateIcon oder Stateformat
This commit is contained in:
@@ -1,4 +1,25 @@
|
|||||||
# 71_XiaomiSmartHome.pm 2017-08-02 13:07:33Z torte $
|
###############################################################################
|
||||||
|
#
|
||||||
|
# 03.2017 torte
|
||||||
|
# All rights reserved
|
||||||
|
#
|
||||||
|
# This script is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# The GNU General Public License can be found at
|
||||||
|
# http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
# A copy is found in the textfile GPL.txt and important notices to the license
|
||||||
|
# from the author is found in LICENSE.txt distributed with these scripts.
|
||||||
|
#
|
||||||
|
# This script is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
@@ -10,6 +31,10 @@ use Data::Dumper;
|
|||||||
use IO::Socket;
|
use IO::Socket;
|
||||||
use IO::Socket::Multicast;
|
use IO::Socket::Multicast;
|
||||||
|
|
||||||
|
sub XiaomiSmartHome_Notify($$);
|
||||||
|
sub XiaomiSmartHome_updateSingleReading($$);
|
||||||
|
|
||||||
|
my $version = "0.02";
|
||||||
my %XiaomiSmartHome_gets = (
|
my %XiaomiSmartHome_gets = (
|
||||||
"getDevices" => ["get_id_list", '^.+get_id_list_ack' ],
|
"getDevices" => ["get_id_list", '^.+get_id_list_ack' ],
|
||||||
|
|
||||||
@@ -29,11 +54,14 @@ sub XiaomiSmartHome_Initialize($) {
|
|||||||
$hash->{GetFn} = 'XiaomiSmartHome_Get';
|
$hash->{GetFn} = 'XiaomiSmartHome_Get';
|
||||||
$hash->{AttrFn} = 'XiaomiSmartHome_Attr';
|
$hash->{AttrFn} = 'XiaomiSmartHome_Attr';
|
||||||
$hash->{ReadFn} = 'XiaomiSmartHome_Read';
|
$hash->{ReadFn} = 'XiaomiSmartHome_Read';
|
||||||
$hash->{AttrList} = "disable:1,0 "
|
$hash->{WriteFn} = "XiaomiSmartHome_Write";
|
||||||
. $readingFnAttributes;
|
$hash->{AttrList} = "disable:1,0 " .
|
||||||
|
"Room " .
|
||||||
|
$readingFnAttributes;
|
||||||
$hash->{MatchList} = { "1:XiaomiSmartHome_Device" => "^.+magnet",
|
$hash->{MatchList} = { "1:XiaomiSmartHome_Device" => "^.+magnet",
|
||||||
"2:XiaomiSmartHome_Device" => "^.+motion",
|
"2:XiaomiSmartHome_Device" => "^.+motion",
|
||||||
"3:XiaomiSmartHome_Device" => "^.+sensor_ht"};
|
"3:XiaomiSmartHome_Device" => "^.+sensor_ht",
|
||||||
|
"4:XiaomiSmartHome_Device" => "^.+switch"};
|
||||||
}
|
}
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
@@ -54,28 +82,23 @@ sub XiaomiSmartHome_Read($) {
|
|||||||
my $decoded = decode_json($buf);
|
my $decoded = decode_json($buf);
|
||||||
if ($json)
|
if ($json)
|
||||||
{
|
{
|
||||||
Log3 $name, 5, "$name: Read:" . $buf;
|
Log3 $name, 5, "$name> Read:" . $buf;
|
||||||
if ($decoded->{'cmd'} eq 'heartbeat'){
|
if ($decoded->{'model'} eq 'gateway'){
|
||||||
readingsSingleUpdate($hash, $decoded->{'sid'}, 'heartbeat', 1 );
|
if ($decoded->{'cmd'} eq 'report'){
|
||||||
}
|
|
||||||
elsif ($decoded->{'cmd'} eq 'report'){
|
|
||||||
if ($decoded->{'model'} eq 'gateway'){
|
|
||||||
my @status = split('\"', $decoded->{'data'});
|
my @status = split('\"', $decoded->{'data'});
|
||||||
if ($status[1] eq 'rgb'){
|
if ($status[1] eq 'rgb'){
|
||||||
my $t = ($status[2] =~ /([\d]+)/);
|
Log3 $name, 4, "$name>" . " SID: " . $decoded->{'sid'} . " Type: Gateway" . " RGB: " . ($status[2] =~ /([\d]+)/)[0] ;
|
||||||
Log3 $name, 3, "$name: Gateway: " . $decoded->{'sid'} . " RGB: " . ($status[2] =~ /([\d]+)/)[0] ;
|
readingsSingleUpdate($hash, "RGB", ($status[2] =~ /([\d]+)/)[0] , 1 );
|
||||||
readingsSingleUpdate($hash, "RGB", ($status[2] =~ /([\d]+)/)[0] , 1 );
|
}
|
||||||
}
|
|
||||||
#elsif($status[1] eq 'battery'){
|
|
||||||
# Log3 $name, 3, "$name: MagnetSensor: " . $decoded->{'sid'} . " Battery: " . $status[3];
|
|
||||||
# readingsSingleUpdate($hash, "Battery_" . "$decoded->{'sid'}", "$status[3]", 1 );
|
|
||||||
#}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
Dispatch($hash, $buf, undef);
|
|
||||||
}
|
}
|
||||||
# my @status = split('\"', $decoded->{'data'});
|
elsif ($decoded->{'cmd'} eq 'heartbeat'){
|
||||||
#
|
readingsSingleUpdate($hash, $decoded->{'sid'}, 'heartbeat', 1 );
|
||||||
|
readingsSingleUpdate($hash, 'token', $decoded->{'token'}, 1 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log3 $name, 4, "$name> Dispatch! " . $buf;
|
||||||
|
Dispatch($hash, $buf, undef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,12 +130,13 @@ sub XiaomiSmartHome_Define($$) {
|
|||||||
$hash->{DEF} = $definition;
|
$hash->{DEF} = $definition;
|
||||||
$hash->{NOTIFYDEV} = "global";
|
$hash->{NOTIFYDEV} = "global";
|
||||||
$hash->{NAME} = $param[0];
|
$hash->{NAME} = $param[0];
|
||||||
|
$hash->{VERSION} = $version;
|
||||||
$hash->{GATEYWAY} = $param[2];
|
$hash->{GATEYWAY} = $param[2];
|
||||||
$hash->{FHEMIP} = XiaomiSmartHome_getLocalIP();
|
$hash->{FHEMIP} = XiaomiSmartHome_getLocalIP();
|
||||||
$hash->{STATE} = "initialized";
|
$hash->{STATE} = "initialized";
|
||||||
$hash->{helper}{host} = $definition;
|
$hash->{helper}{host} = $definition;
|
||||||
$hash->{helper}{JSON} = JSON->new->utf8();
|
$hash->{helper}{JSON} = JSON->new->utf8();
|
||||||
Log3 $hash->{NAME}, 3, "$hash->{NAME}: $definition";
|
Log3 $hash->{NAME}, 5, "$hash->{NAME}> $definition";
|
||||||
|
|
||||||
XiaomiSmartHome_connect($hash) if( $init_done);
|
XiaomiSmartHome_connect($hash) if( $init_done);
|
||||||
|
|
||||||
@@ -129,28 +153,59 @@ sub XiaomiSmartHome_Undef($$) {
|
|||||||
}
|
}
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
sub XiaomiSmartHome_Get($@)
|
sub XiaomiSmartHome_Write($$)
|
||||||
{
|
{
|
||||||
|
my ($hash,$cmd,$sid) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $msg = '{"cmd":"' .$cmd . '","sid":"' . $sid . '"}';
|
||||||
|
|
||||||
|
return Log3 $name, 4, "Master ($name) - socket not connected"
|
||||||
|
unless($hash->{CD});
|
||||||
|
|
||||||
|
Log3 $name, 4, "$name> $msg " . $hash->{GATEYWAY};
|
||||||
|
my $sock = $hash->{CD};
|
||||||
|
my $MAXLEN = 1024;
|
||||||
|
$sock->mcast_send($msg,$hash->{GATEYWAY} .':9898') or die "send: $!";
|
||||||
|
|
||||||
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
|
|
||||||
|
sub XiaomiSmartHome_Get($@)
|
||||||
|
{
|
||||||
|
my ($hash , $name, $opt, $args ) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
if ($opt eq "UpdateAll")
|
||||||
|
{
|
||||||
|
XiaomiSmartHome_updateAllReadings($hash);
|
||||||
|
Log3 $name, 5, "$name> UpdateALLReadings Started";
|
||||||
|
}
|
||||||
|
elsif($opt eq "UpdateSingle")
|
||||||
|
{
|
||||||
|
XiaomiSmartHome_updateSingleReading($hash,$args);
|
||||||
|
Log3 $name, 5, "$name> UpdateSingel Started";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return "unknown argument $opt choose one of UpdateAll:noArg UpdateSingle";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#####################################
|
||||||
|
|
||||||
sub XiaomiSmartHome_Notify($$)
|
sub XiaomiSmartHome_Notify($$)
|
||||||
{
|
{
|
||||||
my ($own_hash, $dev_hash) = @_;
|
my ($own_hash, $dev_hash) = @_;
|
||||||
my $ownName = $own_hash->{NAME}; # own name / hash
|
my $ownName = $own_hash->{NAME}; # own name / hash
|
||||||
Log3 $ownName, 3, "$ownName: NotifyStart - $dev_hash->{NAME}";
|
Log3 $ownName, 3, "$ownName> NotifyStart";
|
||||||
return "" if(IsDisabled($ownName)); # Return without any further action if the module is disabled
|
return "" if(IsDisabled($ownName)); # Return without any further action if the module is disabled
|
||||||
|
|
||||||
my $devName = $dev_hash->{NAME}; # Device that created the events
|
my $devName = $dev_hash->{NAME}; # Device that created the events
|
||||||
my $events = deviceEvents($dev_hash, 1);
|
my $events = deviceEvents($dev_hash, 1);
|
||||||
Log3 $ownName, 3, "$ownName: $devName";
|
|
||||||
print join("; ", @{$events});
|
|
||||||
Log3 $ownName, 3, "$ownName: " . grep(m/^INITIALIZED|REREADCFG$/, @{$events});
|
|
||||||
if($devName eq "global" && grep(m/^INITIALIZED|REREADCFG$/, @{$events}))
|
if($devName eq "global" && grep(m/^INITIALIZED|REREADCFG$/, @{$events}))
|
||||||
{
|
{
|
||||||
Log3 $ownName, 3, "$ownName: 2";
|
Log3 $ownName, 3, "$ownName> Starting Connect";
|
||||||
XiaomiSmartHome_connect($own_hash);
|
XiaomiSmartHome_connect($own_hash);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,12 +225,11 @@ sub XiaomiSmartHome_connect($)
|
|||||||
{
|
{
|
||||||
my $hash = shift;
|
my $hash = shift;
|
||||||
my $name = $hash->{NAME};
|
my $name = $hash->{NAME};
|
||||||
Log3 $name, 3, "$name: ConnectStart";
|
Log3 $name, 3, "$name> ConnectStart";
|
||||||
#return if (AttrVal($hash->{NAME}, "disable", 0));
|
|
||||||
|
|
||||||
XiaomiSmartHome_disconnect($hash);
|
XiaomiSmartHome_disconnect($hash);
|
||||||
|
|
||||||
Log3 $name, 4, "$name: connecting";
|
Log3 $name, 4, "$name> connecting";
|
||||||
|
|
||||||
my $sock = IO::Socket::Multicast->new( Proto => 'udp', LocalPort =>'9898', ReuseAddr => 1) or die "Creating socket: $!\n";
|
my $sock = IO::Socket::Multicast->new( Proto => 'udp', LocalPort =>'9898', ReuseAddr => 1) or die "Creating socket: $!\n";
|
||||||
$sock->mcast_add('224.0.0.50', $hash->{fhemIP} ) || die "Couldn't set group: $!\n"; #$hash->{fhemIP}
|
$sock->mcast_add('224.0.0.50', $hash->{fhemIP} ) || die "Couldn't set group: $!\n"; #$hash->{fhemIP}
|
||||||
@@ -184,7 +238,7 @@ sub XiaomiSmartHome_connect($)
|
|||||||
|
|
||||||
if ($sock)
|
if ($sock)
|
||||||
{
|
{
|
||||||
Log3 $name, 3, "$name: connected";
|
Log3 $name, 3, "$name> connected";
|
||||||
|
|
||||||
$hash->{helper}{ConnectionState} = "Connected";
|
$hash->{helper}{ConnectionState} = "Connected";
|
||||||
|
|
||||||
@@ -198,11 +252,11 @@ sub XiaomiSmartHome_connect($)
|
|||||||
|
|
||||||
$selectlist{$name} = $hash;
|
$selectlist{$name} = $hash;
|
||||||
|
|
||||||
#XiaomiSmartHome_updateAllReadings($hash);
|
XiaomiSmartHome_updateAllReadings($hash);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Log3 $name, 1, "$name: connect to $hash->{helper}{host} failed";
|
Log3 $name, 1, "$name> connect to $hash->{helper}{host} failed";
|
||||||
}
|
}
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
@@ -222,7 +276,7 @@ sub XiaomiSmartHome_disconnect($)
|
|||||||
}
|
}
|
||||||
|
|
||||||
return if (!$hash->{CD});
|
return if (!$hash->{CD});
|
||||||
Log3 $name, 3, "$name: disconnecting";
|
Log3 $name, 3, "$name> disconnecting";
|
||||||
|
|
||||||
close($hash->{CD});
|
close($hash->{CD});
|
||||||
delete($hash->{CD});
|
delete($hash->{CD});
|
||||||
@@ -230,6 +284,60 @@ sub XiaomiSmartHome_disconnect($)
|
|||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
sub XiaomiSmartHome_updateSingleReading($$)
|
||||||
|
{
|
||||||
|
my ($hash, $sensor) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $GATEYWAY = $hash->{GATEYWAY};
|
||||||
|
my $sock = $hash->{CD};
|
||||||
|
my $MAXLEN = 1024;
|
||||||
|
|
||||||
|
Log3 $name, 4, "$name> PushSingelRead:" . $sensor;
|
||||||
|
XiaomiSmartHome_Write($hash, $sensor);
|
||||||
|
|
||||||
|
}
|
||||||
|
#####################################
|
||||||
|
|
||||||
|
sub XiaomiSmartHome_updateAllReadings($)
|
||||||
|
{
|
||||||
|
my $hash = shift;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $GATEYWAY = $hash->{GATEYWAY};
|
||||||
|
my $sock = $hash->{CD};
|
||||||
|
my $MAXLEN = 1024;
|
||||||
|
|
||||||
|
my $msg = '{"cmd" : "get_id_list"}';
|
||||||
|
$sock->mcast_send($msg, $GATEYWAY .':9898') or die "send: $!";
|
||||||
|
eval {
|
||||||
|
$sock->recv($msg, $MAXLEN) or die "recv: $!";
|
||||||
|
Log3 $name, 5, "$name> " . $msg;
|
||||||
|
my $json = $hash->{helper}{JSON}->incr_parse($msg);
|
||||||
|
my $decoded = decode_json($msg);
|
||||||
|
if ($json){
|
||||||
|
Log3 $name, 5, "$name> Read:" . $msg;
|
||||||
|
if ($decoded->{'cmd'} eq 'get_id_list_ack'){
|
||||||
|
my @sensors = split('\"', $decoded->{'data'});
|
||||||
|
@sensors = grep {$_ ne ',' and $_ ne ']' and $_ ne '[' } @sensors;
|
||||||
|
foreach my $sensor (@sensors)
|
||||||
|
{
|
||||||
|
$msg = '{"cmd":"read","sid":"' . $sensor . '" }';
|
||||||
|
Log3 $name, 4, "$name> PushRead:" . $sensor;
|
||||||
|
my $msg = '{"cmd":"read","sid":"' . $sensor . '" }';
|
||||||
|
$sock->mcast_send($msg, $GATEYWAY .':9898') or die "send: $!";
|
||||||
|
eval {
|
||||||
|
$sock->recv($msg, $MAXLEN) or die "recv: $!";
|
||||||
|
Log3 $name, 5, "$name> " . $msg;
|
||||||
|
Dispatch($hash, $msg, undef);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#####################################
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,40 @@
|
|||||||
# 71_XiaomiSmartHome_Device.pm 2017-08-02 13:07:33Z torte $
|
###############################################################################
|
||||||
|
#
|
||||||
|
# 03.2017 torte
|
||||||
|
# All rights reserved
|
||||||
|
#
|
||||||
|
# This script is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# any later version.
|
||||||
|
#
|
||||||
|
# The GNU General Public License can be found at
|
||||||
|
# http://www.gnu.org/copyleft/gpl.html.
|
||||||
|
# A copy is found in the textfile GPL.txt and important notices to the license
|
||||||
|
# from the author is found in LICENSE.txt distributed with these scripts.
|
||||||
|
#
|
||||||
|
# This script is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
#
|
||||||
|
###############################################################################
|
||||||
package main;
|
package main;
|
||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
|
my $version = "0.02";
|
||||||
|
sub XiaomiSmartHome_Device_updateSReading($);
|
||||||
|
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
sub XiaomiSmartHome_Device_Initialize($)
|
sub XiaomiSmartHome_Device_Initialize($)
|
||||||
{
|
{
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
|
||||||
$hash->{Match} = "^.+magnet|motion|sensor_ht";
|
$hash->{Match} = "^.+magnet|motion|sensor_ht|switch";
|
||||||
$hash->{DefFn} = "XiaomiSmartHome_Device_Define";
|
$hash->{DefFn} = "XiaomiSmartHome_Device_Define";
|
||||||
#$hash->{SetFn} = "XiaomiSmartHome_Device_Set";
|
#$hash->{SetFn} = "XiaomiSmartHome_Device_Set";
|
||||||
$hash->{UndefFn} = "XiaomiSmartHome_Device_Undef";
|
$hash->{UndefFn} = "XiaomiSmartHome_Device_Undef";
|
||||||
@@ -35,13 +59,48 @@ sub XiaomiSmartHome_Device_mot($$)
|
|||||||
|
|
||||||
sub XiaomiSmartHome_Device_on_timeout($){
|
sub XiaomiSmartHome_Device_on_timeout($){
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
|
my $name = $hash->{LASTInputDev};
|
||||||
if ($hash->{STATE} eq 'motion') {
|
if ($hash->{STATE} eq 'motion') {
|
||||||
readingsSingleUpdate($hash, "state", "off", 1 );
|
readingsSingleUpdate($hash, "state", "off", 1 );
|
||||||
|
Log3 $name, 3, "$name>" . " SID: " . $hash->{SID} . " Type: " . $hash->{MODEL} . " Status: off";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#####################################
|
#####################################
|
||||||
|
sub XiaomiSmartHome_Device_Read($$$){
|
||||||
|
my ($hash, $msg, $name) = @_;
|
||||||
|
my $decoded = decode_json($msg);
|
||||||
|
|
||||||
|
my $sid = $decoded->{'sid'};
|
||||||
|
my $model = $decoded->{'model'};
|
||||||
|
Log3 $name, 5, "$name: SID: " . $hash->{SID} . " " . $hash->{TYPE};
|
||||||
|
my @status = split('\"', $decoded->{'data'});
|
||||||
|
if ($status[1] eq 'status'){
|
||||||
|
Log3 $name, 3, "$name>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Status: " . $status[3];
|
||||||
|
readingsSingleUpdate($hash, "state", "$status[3]", 1 );
|
||||||
|
}
|
||||||
|
elsif($status[1] eq 'voltage'){
|
||||||
|
Log3 $name, 3, "$name>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Voltage: " . $status[3];
|
||||||
|
readingsSingleUpdate($hash, "voltage", "$status[3]", 1 );
|
||||||
|
}
|
||||||
|
elsif($status[1] eq 'temperature'){
|
||||||
|
Log3 $name, 3, "$name>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Temperature: " . $status[3];
|
||||||
|
$status[3] =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g;
|
||||||
|
readingsSingleUpdate($hash, "temperature", "$status[3]", 1 );
|
||||||
|
}
|
||||||
|
elsif($status[1] eq 'humidity'){
|
||||||
|
Log3 $name, 3, "$name>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Humidity: " . $status[3];
|
||||||
|
$status[3] =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g;
|
||||||
|
readingsSingleUpdate($hash, "humidity", "$status[3]", 1 );
|
||||||
|
}
|
||||||
|
elsif ($decoded->{'cmd'} eq 'heartbeat'){
|
||||||
|
readingsSingleUpdate($hash, $decoded->{'sid'}, 'heartbeat', 1 );
|
||||||
|
}
|
||||||
|
XiaomiSmartHome_Device_update($hash);
|
||||||
|
return $hash->{NAME};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#####################################
|
||||||
|
|
||||||
sub XiaomiSmartHome_Device_Parse($$) {
|
sub XiaomiSmartHome_Device_Parse($$) {
|
||||||
my ($io_hash, $msg) = @_;
|
my ($io_hash, $msg) = @_;
|
||||||
@@ -49,38 +108,19 @@ sub XiaomiSmartHome_Device_Parse($$) {
|
|||||||
|
|
||||||
my $sid = $decoded->{'sid'};
|
my $sid = $decoded->{'sid'};
|
||||||
my $model = $decoded->{'model'};
|
my $model = $decoded->{'model'};
|
||||||
|
my $name = $io_hash->{NAME};
|
||||||
|
|
||||||
if (my $hash = $modules{XiaomiSmartHome_Device}{defptr}{$sid})
|
if (my $hash = $modules{XiaomiSmartHome_Device}{defptr}{$sid})
|
||||||
{
|
{
|
||||||
my $name = $hash->{NAME};
|
Log3 $name, 4, "$name> IS DEFINED " . $model . " : " .$sid;
|
||||||
Log3 $name, 5, "$name: SID: " . $hash->{SID} . " " . $hash->{TYPE};
|
XiaomiSmartHome_Device_Read($hash, $msg, $name);
|
||||||
my @status = split('\"', $decoded->{'data'});
|
|
||||||
if ($status[1] eq 'status'){
|
|
||||||
Log3 $name, 3, "$name: Sensor: " . $hash->{MODEL} . " SID: " . $sid . " Status: " . $status[3];
|
|
||||||
readingsSingleUpdate($hash, "state", "$status[3]", 1 );
|
|
||||||
}
|
|
||||||
elsif($status[1] eq 'voltage'){
|
|
||||||
Log3 $name, 3, "$name: Sensor: " . $hash->{MODEL} . " SID: " . $sid . " Voltage: " . $status[3];
|
|
||||||
readingsSingleUpdate($hash, "voltage", "$status[3]", 1 );
|
|
||||||
}
|
|
||||||
elsif($status[1] eq 'temperature'){
|
|
||||||
Log3 $name, 3, "$name: Sensor: " . $hash->{MODEL} . " SID: " . $sid . " Temperature: " . $status[3];
|
|
||||||
$status[3] =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g;
|
|
||||||
readingsSingleUpdate($hash, "temperature", "$status[3]", 1 );
|
|
||||||
}
|
|
||||||
elsif($status[1] eq 'humidity'){
|
|
||||||
Log3 $name, 3, "$name: Sensor: " . $hash->{MODEL} . " SID: " . $sid . " Humidity: " . $status[3];
|
|
||||||
$status[3] =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g;
|
|
||||||
readingsSingleUpdate($hash, "humidity", "$status[3]", 1 );
|
|
||||||
}
|
|
||||||
XiaomiSmartHome_Device_update($hash);
|
|
||||||
return $hash->{NAME};
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return "UNDEFINED $sid XiaomiSmartHome_Device $model $sid";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Log3 $name, 4, "$name> UNDEFINED " . $model . " : " .$sid;
|
||||||
|
return "UNDEFINED $sid XiaomiSmartHome_Device $model $name";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
@@ -107,25 +147,69 @@ sub XiaomiSmartHome_Device_update($){
|
|||||||
|
|
||||||
sub XiaomiSmartHome_Device_Define($$) {
|
sub XiaomiSmartHome_Device_Define($$) {
|
||||||
my ($hash, $def) = @_;
|
my ($hash, $def) = @_;
|
||||||
my ($name, $modul, $type, $sid) = split("[ \t]+", $def);
|
my ($name, $modul, $type, $iodev) = split("[ \t]+", $def);
|
||||||
Log3 $name, 3, "$name: $modul $type $sid";
|
#Log3 "test", 3, "Define status = " . $status;
|
||||||
$hash->{TYPE} = $modul;
|
$hash->{TYPE} = $modul;
|
||||||
$hash->{MODEL} = $type;
|
$hash->{MODEL} = $type;
|
||||||
$hash->{SID} = $sid;
|
$hash->{SID} = $name;
|
||||||
$hash->{NAME} = $sid;
|
$hash->{NAME} = $name;
|
||||||
$hash->{STATE} = "initialized";
|
$hash->{VERSION} = $version;
|
||||||
$modules{XiaomiSmartHome_Device}{defptr}{$sid} = $hash;
|
$hash->{STATE} = 'initialized';
|
||||||
AssignIoPort($hash);
|
$modules{XiaomiSmartHome_Device}{defptr}{$name} = $hash;
|
||||||
|
AssignIoPort($hash,$iodev);
|
||||||
|
|
||||||
|
if(defined($hash->{IODev}->{NAME})) {
|
||||||
|
my $IOname = $hash->{IODev}->{NAME};
|
||||||
|
Log3 $name, 3, $IOname . "> " .$name. ": " . $type . " I/O device is " . $hash->{IODev}->{NAME};
|
||||||
|
} else {
|
||||||
|
Log3 $name, 1, "$name $type - no I/O device";
|
||||||
|
}
|
||||||
|
$iodev = $hash->{IODev}->{NAME};
|
||||||
|
|
||||||
|
my $d = $modules{XiaomiSmartHome_Device}{defptr}{$name};
|
||||||
|
|
||||||
|
return "XiaomiSmartHome device $hash->{SID} on XiaomiSmartHome $iodev already defined as $d->{NAME}." if( defined($d) && $d->{IODev} == $hash->{IODev} && $d->{NAME} ne $name );
|
||||||
|
|
||||||
|
Log3 $name, 3, $iodev . "> " . $name . "- defined with Code: ". $hash->{DEV};
|
||||||
|
$attr{$name}{room} = "MiSmartHome" if( !defined( $attr{$name}{room} ) );
|
||||||
|
if( $type eq 'motion') {
|
||||||
|
$attr{$name}{devStateIcon} = 'motion:motion_detector@red off:motion_detector@green' if( !defined( $attr{$name}{devStateIcon} ) );
|
||||||
|
}
|
||||||
|
elsif ( $type eq 'magnet') {
|
||||||
|
$attr{$name}{devStateIcon} = 'open:fts_door_open@red close:fts_door@green' if( !defined( $attr{$name}{devStateIcon} ) );
|
||||||
|
}
|
||||||
|
elsif ( $type eq 'sensor_ht') {
|
||||||
|
$attr{$name}{stateFormat} = 'temperature °C, humidity %' if( !defined( $attr{$name}{stateFormat} ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if( $init_done ) {
|
||||||
|
InternalTimer( gettimeofday()+int(rand(2)), "XiaomiSmartHome_Device_updateSReading", $hash, 0 );
|
||||||
|
Log3 $name, 4, $iodev . "> " . $name . " Init Done set InternalTimer for Update";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#####################################
|
||||||
|
sub XiaomiSmartHome_Device_updateSReading($) {
|
||||||
|
|
||||||
|
my $hash = shift;
|
||||||
|
#my $name = $hash->{NAME};
|
||||||
|
#Log3 $name, 3, $name . " Updae SR";
|
||||||
|
IOWrite($hash,'read',"$hash->{SID}");
|
||||||
}
|
}
|
||||||
#####################################
|
#####################################
|
||||||
|
|
||||||
|
#####################################
|
||||||
sub XiaomiSmartHome_Device_Undef($)
|
sub XiaomiSmartHome_Device_Undef($)
|
||||||
{
|
{
|
||||||
my ($hash, $arg) = @_;
|
my ($hash, $arg) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
RemoveInternalTimer($hash);
|
RemoveInternalTimer($hash);
|
||||||
delete($modules{XiaomiSmartHome_Device}{defptr}{$hash->{SID}});
|
delete($modules{XiaomiSmartHome_Device}{defptr}{$hash->{SID}});
|
||||||
return undef;
|
my $code = $hash->{IODev}->{NAME} if( defined($hash->{IODev}->{NAME}) );
|
||||||
|
delete($modules{HEOSPlayer}{defptr}{$code});
|
||||||
|
|
||||||
|
Log3 $name, 3, "$code> $name - device deleted";
|
||||||
|
return undef;
|
||||||
|
|
||||||
}
|
}
|
||||||
1;
|
1;
|
||||||
#####################################
|
#####################################
|
||||||
|
|||||||
Reference in New Issue
Block a user