Compare commits

45 Commits
pr/5 ... devel

Author SHA1 Message Date
8f5f50385b -fix: error handling
-fix: error handling malformed JSON
2019-07-16 07:21:05 +02:00
430adca511 -fix: error handling
-fix: error handling malformed JSON
2019-07-09 07:46:13 +02:00
d3c97857c0 Update controls_mish.txt
-fix: wrong time
2019-05-02 12:43:23 +02:00
f3dc58137a Merge branch 'master' of https://github.com/T0RST3N/fhem-XiaomiSmartHome 2019-05-02 12:38:32 +02:00
9bde01610d -fix: bug connextionstate
-fix: bug connectionstate and reconnect after disconnected gateway
2019-05-02 12:38:22 +02:00
7cdbe5f16c Update README.md 2019-03-22 07:11:26 +01:00
e7e4634a53 Update controls_mish.txt
-fix: wrong timeformat
2019-03-21 08:18:48 +01:00
475b60c50b Merge branch 'devel' 2019-03-21 08:12:11 +01:00
2b637d9066 fix multiple events
close #18 no response, i didnt find/understand the problem.
close #20 no response
-fix:  If more than one gateway is used, only one event is now triggered.
-fix:  Fixed spelling errors in german help.
2019-03-20 12:00:35 +01:00
140f258c82 Update README.md 2019-01-31 07:27:07 +01:00
5bf1141eaa Update README.md 2018-11-24 16:10:31 +01:00
fbd347aae3 add support
-add support for sensor Singel Rocker
-add support for sensor Double Rocker
-add support for sensor Wirless Mini Switch
-add function for reconnect if disconnected
2018-11-24 00:00:42 +01:00
d3d96436a2 Support for new Sensors vibration
-add support for sensor vibration
-fix some fixes for multigw support.
2018-09-09 12:52:58 +02:00
631c54d0d9 Fix double dispatch
-fix: dispatching twice
2018-07-02 21:20:59 +02:00
ae08a7455e Merge pull request #17 from T0RST3N/devel
close #16
close #15
close #14
close #13

-change: the sensors now align themselves with their real gateway (iodev)
-change: the ne aqara cube is supportet but the firmware has an bug
-change batteryreadings changed to FHEM standard
2018-07-02 08:51:50 +02:00
ad1fa232ca some changes and fixes
close #16
close #15
close #14
close #13

-change: the sensors now align themselves with their real gateway (iodev)
-change: the ne aqara cube is supportet but the firmware has an bug
-change batteryreadings changed to FHEM standard
2018-06-22 13:50:57 +02:00
e4b1f0cb0c Merge branch 'master' into devel 2018-06-22 13:23:10 +02:00
2065ea1e8f Update README.md 2017-12-20 22:50:55 +01:00
a7625c0802 Update controls_mish.txt 2017-12-18 14:32:36 +01:00
5c5c845696 Update controls_mish.txt 2017-12-18 14:31:53 +01:00
a11d334298 Add missing Round pressure, Fix something
-added: missing round pressure
-added: round to zero decimal places
-added: helper list connected sensors
-change: reading battery_level to  batteryLevel
-fix: multigwsupport sensorreadings are now to correct gw associated
2017-12-18 14:20:48 +01:00
672521a4aa Merge remote-tracking branch 'refs/remotes/origin/master' into devel 2017-12-18 08:53:55 +01:00
95c240efce help added
-change: device specific help
2017-12-15 09:49:02 +01:00
c3f37feacd help added
-change: device specific help
2017-12-15 09:39:22 +01:00
feefe1a418 Merge pull request #9 from T0RST3N/devel
some changes and fixes
2017-12-15 09:12:09 +01:00
a71f701e7c Merge branch 'master' into devel 2017-12-15 09:11:21 +01:00
ff57476935 some changes and fixes
- change: Perl modul math::round no longer necessary
- change: reading round is now rnd_tmp, rnd_hum, rnd_bat
- change: reading battery is now batterystate
closes #8
- change: reading battery is now battery_level
- fix: if GW has no SID reading stop
- fix: if temperature is [1][0].xx or -[1][0].xx now the leading number
is display
-fix: if no or wrong data is reached data will be skipped
- added: support switch 86sw2 dual_channel click
2017-12-13 08:17:19 +01:00
0a9738f543 some changes and fixes
- change: Perl modul math::round no longer necessary
- change: reading round is now rnd_tmp, rnd_hum, rnd_bat
- change: reading battery is now batterystate
- change: reading battery is now battery_level
- fix: if GW has no SID reading stop
- fix: if temperature is [1][0].xx or -[1][0].xx now the leading number
is display
- added: support switch 86sw2 dual_channel click
2017-12-08 13:44:47 +01:00
5e4194c5c1 -fix: rollback, no error 2017-10-30 11:25:07 +01:00
9c3fc38dc7 -fix: rollback, no error 2017-10-30 11:21:19 +01:00
24d7fc4e87 -fix: rollback, no error 2017-10-30 11:18:14 +01:00
0a1c2b4732 -fix: check 'cmd' wrong, must define befor 2017-10-30 07:40:27 +01:00
d19108559b -fix: check 'cmd' wrong, must define befor 2017-10-30 07:35:20 +01:00
9caee3a95f -fix: heartbeat no longer report status again 2017-10-25 10:26:59 +02:00
eb3dddcdc2 FIX 2017-10-24 09:38:26 +02:00
cca119e3fc FIX 2017-10-24 09:32:18 +02:00
3f9b1bc745 New sensor wleak(water), learning sensors, some fixes and improvments
NEW PERL MODULE MATH ROUND IS NECESSARY
- added: new Wleak.aq1 Water sensor
- added: learn, learning sensors with fhem
- added: round, temperature and humidity can now be rounded
- added: new reading batterystate (low or ok)
- change: on verbose 3 only status messages will be logged
- change: new sensors will inherit his room from gateway
- fix: smoke and gas sensor copy and paste error
2017-10-24 09:25:31 +02:00
a0f59fd96e Update README.md 2017-10-24 09:02:30 +02:00
ca97220d09 Update README.md 2017-10-16 07:21:43 +02:00
3b5be4a8c5 Update README.md 2017-10-04 18:45:05 +02:00
3e2dd99769 Update README.md 2017-10-04 18:38:54 +02:00
52ff120e11 Add files via upload 2017-09-15 08:27:47 +02:00
cdde04b39d controls_mish.txt for version 1.08 2017-08-13 18:17:32 +02:00
9571dcf066 controls_mish.txt for version 1.08 2017-08-13 17:53:35 +02:00
c7f242fd82 Merge pull request #5 from bihlmaier/master
Added: new Aqara Human body motion sensor
2017-08-13 17:46:25 +02:00
5 changed files with 559 additions and 294 deletions

View File

@@ -41,15 +41,15 @@ return "\nERROR: Please install Crypt::CBC" if($@);
eval "use Net::Ping"; eval "use Net::Ping";
return "\nERROR: Please install Net::Ping" if($@); return "\nERROR: Please install Net::Ping" if($@);
use Color; use Color;
use SetExtensions; use SetExtensions;
sub XiaomiSmartHome_Notify($$);
sub XiaomiSmartHome_updateSingleReading($$); sub XiaomiSmartHome_updateSingleReading($$);
my $iv="\x17\x99\x6d\x09\x3d\x28\xdd\xb3\xba\x69\x5a\x2e\x6f\x58\x56\x2e"; my $iv="\x17\x99\x6d\x09\x3d\x28\xdd\xb3\xba\x69\x5a\x2e\x6f\x58\x56\x2e";
my $version = "1.08";
my $version = "1.43";
my %XiaomiSmartHome_gets = ( my %XiaomiSmartHome_gets = (
"getDevices" => ["get_id_list", '^.+get_id_list_ack' ], "getDevices" => ["get_id_list", '^.+get_id_list_ack' ],
@@ -64,6 +64,7 @@ my %sets = (
"volume:slider,1,1,100" => 1, "volume:slider,1,1,100" => 1,
"ringtone:0,1,2,3,4,5,6,7,8,13,21,22,23,24,25,26,27,28,29,10000,10001" => 1, "ringtone:0,1,2,3,4,5,6,7,8,13,21,22,23,24,25,26,27,28,29,10000,10001" => 1,
"ringvol" => 2, "ringvol" => 2,
"learn" => 0,
); );
@@ -71,8 +72,8 @@ my %sets = (
sub XiaomiSmartHome_Initialize($) { sub XiaomiSmartHome_Initialize($) {
my ($hash) = @_; my ($hash) = @_;
$hash->{Clients} = "XiaomiSmartHome_Device"; $hash->{Clients} = 'XiaomiSmartHome_Device';
$hash->{DefFn} = 'XiaomiSmartHome_Define'; $hash->{DefFn} = 'XiaomiSmartHome_Define';
$hash->{UndefFn} = 'XiaomiSmartHome_Undef'; $hash->{UndefFn} = 'XiaomiSmartHome_Undef';
$hash->{NotifyFn} = 'XiaomiSmartHome_Notify'; $hash->{NotifyFn} = 'XiaomiSmartHome_Notify';
@@ -80,15 +81,16 @@ 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->{WriteFn} = "XiaomiSmartHome_Write"; $hash->{ReadyFn} = 'XiaomiSmartHome_Ready';
$hash->{AttrList} = "disable:1,0 " . $hash->{WriteFn} = 'XiaomiSmartHome_Write';
$hash->{AttrList} = 'disable:1,0 ' .
$readingFnAttributes; $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.*", "4:XiaomiSmartHome_Device" => ".*switch.*",
"5:XiaomiSmartHome_Device" => "^.+cube", "5:XiaomiSmartHome_Device" => ".*cube.*",
"6:XiaomiSmartHome_Device" => "^.+plug", "6:XiaomiSmartHome_Device" => "^.+plug",
"7:XiaomiSmartHome_Device" => "^.+86sw1", "7:XiaomiSmartHome_Device" => "^.+86sw1",
"8:XiaomiSmartHome_Device" => "^.+86sw2", "8:XiaomiSmartHome_Device" => "^.+86sw2",
@@ -102,7 +104,12 @@ sub XiaomiSmartHome_Initialize($) {
"16:XiaomiSmartHome_Device" => "^.+natgas", "16:XiaomiSmartHome_Device" => "^.+natgas",
"17:XiaomiSmartHome_Device" => "^.+smoke", "17:XiaomiSmartHome_Device" => "^.+smoke",
"18:XiaomiSmartHome_Device" => "^.+weather.v1", "18:XiaomiSmartHome_Device" => "^.+weather.v1",
"19:XiaomiSmartHome_Device" => "^.+sensor_motion.aq2"}; "19:XiaomiSmartHome_Device" => "^.+sensor_motion.aq2",
"20:XiaomiSmartHome_Device" => "^.+sensor_wleak.aq1",
"21:XiaomiSmartHome_Device" => "^.+vibration",
"22:XiaomiSmartHome_Device" => "^.*b186acn01",
"23:XiaomiSmartHome_Device" => "^.*b286acn01",
"24:XiaomiSmartHome_Device" => "^.*b1acn01"};
FHEM_colorpickerInit(); FHEM_colorpickerInit();
} }
##################################### #####################################
@@ -110,10 +117,13 @@ sub XiaomiSmartHome_Read($) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $self = {}; # my new hash my $self = {}; # my new hash
my $new_hash = {};
Log3 $name, 5, "$name: Read> Read start"; Log3 $name, 5, "$name: Read> Read start";
my $buf = ""; if ( ! $hash->{SID} ){
Log3 $name, 3, "$name: Read> No SID, Stop Read";
return;
}
my $buf = "";
my $ret = sysread($hash->{CD}, $buf, 1024); my $ret = sysread($hash->{CD}, $buf, 1024);
if (!defined($ret) || $ret <= 0) if (!defined($ret) || $ret <= 0)
{ {
@@ -122,35 +132,81 @@ sub XiaomiSmartHome_Read($) {
InternalTimer(gettimeofday() + 2, "XiaomiSmartHome_connect", $hash, 0); InternalTimer(gettimeofday() + 2, "XiaomiSmartHome_connect", $hash, 0);
return; return;
} }
my $json = $hash->{helper}{JSON}->incr_parse($buf);
my $decoded = eval{decode_json($buf)}; my $decoded = eval{decode_json($buf)};
if ($@) { if ($@) {
Log3 $name, 1, "$name: Read> Error while request: $@"; Log3 $name, 1, "$name: Read> Error while request: $@ " . $buf;
return; return;
} }
if ( ! $decoded ) { if ( ! $decoded ) {
Log3 $name, 5, "$name: Read> Error no JSON Data " . $buf; Log3 $name, 5, "$name: Read> Error no JSON Data " . $buf;
return; return;
} }
my $json = $hash->{helper}{JSON}->incr_parse($buf);
if ($json) if ($json)
{ {
Log3 $name, 5, "$name: Read> " . $buf; Log3 $name, 5, "$name: Read> [PLAIN] " . $buf;
my $rsid = $decoded->{'sid'}; my $rsid = $decoded->{'sid'};
if ($decoded->{'cmd'} eq 'read_ack' || $decoded->{'cmd'} eq 'report' && $decoded->{'model'} ne 'gateway'|| $decoded->{'cmd'} eq 'heartbeat' && $decoded->{'model'} ne 'gateway' || $decoded->{'cmd'} eq 'write_ack' && $decoded->{'model'} ne 'gateway') { if ($decoded->{'cmd'} eq 'read_ack' || $decoded->{'cmd'} eq 'report' && $decoded->{'model'} ne 'gateway'|| $decoded->{'cmd'} eq 'heartbeat' && $decoded->{'model'} ne 'gateway' || $decoded->{'cmd'} eq 'write_ack' && $decoded->{'model'} ne 'gateway') {
Log3 $name, 5, "$name: Read> Dispatch " . $buf; # devices does not exist yet
Dispatch($hash, $buf, undef); if (!$modules{XiaomiSmartHome_Device}{defptr}{$rsid}{IODev}->{NAME}){
Log3 $name, 5, "$name: Read> XiaomiSmartHome_Device unknown trying autocreate" ;
my $def=$modules{XiaomiSmartHome}{defptr};
while(my ($key, $value) =each(%$def)){
XiaomiSmartHome_Write($value, 'get_id_list');
Log3 $value->{NAME}, 5, "$value->{NAME}: Push to get all Sensors for Gateway $value->{NAME} " . $key;
if ($value->{helper}{sensors} =~ m/$rsid/ ) {
Log3 $value->{NAME}, 5, "$value->{NAME}: $rsid is sensor from $value->{NAME}";
Dispatch($value, $buf, undef);
return;
}
}
}
# devices available with proper and HEARTBEAT gw
elsif ($decoded->{'cmd'} eq 'heartbeat' && $modules{XiaomiSmartHome_Device}{defptr}{$rsid}{IODev}->{NAME} eq $hash->{NAME}) {
Log3 $name, 5, "$name: Read> Dispatching! " . "SID: " . $rsid . " " . $modules{XiaomiSmartHome_Device}{defptr}{$rsid}{IODev}->{NAME} . " " . $hash->{NAME};
Dispatch($hash, $buf, undef);
return;
}
elsif ($decoded->{'cmd'} eq 'report' && $modules{XiaomiSmartHome_Device}{defptr}{$rsid}{IODev}->{NAME} eq $hash->{NAME}) {
Log3 $name, 5, "$name: Read> Dispatching! " . "SID: " . $rsid . " " . $modules{XiaomiSmartHome_Device}{defptr}{$rsid}{IODev}->{NAME} . " " . $hash->{NAME};
Dispatch($hash, $buf, undef);
return;
}
# Senosoren check change to right GW
elsif ($decoded->{'cmd'} eq 'read_ack') {
$hash = $modules{XiaomiSmartHome_Device}{defptr}{$rsid}->{IODev};
Log3 $name, 4, "$name: Read> Dispatching using this GW " . $hash->{NAME} ;
Dispatch($hash, $buf, undef);
return;
}
} }
# gateway sensor list
elsif ($decoded->{'cmd'} eq 'get_id_list_ack'){
$self = $modules{XiaomiSmartHome}{defptr}{$rsid};
Log3 $name, 5, "$name: Read> Reading Sensorlist with $self->{NAME}" ;
XiaomiSmartHome_Reading ($self, $buf);
return;
}
# gateway not definded
elsif (!$modules{XiaomiSmartHome}{defptr}{$rsid}){
Log3 $name, 1, "$name: Read> GW not defined " . $buf;
return;
}
# gateway defined but not the right modul instance - change
elsif ( $modules{XiaomiSmartHome}{defptr}{$rsid}->{SID} ne $hash->{SID} ){ elsif ( $modules{XiaomiSmartHome}{defptr}{$rsid}->{SID} ne $hash->{SID} ){
$self = $modules{XiaomiSmartHome}{defptr}{$rsid}; $self = $modules{XiaomiSmartHome}{defptr}{$rsid};
Log3 $name, 5, "$name: Read> Change HASH Ref to $self->{NAME}"; Log3 $name, 5, "$name: Read> Wrong Modul HASH skipping $self->{NAME}";
XiaomiSmartHome_Reading ($self, $buf); #XiaomiSmartHome_Reading ($self, $buf); no reading anymore!
return;
} }
else #gateway defined and the right modul instance - nothing to change
{ elsif ( $modules{XiaomiSmartHome}{defptr}{$rsid}->{SID} eq $hash->{SID} ){
Log3 $name, 5, "$name: Read> HASH correctly"; Log3 $name, 5, "$name: Read> HASH correctly";
XiaomiSmartHome_Reading ($hash, $buf); XiaomiSmartHome_Reading ($hash, $buf);
} return;
} }
}
} }
##################################### #####################################
sub XiaomiSmartHome_Reading ($@) { sub XiaomiSmartHome_Reading ($@) {
@@ -199,7 +255,7 @@ sub XiaomiSmartHome_Reading ($@) {
#$hash->{SID} = $decoded->{'sid'}; #$hash->{SID} = $decoded->{'sid'};
} }
else { else {
Log3 $name, 4, "$name: Reading> IP-Heartbeat Data didnt match! $data->{ip} " . $hash->{GATEWAY_IP} ; Log3 $name, 5, "$name: Reading> IP-Heartbeat Data didnt match! $data->{ip} " . $hash->{GATEWAY_IP} ;
} }
} }
} }
@@ -215,10 +271,10 @@ sub XiaomiSmartHome_Reading ($@) {
return; return;
} }
if ($data->{error}){ if ($data->{error}){
readingsBulkUpdate($hash, 'heartbeat', $data->{error}, 1 ); readingsBulkUpdate($hash, 'heartbeat', $data->{error}, 1 );
} }
else { else {
readingsBulkUpdate($hash, 'heartbeat', "Write_OK", 1 ); readingsBulkUpdate($hash, 'heartbeat', "Write_OK", 1 );
readingsBulkUpdate($hash, "proto_version", $data->{proto_version} , 1 ); readingsBulkUpdate($hash, "proto_version", $data->{proto_version} , 1 );
} }
} }
@@ -235,11 +291,14 @@ sub XiaomiSmartHome_Reading ($@) {
Log3 $name, 1, "$name: Reading> Error while request: $@"; Log3 $name, 1, "$name: Reading> Error while request: $@";
return; return;
} }
foreach my $sensor (@sensors) my $all_sensors = "";
foreach my $sensor (@sensors)
{ {
Log3 $name, 4, "$name: Reading> PushRead:" . $sensor; Log3 $name, 4, "$name: Reading> PushRead:" . $sensor;
XiaomiSmartHome_Write($hash, 'read', $sensor ); XiaomiSmartHome_Write($hash, 'read', $sensor );
$all_sensors = $all_sensors . $sensor . ",";
} }
$hash->{helper}{sensors} = $all_sensors;
return; return;
} }
} }
@@ -286,16 +345,16 @@ sub XiaomiSmartHome_getGatewaySID($){
} }
if ($json) { if ($json) {
if ($decoded->{'ip'} eq $ip){ if ($decoded->{'ip'} eq $ip){
Log3 $name, 4, "$name: getGatewaySID> Find SID for Gateway: $decoded->{sid}"; Log3 $name, 3, "$name: getGatewaySID> Find SID for Gateway: $decoded->{sid}";
$sidsock->close(); $sidsock->close();
$hash->{SID} = $decoded->{sid}; $hash->{SID} = $decoded->{sid};
$modules{XiaomiSmartHome}{defptr}{$decoded->{sid}} = $hash; $modules{XiaomiSmartHome}{defptr}{$decoded->{sid}} = $hash;
return $decoded->{sid}; return $decoded->{sid};
} }
else { else {
Log3 $name, 4, "$name: getGatewaySID> whois Data didnt match! $decoded->{sid} $decoded->{'ip'} ". $ip ; Log3 $name, 5, "$name: getGatewaySID> whois Data didnt match! $decoded->{sid} $decoded->{'ip'} ". $ip ;
} }
} }
}; };
if ($@) { if ($@) {
Log3 $name, 1, "$name: getGatewaySID> Error no response from whois!! STOP!!"; Log3 $name, 1, "$name: getGatewaySID> Error no response from whois!! STOP!!";
@@ -326,8 +385,8 @@ sub XiaomiSmartHome_Define($$) {
if ( ! $p->ping($param[2])){ if ( ! $p->ping($param[2])){
$hash->{STATE} = "Disconnected"; $hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash); XiaomiSmartHome_disconnect($hash);
Log3 $name, 5, "$name: Define> Ping ERROR Gateway disconnecting"; Log3 $name, 1, "$name: Define> Ping ERROR Gateway disconnecting";
$p->close(); $p->close();
} }
my $GATEWAY_IP = $param[2]; my $GATEWAY_IP = $param[2];
my $definition = $param[2]; my $definition = $param[2];
@@ -339,12 +398,12 @@ sub XiaomiSmartHome_Define($$) {
$hash->{helper}{JSON} = JSON->new->utf8(); $hash->{helper}{JSON} = JSON->new->utf8();
$hash->{FHEMIP} = XiaomiSmartHome_getLocalIP(); $hash->{FHEMIP} = XiaomiSmartHome_getLocalIP();
$hash->{STATE} = "initialized"; $hash->{STATE} = "initialized";
$hash->{helper}{host} = $definition; $hash->{helper}{host} = $definition;
if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){ if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){
eval { eval {
$GATEWAY_IP = inet_ntoa(inet_aton($hash->{GATEWAY})) ; $GATEWAY_IP = inet_ntoa(inet_aton($hash->{GATEWAY})) ;
$hash->{GATEWAY_IP} = $GATEWAY_IP; $hash->{GATEWAY_IP} = $GATEWAY_IP;
Log3 $name, 1, "$name: Define> Set GATEWAYs IP: " . $GATEWAY_IP; Log3 $name, 5, "$name: Define> Set GATEWAYs IP: " . $GATEWAY_IP;
}; };
if ($@) { if ($@) {
Log3 $name, 1, "$name: Define> Error $@\n"; Log3 $name, 1, "$name: Define> Error $@\n";
@@ -354,24 +413,24 @@ sub XiaomiSmartHome_Define($$) {
} }
} }
$hash->{GATEWAY_IP} = $GATEWAY_IP; $hash->{GATEWAY_IP} = $GATEWAY_IP;
$modules{XiaomiSmartHome}{defptr}{$GATEWAY_IP} = $hash; #$modules{XiaomiSmartHome}{defptr}{$GATEWAY_IP} = $hash;
#$hash->{SID} = XiaomiSmartHome_getGatewaySID($hash); #$hash->{SID} = XiaomiSmartHome_getGatewaySID($hash);
Log3 $name, 5, "$name: Define> $definition"; Log3 $name, 5, "$name: Define> $definition";
# Define devStateIcon # Define devStateIcon
$attr{$hash->{NAME}}{devStateIcon} = '{Color_devStateIcon(ReadingsVal($name,"rgb","000000"))}' if(!defined($attr{$hash->{NAME}}{devStateIcon})); $attr{$hash->{NAME}}{devStateIcon} = '{Color_devStateIcon(ReadingsVal($name,"rgb","000000"))}' if(!defined($attr{$hash->{NAME}}{devStateIcon}));
$attr{$hash->{NAME}}{room} = "MiSmartHome" if( !defined( $attr{$hash->{NAME}}{room} ) ); $attr{$hash->{NAME}}{room} = "MiSmartHome" if( !defined( $attr{$hash->{NAME}}{room} ) );
InternalTimer(gettimeofday() + 5, "XiaomiSmartHome_connect", $hash, 0); InternalTimer(gettimeofday() + 5, "XiaomiSmartHome_connect", $hash, 0);
return undef; return undef;
} }
##################################### #####################################
sub XiaomiSmartHome_Undef($$) { sub XiaomiSmartHome_Undef($$) {
my ($hash, $arg) = @_; my ($hash, $arg) = @_;
XiaomiSmartHome_disconnect($hash); XiaomiSmartHome_disconnect($hash);
# nothing to do # nothing to do
return undef; return undef;
@@ -382,8 +441,8 @@ sub XiaomiSmartHome_Write($@)
{ {
my ($hash,$cmd,$val,$iohash) = @_; my ($hash,$cmd,$val,$iohash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
if ( $hash->{helper}{ConnectionState} eq 'Disconnected') { if ( $hash->{helper}{ConnectionState} eq 'Disconnected') {
Log3 $name, 1, "$name: Write> Cannot write iam disconnected"; Log3 $name, 1, "$name: Write> Cannot write iam Disconnected";
return undef; return undef;
} }
else{ else{
@@ -393,7 +452,7 @@ sub XiaomiSmartHome_Write($@)
Log3 $name, 1, "$name: Write> Ping to $hash->{helper}{host} failed"; Log3 $name, 1, "$name: Write> Ping to $hash->{helper}{host} failed";
$hash->{STATE} = "Disconnected"; $hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash); XiaomiSmartHome_disconnect($hash);
$p->close(); $p->close();
return undef; return undef;
} }
} }
@@ -475,6 +534,11 @@ sub XiaomiSmartHome_Write($@)
{ {
$msg = '{"cmd":"write","model":"curtain","sid":"' . $iohash->{SID} . '","data":"{\"curtain_level\":\"' . $val . '\",\"key\":\"'. XiaomiSmartHome_EncryptKey($hash) .'\"}" }'; $msg = '{"cmd":"write","model":"curtain","sid":"' . $iohash->{SID} . '","data":"{\"curtain_level\":\"' . $val . '\",\"key\":\"'. XiaomiSmartHome_EncryptKey($hash) .'\"}" }';
} }
if ($cmd eq 'learn')
{
my $t = '"yes"';
$msg = '{"cmd":"write","model":"gateway","sid":"' . $hash->{SID} . '","data":"{\"join_permission\":' . $t . ',\"key\":\"'. XiaomiSmartHome_EncryptKey($hash) .'\"}" }';
}
} }
} }
return Log3 $name, 4, "$name: Write> - socket not connected" unless($hash->{CD}); return Log3 $name, 4, "$name: Write> - socket not connected" unless($hash->{CD});
@@ -482,7 +546,7 @@ sub XiaomiSmartHome_Write($@)
my $sock = $hash->{CD}; my $sock = $hash->{CD};
my $MAXLEN = 1024; my $MAXLEN = 1024;
$sock->mcast_send($msg,$GATEWAY .':9898') or die "send: $!"; $sock->mcast_send($msg,$GATEWAY .':9898') or die "send: $!";
Log3 $name, 5, "$name: Write> End " . $GATEWAY; Log3 $name, 4, "$name: Write> End " . $GATEWAY;
return undef; return undef;
} }
##################################### #####################################
@@ -493,9 +557,9 @@ sub XiaomiSmartHome_EncryptKey($)
my $name = $hash->{NAME}; my $name = $hash->{NAME};
if ( $hash->{READINGS}{password}{VAL} =~ /^[a-zA-Z0-9]{16}$/ ) { if ( $hash->{READINGS}{password}{VAL} =~ /^[a-zA-Z0-9]{16}$/ ) {
my $key = $hash->{READINGS}{password}{VAL}; my $key = $hash->{READINGS}{password}{VAL};
my $cipher = Crypt::CBC->new(-key => $key, -cipher => 'Cipher::AES',-iv => $iv, -literal_key => 1, -header => "none", -keysize => 16 ); my $cipher = Crypt::CBC->new(-key => $key, -cipher => 'Cipher::AES',-iv => $iv, -literal_key => 1, -header => "none", -keysize => 16 );
my $encryptkey = $cipher->encrypt_hex($hash->{READINGS}{token}{VAL}); my $encryptkey = $cipher->encrypt_hex($hash->{READINGS}{token}{VAL});
$encryptkey = substr($encryptkey, 0, 32); $encryptkey = substr($encryptkey, 0, 32);
return $encryptkey; return $encryptkey;
} }
else else
@@ -506,19 +570,37 @@ sub XiaomiSmartHome_EncryptKey($)
} }
##################################### #####################################
sub XiaomiSmartHome_Ready($)
{
my ($hash) = @_;
# Versuch eines Verbindungsaufbaus, sofern die Verbindung beendet ist.
return DevIo_OpenDev($hash, 1, undef ) if ( $hash->{helper}{ConnectionState} eq "Disconnected" );
# This is relevant for Windows/USB only
if(defined($hash->{USBDev})) {
my $po = $hash->{USBDev};
my ( $BlockingFlags, $InBytes, $OutBytes, $ErrorFlags ) = $po->status;
return ( $InBytes > 0 );
}
}
#####################################
sub XiaomiSmartHome_Get($@) sub XiaomiSmartHome_Get($@)
{ {
my ($hash , $name, $opt, $args ) = @_; my ($hash , $name, $opt, $args ) = @_;
if ($opt eq "UpdateAll") if ($opt eq "UpdateAll")
{ {
XiaomiSmartHome_updateAllReadings($hash); XiaomiSmartHome_updateAllReadings($hash);
Log3 $name, 5, "$name: Get> UpdateALLReadings Started"; Log3 $name, 3, "$name: Get> UpdateALLReadings Started";
return "UpdateALLReadings Started";
} }
elsif($opt eq "UpdateSingle") elsif($opt eq "UpdateSingle")
{ {
XiaomiSmartHome_updateSingleReading($hash,$args); XiaomiSmartHome_updateSingleReading($hash,$args);
Log3 $name, 5, "$name: Get> UpdateSingel Started"; Log3 $name, 3, "$name: Get> UpdateSingel Started";
return "UpdateSingel " . $args . " Started";
} }
else else
{ {
@@ -531,12 +613,23 @@ sub XiaomiSmartHome_Notify($$)
{ {
my ($hash, $dev_hash) = @_; my ($hash, $dev_hash) = @_;
my $ownName = $hash->{NAME}; # own name / hash my $ownName = $hash->{NAME}; # own name / hash
Log3 $ownName, 5, "$ownName: Notify> NotifyStart"; #my $evName = $dev_hash->{NAME}; # triggered device
#my $rsid = $dev_hash->{SID};
Log3 $ownName, 5, "$ownName: Notify> NotifyStart";# . $rsid . " " . $evName;
# gateway defined but not the right modul instance
#if ( $modules{XiaomiSmartHome}{defptr}{$rsid}->{SID} ne $hash->{SID} ){
# Log3 $ownName, 5, "$ownName: Notify> Wrong Event-Modul HASH skipping " . $evName;
# #XiaomiSmartHome_Reading ($self, $buf);
# return;
#}
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
$attr{$hash->{NAME}}{webCmd} = "pct:rgb:rgb ff0000:rgb 00ff00:rgb 0000ff:on:off" if ( ! $attr{$hash->{NAME}}{webCmd} || $attr{$hash->{NAME}}{webCmd} eq "rgb:rgb ff0000:rgb 00ff00:rgb 0000ff:on:off" ); $attr{$hash->{NAME}}{webCmd} = "pct:rgb:rgb ff0000:rgb 00ff00:rgb 0000ff:on:off" if ( ! $attr{$hash->{NAME}}{webCmd} || $attr{$hash->{NAME}}{webCmd} eq "rgb:rgb ff0000:rgb 00ff00:rgb 0000ff:on:off" );
readingsSingleUpdate($hash, "pct", 100, 1) if ( ! $hash->{READINGS}{pct}{VAL}); readingsSingleUpdate($hash, "pct", 100, 1) if ( ! $hash->{READINGS}{pct}{VAL});
readingsSingleUpdate($hash, "ringtone", 21, 1) if ( ! $hash->{READINGS}{ringtone}{VAL}); readingsSingleUpdate($hash, "ringtone", 21, 1) if ( ! $hash->{READINGS}{ringtone}{VAL});
readingsSingleUpdate($hash, "volume", 10, 1) if ( ! $hash->{READINGS}{volume}{VAL}); readingsSingleUpdate($hash, "volume", 10, 1) if ( ! $hash->{READINGS}{volume}{VAL});
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);
if($devName eq "global" && grep(m/^INITIALIZED|REREADCFG$/, @{$events})) if($devName eq "global" && grep(m/^INITIALIZED|REREADCFG$/, @{$events}))
@@ -548,7 +641,7 @@ sub XiaomiSmartHome_Notify($$)
} }
##################################### #####################################
sub XiaomiSmartHome_Set($@) sub XiaomiSmartHome_Set($@)
{ {
my ( $hash, $name, $cmd, @args ) = @_; my ( $hash, $name, $cmd, @args ) = @_;
my $dec_num; my $dec_num;
@@ -557,14 +650,14 @@ sub XiaomiSmartHome_Set($@)
#-- check argument #-- check argument
return SetExtensions($hash, join(" ", keys %sets), $name, $cmd, @args) unless @match == 1; return SetExtensions($hash, join(" ", keys %sets), $name, $cmd, @args) unless @match == 1;
return "$cmd expects $sets{$match[0]} parameters" unless (@args eq $sets{$match[0]}); return "$cmd expects $sets{$match[0]} parameters" unless (@args eq $sets{$match[0]});
return "\"set $name\" needs at least one argument" unless(defined($cmd)); return "\"set $name\" needs at least one argument" unless(defined($cmd));
if (!defined $hash->{READINGS}{pct}) { if (!defined $hash->{READINGS}{pct}) {
$MIpct = $hash->{READINGS}{pct}{VAL}; $MIpct = $hash->{READINGS}{pct}{VAL};
} }
else { else {
$MIpct = 64; $MIpct = 64;
} }
if($cmd eq "password") if($cmd eq "password")
{ {
#if($args[0] =~ /^[a-zA-Z0-9_.-]*$/) #if($args[0] =~ /^[a-zA-Z0-9_.-]*$/)
@@ -576,7 +669,7 @@ sub XiaomiSmartHome_Set($@)
else else
{ {
return "Unknown value $args[0] for $cmd, wrong password, it must be hex and 16 characters"; return "Unknown value $args[0] for $cmd, wrong password, it must be hex and 16 characters";
} }
} }
if ( $hash->{READINGS}{password}{VAL} !~ /^[a-zA-Z0-9]{16}$/) if ( $hash->{READINGS}{password}{VAL} !~ /^[a-zA-Z0-9]{16}$/)
{ {
@@ -587,7 +680,7 @@ sub XiaomiSmartHome_Set($@)
elsif($cmd eq "rgb") elsif($cmd eq "rgb")
{ {
my $ownName = $hash->{NAME}; my $ownName = $hash->{NAME};
Log3 $ownName, 4, "$ownName: Set> $cmd, $args[0]"; Log3 $ownName, 4, "$ownName: Set> $cmd, $args[0]";
$dec_num = sprintf("%d", hex($MIpct . $args[0])); $dec_num = sprintf("%d", hex($MIpct . $args[0]));
Log3 $ownName, 4, "$ownName: Set> $cmd, $dec_num"; Log3 $ownName, 4, "$ownName: Set> $cmd, $dec_num";
@@ -613,13 +706,17 @@ sub XiaomiSmartHome_Set($@)
readingsBulkUpdate( $hash, 'rgb', $hash->{helper}{prevrgbvalue}, 1 ); readingsBulkUpdate( $hash, 'rgb', $hash->{helper}{prevrgbvalue}, 1 );
XiaomiSmartHome_Write($hash,'rgb', $dec_num); XiaomiSmartHome_Write($hash,'rgb', $dec_num);
} }
else else
{ {
readingsBulkUpdate( $hash, 'rgb', "00ff00", 1 ); readingsBulkUpdate( $hash, 'rgb', "00ff00", 1 );
XiaomiSmartHome_Write($hash,'rgb', 1677786880); XiaomiSmartHome_Write($hash,'rgb', 1677786880);
} }
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
} }
elsif($cmd eq "learn")
{
XiaomiSmartHome_Write($hash,'learn', 1);
}
elsif($cmd eq "pct") elsif($cmd eq "pct")
{ {
my $ownName = $hash->{NAME}; my $ownName = $hash->{NAME};
@@ -663,7 +760,7 @@ sub XiaomiSmartHome_Set($@)
sub XiaomiSmartHome_Attr(@) { sub XiaomiSmartHome_Attr(@) {
my ($cmd,$NAME,$name, $val) = @_; my ($cmd,$NAME,$name, $val) = @_;
if ($cmd eq "delete"){ if ($cmd eq "delete"){
delete $attr{$NAME}{$name}; delete $attr{$NAME}{$name};
CommandDeleteAttr(undef, "$NAME $name"); CommandDeleteAttr(undef, "$NAME $name");
Log3 $name, 1, "$name: Attr> delete $name"; Log3 $name, 1, "$name: Attr> delete $name";
} }
@@ -681,21 +778,19 @@ sub XiaomiSmartHome_connect($)
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $GATEWAY_IP; my $GATEWAY_IP;
Log3 $name, 5, "$name: connect> ConnectStart"; Log3 $name, 5, "$name: connect> ConnectStart";
Log3 $name, 4, "$name: connecting";
my $p = Net::Ping->new(); my $p = Net::Ping->new();
if ( ! $p->ping($hash->{GATEWAY})){ if ( ! $p->ping($hash->{GATEWAY})){
Log3 $name, 1, "$name: connect> Ping to $hash->{helper}{host} failed"; Log3 $name, 1, "$name: connect> Ping to $hash->{helper}{host} failed";
$hash->{STATE} = "Disconnected"; $hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash); XiaomiSmartHome_disconnect($hash);
$p->close(); $p->close();
return undef; return undef;
} }
if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){ if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){
eval { eval {
$GATEWAY_IP = inet_ntoa(inet_aton($hash->{GATEWAY})) ; $GATEWAY_IP = inet_ntoa(inet_aton($hash->{GATEWAY})) ;
$hash->{GATEWAY_IP} = $GATEWAY_IP; $hash->{GATEWAY_IP} = $GATEWAY_IP;
Log3 $name, 4, "$name: Connect> Set GATEWAYs IP: " . $GATEWAY_IP; Log3 $name, 5, "$name: Connect> Set GATEWAYs IP: " . $GATEWAY_IP;
}; };
if ($@) { if ($@) {
Log3 $name, 1, "$name: Connect> Error $@\n"; Log3 $name, 1, "$name: Connect> Error $@\n";
@@ -706,12 +801,12 @@ sub XiaomiSmartHome_connect($)
} }
XiaomiSmartHome_getGatewaySID($hash); XiaomiSmartHome_getGatewaySID($hash);
my $timeout = $hash->{TIMEOUT} ? $hash->{TIMEOUT} : 3; my $timeout = $hash->{TIMEOUT} ? $hash->{TIMEOUT} : 3;
my $sock = IO::Socket::Multicast->new( Proto => 'udp', LocalPort =>'9898', ReuseAddr => 1, Timeout => $timeout) or die "Creating socket: $!\n"; my $sock = IO::Socket::Multicast->new( Proto => 'udp', LocalPort =>'9898', ReusePort => 1, ReuseAddr => 1, Timeout => $timeout) or die "Creating socket: $!\n";
$sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, pack('l!l!', 30, 0)) or die "setsockopt: $!"; $sock->setsockopt(SOL_SOCKET, SO_RCVTIMEO, pack('l!l!', 30, 0)) or die "setsockopt: $!";
if ($sock) if ($sock)
{ {
Log3 $name, 3, "$name: connect> Connected"; Log3 $name, 3, "$name: connect> Connected";
$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}
$sock->mcast_ttl(32); $sock->mcast_ttl(32);
$sock->mcast_loopback(1); $sock->mcast_loopback(1);
$hash->{helper}{ConnectionState} = "Connected"; $hash->{helper}{ConnectionState} = "Connected";
@@ -748,13 +843,13 @@ sub XiaomiSmartHome_disconnect($)
} }
return if (!$hash->{CD}); return if (!$hash->{CD});
Log3 $name, 3, "$name: disconnect> disconnecting"; Log3 $name, 1, "$name: disconnect> disconnecting";
close($hash->{CD}) if($hash->{CD}); close($hash->{CD}) if($hash->{CD});
delete($hash->{FD}); delete($hash->{FD});
delete($hash->{CD}); delete($hash->{CD});
delete($selectlist{$name}); delete($selectlist{$name});
return undef; return undef;
} }
@@ -767,10 +862,10 @@ sub XiaomiSmartHome_updateSingleReading($$)
my $GATEWAY = $hash->{GATEWAY}; my $GATEWAY = $hash->{GATEWAY};
my $sock = $hash->{CD}; my $sock = $hash->{CD};
my $MAXLEN = 1024; my $MAXLEN = 1024;
Log3 $name, 4, "$name: updateSingleReading> PushSingelRead:" . $sensor; Log3 $name, 4, "$name: updateSingleReading> PushSingelRead:" . $sensor;
XiaomiSmartHome_Write($hash, 'read', $sensor); XiaomiSmartHome_Write($hash, 'read', $sensor);
} }
##################################### #####################################
@@ -782,10 +877,10 @@ sub XiaomiSmartHome_updateAllReadings($)
my $GATEWAY; my $GATEWAY;
my $p = Net::Ping->new(); my $p = Net::Ping->new();
if ( ! $p->ping($hash->{GATEWAY})){ if ( ! $p->ping($hash->{GATEWAY})){
Log3 $name, 4, "$name: updateAllReadings> Ping to $hash->{helper}{host} failed"; Log3 $name, 1, "$name: updateAllReadings> Ping to $hash->{helper}{host} failed";
$hash->{STATE} = "Disconnected"; $hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash); XiaomiSmartHome_disconnect($hash);
$p->close(); $p->close();
return undef; return undef;
} }
if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){ if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){
@@ -805,13 +900,13 @@ sub XiaomiSmartHome_updateAllReadings($)
$GATEWAY = $hash->{GATEWAY}; $GATEWAY = $hash->{GATEWAY};
} }
if ( $hash->{helper}{ConnectionState} eq 'Disconnected') if ( $hash->{helper}{ConnectionState} eq 'Disconnected')
{ {
Log3 $name, 1, "$name: updateAllReadings> Gateway is $hash->{STATE} trying to reconnect to $hash->{GATEWAY}"; Log3 $name, 1, "$name: updateAllReadings> Gateway is $hash->{STATE} trying to reconnect to $hash->{GATEWAY}";
XiaomiSmartHome_connect($hash); XiaomiSmartHome_connect($hash);
return undef; return undef;
} }
XiaomiSmartHome_Write($hash, 'get_id_list'); XiaomiSmartHome_Write($hash, 'get_id_list');
} }
@@ -829,7 +924,7 @@ sub XiaomiSmartHome_updateAllReadings($)
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome"></a>
<h3>XiaomiSmartHome</h3> <h3>XiaomiSmartHome</h3>
<ul> <ul>
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors. <i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome"></a>
<br/> <br/>
<b>Prerequisite</b> <b>Prerequisite</b>
@@ -872,20 +967,21 @@ sub XiaomiSmartHome_updateAllReadings($)
<li>ctrl_neutral2: Double bond ignition switch</li> <li>ctrl_neutral2: Double bond ignition switch</li>
<li>rgbw_light: Smart lights (report only)</li> <li>rgbw_light: Smart lights (report only)</li>
<li>curtain: Curtain (Control only if device has reporte curtain_level)</li> <li>curtain: Curtain (Control only if device has reporte curtain_level)</li>
<li>water: water detector</li>
<li>smoke: smoke alarm detector</li> <li>smoke: smoke alarm detector</li>
<ul> <ul>
<li>0: disarm</li> <li>0: disarm</li>
<li>1: arlarm</li> <li>1: alarm</li>
<li>8: battery arlarm</li> <li>8: battery alarm</li>
<li>64: arlarm sensitivity</li> <li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li> <li>32768: ICC communication failure</li>
</ul> </ul>
<li>gas: gas alarm detector</li> <li>gas: gas alarm detector</li>
<ul> <ul>
<li>0: disarm</li> <li>0: disarm</li>
<li>1: arlarm</li> <li>1: alarm</li>
<li>2: analog arlarm</li> <li>2: analog alarm</li>
<li>64: arlarm sensitivity</li> <li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li> <li>32768: ICC communication failure</li>
</ul> </ul>
</ul> </ul>
@@ -902,9 +998,11 @@ sub XiaomiSmartHome_updateAllReadings($)
<li>password: without password no write to the gateway is possible. Use the MI APP to find the password</li> <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>RGB(Colorpicker): set the color</li>
<li>PCT(Slider): set the brightness in percent</li> <li>PCT(Slider): set the brightness in percent</li>
<li>intervals: set the gateway to on for an time eg. set intervals 07:00-08:00</li>
<li>ringtone: set the ringtone 0-8,13,21-29,10001-.. | 10000 = off</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>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> <li>ringvol: set ringtone and volume in on step e.g. set [GWNAME] ringvol 21 10</li>
<li>learn: set the gateway in learningmode to learn new sensors now push the button from the new sensor</li>
</ul> </ul>
<br/> <br/>
<b>Set: Devices</b> <b>Set: Devices</b>
@@ -928,12 +1026,12 @@ sub XiaomiSmartHome_updateAllReadings($)
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome"></a>
<h3>XiaomiSmartHome</h3> <h3>XiaomiSmartHome</h3>
<ul> <ul>
<i>XiaomiSmartHome</i> Steuern des XiaomiSmartHome Gateway und deren verbundener Sensoren. <i>XiaomiSmartHome</i> Steuern des XiaomiSmartHome Gateway und deren verbundener Sensoren.
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome"></a>
<br/> <br/>
<b>Vorraussetzungen</b> <b>Voraussetzungen</b>
<ul> <ul>
<li>Diese Pakete m&uumlssen installiert sein: apt-get install libio-socket-multicast-perl libjson-perl libcrypt-cbc-perl</li> <li>Diese Pakete m&uuml;ssen installiert sein: apt-get install libio-socket-multicast-perl libjson-perl libcrypt-cbc-perl</li>
<li>Und mit CPAN: cpan Crypt::Cipher::AES</li> <li>Und mit CPAN: cpan Crypt::Cipher::AES</li>
</ul> </ul>
<br/> <br/>
@@ -945,11 +1043,11 @@ sub XiaomiSmartHome_updateAllReadings($)
<br><br> <br><br>
</ul> </ul>
<br/> <br/>
<b>Entwicklermodus am Gatway setzen!</b> <b>Entwicklermodus am Gateway setzen!</b>
<ul> <ul>
<p>Ohne Entwicklermodus ist keine Komunikation mit dem Gateway m&oumlglich. <p>Ohne Entwicklermodus ist keine Kommunikation mit dem Gateway m&ouml;glich.
<br/>Zum setzen des Entwicklermoduses braucht man ein android oder ios Ger&aumlt mit installierter MI APP. <br/>Zum setzen des Entwicklermodusses braucht man ein android oder ios Ger&auml;t mit installierter MI APP.
<br/>Um das versteckte Men&uuml zu &oumlffnen muss man mehrmals auf die Versionsnummer der MI APP klicken. <br/>Um das versteckte Men&uuml; zu &ouml;ffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<br/>Hier finden Sie eine Anleitung mit Bildern. <br/>Hier finden Sie eine Anleitung mit Bildern.
<br/>Android -> https://louiszl.gitbooks.io/lumi-gateway-local-api/content/device_discover.html <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/>IOS -> https://github.com/fooxy/homeassistant-aqara/wiki/Enable-dev-mode
@@ -958,32 +1056,33 @@ sub XiaomiSmartHome_updateAllReadings($)
<br/> <br/>
<b>Unterstütze Sensoren</b> <b>Unterstütze Sensoren</b>
<ul> <ul>
<li>magnet: Magnetischer Fenster/T&uumlr Sensor</li> <li>magnet: Magnetischer Fenster/T&uuml;r Sensor</li>
<li>motion: Bewegungsmelder</li> <li>motion: Bewegungsmelder</li>
<li>sensor_ht: Temperatur und Luftdruck</li> <li>sensor_ht: Temperatur und Luftdruck</li>
<li>switch: Funkschalter</li> <li>switch: Funkschalter</li>
<li>plug & 86plug: Schaltbare Funksteckdose</li> <li>plug & 86plug: Schaltbare Funksteckdose</li>
<li>cube: W&uumlrfel Sensor</li> <li>cube: W&uuml;rfel Sensor</li>
<li>86sw1: Einfacher Wandfunkschalter</li> <li>86sw1: Einfacher Wandfunkschalter</li>
<li>86sw2: Wandfunkschalter doppelt</li> <li>86sw2: Wandfunkschalter doppelt</li>
<li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li> <li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li>
<li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li> <li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li>
<li>rgbw_light: RBGW Lampe (nur Anzeige)</li> <li>rgbw_light: RBGW Lampe (nur Anzeige)</li>
<li>curtain: Vorhangmotor (ohne das das device den curtain_level gemeldet hat ist ein steuern nicht möglich)</li> <li>curtain: Vorhangmotor (ohne dass das Device den curtain_level gemeldet hat ist ein Steuern nicht m&ouml;glich)</li>
<li>water: Wasser Sensor</li>
<li>smoke: Rauchmelder</li> <li>smoke: Rauchmelder</li>
<ul> <ul>
<li>0: disarm</li> <li>0: disarm</li>
<li>1: arlarm</li> <li>1: alarm</li>
<li>8: battery arlarm</li> <li>8: battery alarm</li>
<li>64: arlarm sensitivity</li> <li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li> <li>32768: ICC communication failure</li>
</ul> </ul>
<li>gas: Gasmelder</li> <li>gas: Gasmelder</li>
<ul> <ul>
<li>0: disarm</li> <li>0: disarm</li>
<li>1: arlarm</li> <li>1: alarm</li>
<li>2: analog arlarm</li> <li>2: analog alarm</li>
<li>64: arlarm sensitivity</li> <li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li> <li>32768: ICC communication failure</li>
</ul> </ul>
</ul> </ul>
@@ -992,27 +1091,29 @@ sub XiaomiSmartHome_updateAllReadings($)
<ul> <ul>
<li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li> <li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li>
<li>Jedes XiaomiSmartHome Devices sendet alle 60 Minuten 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> <li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim Empfang eines Heartbeat aktualisiert</li>
</ul> </ul>
<br/> <br/>
<b>Set: Gateway</b> <b>Set: Gateway</b>
<ul> <ul>
<li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&oumlglich. Das Passwort findet man in der MI APP</li> <li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&ouml;glich. Das Passwort findet man in der MI APP</li>
<li>RGB(Colorpicker): Einstellen der LED Farbe des Gateways</li> <li>RGB(Colorpicker): Einstellen der LED Farbe des Gateways</li>
<li>PCT(Slider): Einstellen der Helligkeit 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>intervals: Einschalten des Gateways für einen Zeitraum zb. set intervals 07:00-08:00</li>
<li>volume: Einstellen der Lautst&aumlrke des Arlarmtones 1-100, (100 ist sehr laut!)</li> <li>ringtone: Wiedergeben eines Alarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges verändern der Lautst&aumlrke set [GWNAME] ringvol 21 10</li> <li>volume: Einstellen der Lautst&auml;rke des Alarmtones 1-100, (100 ist sehr laut!)</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges ver&auml;ndern der Lautst&auml;rke set [GWNAME] ringvol 21 10</li>
<li>learn: Anlernen neuer Sensoren, nach dem Set an dem neuen Sensor den Button dr&uuml;cken</li>
</ul> </ul>
<br/> <br/>
<b>Set: Devices</b> <b>Set: Devices</b>
<ul> <ul>
<li>motionOffTimer: (nur Bewegungsmelder) <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/>Durch setzen des Parameters ist es m&ouml;glich, dass das Reading des Bewegungsmelder nach 1, 5 oder 10 Sekunden
<br/>automatisch wieder auf off gestellt wird. <br/>automatisch wieder auf off gestellt wird.
<br/>Hintergrund: Der Bewegungsmelder sendet kein selber kein off. <br/>Hintergrund: Der Bewegungsmelder sendet selber kein off.
<br/>Der Bewegungsmelder sendet no_motion nach 120, 180, 300, 600, 1200 Sekunden wenn keine Bewegung festgestellt wurde.</li> <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>Power: (nur Funksteckdose) on off Funksteckdose ein oder ausschalten</li>
<li>ctrl: (nur Funkschalter) on off Funkschalter </li> <li>ctrl: (nur Funkschalter) on off Funkschalter </li>
<li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li> <li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
<li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li> <li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
@@ -1024,5 +1125,3 @@ sub XiaomiSmartHome_updateAllReadings($)
=cut =cut

View File

@@ -25,7 +25,10 @@ package main;
use strict; use strict;
use warnings; use warnings;
my $version = "1.08";
my $version = "1.40";
sub XiaomiSmartHome_Device_updateSReading($); sub XiaomiSmartHome_Device_updateSReading($);
@@ -34,16 +37,21 @@ sub XiaomiSmartHome_Device_updateSReading($);
sub XiaomiSmartHome_Device_Initialize($) sub XiaomiSmartHome_Device_Initialize($)
{ {
my ($hash) = @_; my ($hash) = @_;
$hash->{Match} = ".*magnet.*|.*motion.*|sensor_ht|.*switch.*|plug|cube|86sw1|86sw2|ctrl_neutral1|ctrl_neutral2|rgbw_light|curtain|ctrl_ln1|ctrl_ln2|86plug|natgas|smoke|weather.v1"; $hash->{Match} = ".*magnet.*|.*motion.*|sensor_ht|.*switch.*|plug|.*cube.*|86sw1|86sw2|ctrl_neutral1|ctrl_neutral2|rgbw_light|curtain|ctrl_ln1|ctrl_ln2|86plug|natgas|smoke|weather.v1|sensor_wleak.aq1|vibration|remote.b186acn01|remote.b286acn01|remote.b1acn01";
$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";
$hash->{ParseFn} = "XiaomiSmartHome_Device_Parse"; $hash->{ParseFn} = "XiaomiSmartHome_Device_Parse";
$hash->{FingerprintFn} = "XiaomiSmartHome_Device_Fingerprint";
$hash->{AttrList} = "IODev follow-on-for-timer:1,0 follow-on-timer ". $hash->{AttrList} = "follow-on-for-timer:1,0 follow-on-timer ".
"do_not_notify:1,0 ignore:1,0 dummy:1,0 showtime:1,0 valueFn:textField-long ". "do_not_notify:1,0 ignore:1,0 dummy:1,0 showtime:1,0 valueFn:textField-long ".
$readingFnAttributes ; "rnd_tmp:0,1,2,3 ".
"rnd_hum:0,1,2,3 ".
"rnd_bat:0,1,2,3 ".
"rnd_pres:0,1,2,3 ".
$readingFnAttributes ;
} }
##################################### #####################################
@@ -61,7 +69,7 @@ sub XiaomiSmartHome_Device_Set($@)
my ( $hash, $name, $cmd, @args ) = @_; my ( $hash, $name, $cmd, @args ) = @_;
return "\"set $name\" needs at least one argument" unless(defined($cmd)); return "\"set $name\" needs at least one argument" unless(defined($cmd));
my $setlist = ""; my $setlist = "";
$setlist .= "motionOffTimer:1,5,10 " if ($hash->{MODEL} =~ /motion/); $setlist .= "motionOffTimer:1,5,10 " if ($hash->{MODEL} =~ /motion/);
#$setlist = "open:noArg close:noArg " if ($hash->{MODEL} =~ /magnet/); #$setlist = "open:noArg close:noArg " if ($hash->{MODEL} =~ /magnet/);
@@ -72,7 +80,7 @@ sub XiaomiSmartHome_Device_Set($@)
$setlist .= "channel_0:on,off channel_1:on,off " if ($hash->{MODEL} eq 'ctrl_neutral2'); $setlist .= "channel_0:on,off channel_1:on,off " if ($hash->{MODEL} eq 'ctrl_neutral2');
$setlist .= "channel_0:on,off channel_1:on,off " if ($hash->{MODEL} eq 'ctrl_ln2'); $setlist .= "channel_0:on,off channel_1:on,off " if ($hash->{MODEL} eq 'ctrl_ln2');
$setlist .= "status:open,close,stop,auto level:slider,1,1,100 " if ($hash->{MODEL} eq 'curtain'); $setlist .= "status:open,close,stop,auto level:slider,1,1,100 " if ($hash->{MODEL} eq 'curtain');
if($cmd eq "power") if($cmd eq "power")
{ {
if($args[0] eq "on") if($args[0] eq "on")
@@ -144,22 +152,22 @@ sub XiaomiSmartHome_Device_Set($@)
{ {
IOWrite($hash,"status","close",$hash) ; IOWrite($hash,"status","close",$hash) ;
return; return;
} }
elsif($args[0] eq "stop") elsif($args[0] eq "stop")
{ {
IOWrite($hash,"status","stop",$hash) ; IOWrite($hash,"status","stop",$hash) ;
return; return;
} }
elsif($args[0] eq "auto") elsif($args[0] eq "auto")
{ {
IOWrite($hash,"status","auto",$hash) ; IOWrite($hash,"status","auto",$hash) ;
return; return;
} }
} }
if($cmd eq "level") if($cmd eq "level")
{ {
IOWrite($hash,"level", $args[0] ,$hash) ; IOWrite($hash,"level", $args[0] ,$hash) ;
return; return;
} }
# if($cmd eq "open") # if($cmd eq "open")
# { # {
@@ -171,7 +179,7 @@ sub XiaomiSmartHome_Device_Set($@)
readingsSingleUpdate($hash, "motionOffTimer", "$args[0]", 1 );; readingsSingleUpdate($hash, "motionOffTimer", "$args[0]", 1 );;
return; return;
} }
return "Unknown argument $cmd, choose one of $setlist"; return "Unknown argument $cmd, choose one of $setlist";
} }
@@ -190,6 +198,12 @@ sub XiaomiSmartHome_Device_on_timeout($){
##################################### #####################################
sub XiaomiSmartHome_Device_Read($$$){ sub XiaomiSmartHome_Device_Read($$$){
my ($hash, $msg, $name) = @_; my ($hash, $msg, $name) = @_;
my $XMIround_tmp = AttrVal( $hash->{NAME}, "rnd_tmp", "2" );
my $XMIround_hum = AttrVal( $hash->{NAME}, "rnd_hum", "2" );
my $XMIround_bat = AttrVal( $hash->{NAME}, "rnd_bat", "1" );
my $XMIround_pres = AttrVal( $hash->{NAME}, "rnd_pres", "2" );
my $decoded = eval{decode_json($msg)}; my $decoded = eval{decode_json($msg)};
if ($@) { if ($@) {
Log3 $name, 1, "$name: DEV_Read> Error while request: $@"; Log3 $name, 1, "$name: DEV_Read> Error while request: $@";
@@ -197,6 +211,7 @@ sub XiaomiSmartHome_Device_Read($$$){
} }
my $sid = $decoded->{'sid'}; my $sid = $decoded->{'sid'};
my $model = $decoded->{'model'}; my $model = $decoded->{'model'};
my $cmd = $decoded->{'cmd'};
Log3 $name, 5, "$name: DEV_Read> SID: " . $hash->{SID} . " " . $hash->{TYPE}; Log3 $name, 5, "$name: DEV_Read> SID: " . $hash->{SID} . " " . $hash->{TYPE};
my $data = eval{decode_json($decoded->{data})}; my $data = eval{decode_json($decoded->{data})};
if ($@) { if ($@) {
@@ -204,128 +219,164 @@ sub XiaomiSmartHome_Device_Read($$$){
return; return;
} }
readingsBeginUpdate( $hash ); readingsBeginUpdate( $hash );
if (defined $data->{status}){ if (defined $data->{status}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Status: " . $data->{status}; Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Status: " . $data->{status};
readingsBulkUpdate($hash, "state", "$data->{status}", 1 ); readingsBulkUpdate($hash, "state", "$data->{status}", 1 );
if ($data->{status} eq 'motion' && $hash->{MODEL} =~ /motion/){ if ($data->{status} eq 'motion' && $hash->{MODEL} =~ /motion/){
readingsBulkUpdate($hash, "no_motion", "0", 1 ); readingsBulkUpdate($hash, "no_motion", "0", 1 );
} }
if ($data->{status} eq 'close' && $hash->{MODEL} =~ /magnet/){ if ($data->{status} eq 'close' && $hash->{MODEL} =~ /magnet/){
readingsBulkUpdate($hash, "no_close", "0", 1 ); readingsBulkUpdate($hash, "no_close", "0", 1 );
}
} }
}
if (defined $data->{no_motion}){ if (defined $data->{no_motion}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " NO_motion: " . $data->{no_motion}; Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " NO_motion: " . $data->{no_motion};
readingsBulkUpdate($hash, "no_motion", "$data->{no_motion}", 1 ); readingsBulkUpdate($hash, "no_motion", "$data->{no_motion}", 1 );
} }
if (defined $data->{no_close}){ if (defined $data->{no_close}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " NO_close: " . $data->{no_close}; Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " NO_close: " . $data->{no_close};
readingsBulkUpdate($hash, "no_close", "$data->{no_close}", 1 ); readingsBulkUpdate($hash, "no_close", "$data->{no_close}", 1 );
} }
if (defined $data->{voltage}){ if (defined $data->{voltage}){
my $bat = ($data->{voltage}/1000); my $bat = ($data->{voltage}/1000);
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Voltage: " . $data->{voltage}; Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Voltage: " . $data->{voltage};
readingsBulkUpdate($hash, "battery", $bat, 1 ); if ($bat < 2.2) {
} readingsBulkUpdate($hash, "batteryState", "low", 1 );
if (defined $data->{temperature}){ }
my $temp = $data->{temperature}; else {
$temp =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g; readingsBulkUpdate($hash, "batteryState", "ok", 1 )
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Temperature: " . $temp; }
readingsBulkUpdate($hash, "temperature", "$temp", 1 ); $bat = XiaomiSmartHome_round($bat, $XMIround_bat, $name );
} readingsBulkUpdate($hash, "batteryVoltage", $bat, 1 );
if (defined $data->{humidity}){ }
my $hum = $data->{humidity}; if (defined $data->{temperature}){
$hum =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g; if ($data->{temperature} ne "10000"){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Humidity: " . $hum; my $temp = sprintf( "%#.4d", $data->{temperature});
readingsBulkUpdate($hash, "humidity", "$hum", 1 ); $temp =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
} $temp = XiaomiSmartHome_round($temp, $XMIround_tmp, $name );
if (defined $data->{pressure}){ Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Temperature: " . $temp . " Round: " . $XMIround_tmp;
my $pres = $data->{pressure}; readingsBulkUpdate($hash, "temperature", "$temp", 1 );
$pres =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1./g; }
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Pressure: " . $pres; }
readingsBulkUpdate($hash, "pressure", "$pres", 1 ); if (defined $data->{humidity}){
} if ($data->{humidity} ne "0"){
if (defined $data->{lux}){ my $hum = $data->{humidity};
my $lux = $data->{lux}; $hum =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g;
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Illuminance: " . $lux; $hum = XiaomiSmartHome_round($hum, $XMIround_hum, $name );
readingsBulkUpdate($hash, "lux", "$lux", 1 ); Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Humidity: " . $hum . " Round: " . $XMIround_hum;
} readingsBulkUpdate($hash, "humidity", "$hum", 1 );
#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}; if (defined $data->{pressure}){
readingsBulkUpdate($hash, "channel_0", "$data->{channel_0}", 1 ); if ($data->{pressure} ne "0"){
} my $pres = $data->{pressure};
if (defined $data->{channel_1}){ $pres =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_1: " . $data->{channel_1}; $pres = XiaomiSmartHome_round($pres, $XMIround_pres, $name );
readingsBulkUpdate($hash, "channel_1", "$data->{channel_1}", 1 ); Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Pressure: " . $pres . " Round: " . $XMIround_pres;
} readingsBulkUpdate($hash, "pressure", "$pres", 1 );
#86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 end }
#plug & 86plug start }
if (defined $data->{load_voltage}){ if (defined $data->{lux}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Voltage: " . $data->{load_voltage}; my $lux = $data->{lux};
readingsBulkUpdate($hash, "LOAD_Voltage", "$data->{load_voltage}", 1 ); Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Illuminance: " . $lux;
} readingsBulkUpdate($hash, "lux", "$lux", 1 );
if (defined $data->{load_power}){ }
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Power: " . $data->{load_power}; #86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 start
readingsBulkUpdate($hash, "LOAD_Power", "$data->{load_power}", 1 ); if (defined $data->{channel_0}){
} Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_0: " . $data->{channel_0};
if (defined $data->{power_consumed}){ readingsBulkUpdate($hash, "channel_0", "$data->{channel_0}", 1 );
Log3 $name, 3, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " POWER_Consumed: " . $data->{power_consumed}; }
readingsBulkUpdate($hash, "POWER_Consumed", "$data->{power_consumed}", 1 ); if (defined $data->{channel_1}){
} Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_1: " . $data->{channel_1};
if (defined $data->{inuse}){ readingsBulkUpdate($hash, "channel_1", "$data->{channel_1}", 1 );
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " InUse: " . $data->{inuse}; }
readingsBulkUpdate($hash, "inuse", "$data->{inuse}", 1 ); if (defined $data->{dual_channel}){
} Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Dual_Channel: " . $data->{dual_channel};
#plug & 86plug end readingsBulkUpdate($hash, "dual_channel", "$data->{dual_channel}", 1 );
#rgbw_light start }
if (defined $data->{level}){ #86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 end
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Level: " . $data->{level}; #plug & 86plug start
readingsBulkUpdate($hash, "level", "$data->{level}", 1 ); if (defined $data->{load_voltage}){
} Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Voltage: " . $data->{load_voltage};
if (defined $data->{hue}){ readingsBulkUpdate($hash, "LOAD_Voltage", "$data->{load_voltage}", 1 );
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->{load_power}){
} Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Power: " . $data->{load_power};
if (defined $data->{saturation}){ readingsBulkUpdate($hash, "LOAD_Power", "$data->{load_power}", 1 );
Log3 $name, 3, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Saturation: " . $data->{saturation}; }
readingsBulkUpdate($hash, "saturation", "$data->{saturation}", 1 ); if (defined $data->{power_consumed}){
} Log3 $name, 4, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " POWER_Consumed: " . $data->{power_consumed};
if (defined $data->{color_temperature}){ readingsBulkUpdate($hash, "POWER_Consumed", "$data->{power_consumed}", 1 );
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->{inuse}){
} Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " InUse: " . $data->{inuse};
if (defined $data->{x}){ readingsBulkUpdate($hash, "inuse", "$data->{inuse}", 1 );
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " X: " . $data->{x}; }
readingsBulkUpdate($hash, "x", "$data->{x}", 1 ); #plug & 86plug end
} #rgbw_light start
if (defined $data->{y}){ if (defined $data->{level}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Y: " . $data->{y}; Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Level: " . $data->{level};
readingsBulkUpdate($hash, "y", "$data->{y}", 1 ); readingsBulkUpdate($hash, "level", "$data->{level}", 1 );
} }
#rgbw_light end if (defined $data->{hue}){
#cube start Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Hue: " . $data->{hue};
if (defined $data->{rotate}){ readingsBulkUpdate($hash, "hue", "$data->{hue}", 1 );
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Rotate: " . $data->{rotate}; }
readingsBulkUpdate($hash, "rotate", "$data->{rotate}", 1 ); if (defined $data->{saturation}){
readingsBulkUpdate($hash, "state", "rotate", 1 ); Log3 $name, 4, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Saturation: " . $data->{saturation};
} readingsBulkUpdate($hash, "saturation", "$data->{saturation}", 1 );
#cube end }
#smoke & natgast start if (defined $data->{color_temperature}){
if (defined $data->{alarm}){ Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Color_temperature: " . $data->{color_temperature};
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Rotate: " . $data->{arlarm}; readingsBulkUpdate($hash, "color_temperature", "$data->{color_temperature}", 1 );
readingsBulkUpdate($hash, "arlarm", "$data->{arlarm}", 1 ); }
} if (defined $data->{x}){
#smoke & natgast end Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " X: " . $data->{x};
#curtain start readingsBulkUpdate($hash, "x", "$data->{x}", 1 );
if (defined $data->{curtain_level}){ }
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Rotate: " . $data->{curtain_level}; if (defined $data->{y}){
readingsBulkUpdate($hash, "arlarm", "$data->{curtain_level}", 1 ); Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Y: " . $data->{y};
} readingsBulkUpdate($hash, "y", "$data->{y}", 1 );
#curtain end }
if ($decoded->{'cmd'} eq 'heartbeat'){ #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};
readingsBulkUpdate($hash, "rotate", "$data->{rotate}", 1 );
readingsBulkUpdate($hash, "state", "rotate", 1 );
}
#cube end
#smoke & natgast start
if (defined $data->{alarm}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Alarm: " . $data->{alarm};
readingsBulkUpdate($hash, "alarm", "$data->{alarm}", 1 );
}
if (defined $data->{density}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Density: " . $data->{density};
readingsBulkUpdate($hash, "density", "$data->{density}", 1 );
}
#smoke & natgast end
#curtain start
if (defined $data->{curtain_level}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Curtain: " . $data->{curtain_level};
readingsBulkUpdate($hash, "alarm", "$data->{curtain_level}", 1 );
}
#curtain end
#vibration Start
if (defined $data->{'coordination'}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Coordination: " . $data->{coordination};
readingsBulkUpdate($hash, "coordination", "$data->{coordination}", 1 );
}
if (defined $data->{'final_tilt_angle'}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Final tilt angle: " . $data->{final_tilt_angle};
readingsBulkUpdate($hash, "final_tilt_angle", "$data->{final_tilt_angle}", 1 );
}
#vibration end
if ($decoded->{'cmd'} eq 'heartbeat'){
readingsBulkUpdate($hash, 'heartbeat', $decoded->{'sid'} , 1 ); readingsBulkUpdate($hash, 'heartbeat', $decoded->{'sid'} , 1 );
} }
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
XiaomiSmartHome_Device_update($hash); XiaomiSmartHome_Device_update($hash);
return $hash->{NAME}; return $hash->{NAME};
@@ -343,15 +394,17 @@ sub XiaomiSmartHome_Device_Parse($$) {
} }
my $sid = $decoded->{'sid'}; my $sid = $decoded->{'sid'};
my $model = $decoded->{'model'}; my $model = $decoded->{'model'};
if (my $hash = $modules{XiaomiSmartHome_Device}{defptr}{$sid}) if ($modules{XiaomiSmartHome_Device}{defptr}{$sid}{IODev}->{NAME})
{ {
Log3 $name, 4, "$name: DEV_Parse> IS DEFINED " . $model . " : " .$sid; my $hash = $modules{XiaomiSmartHome_Device}{defptr}{$sid}->{IODev};
Log3 $name, 5, "$name: DEV_Parse> IS DEFINED " . $model . " : " . $sid . " " . $modules{XiaomiSmartHome_Device}{defptr}{$sid}->{IODev};
$hash = $modules{XiaomiSmartHome_Device}{defptr}{$sid};
XiaomiSmartHome_Device_Read($hash, $msg, $name); XiaomiSmartHome_Device_Read($hash, $msg, $name);
} }
else else
{ {
Log3 $name, 4, "$name: DEV_Parse> UNDEFINED " . $model . " : " .$sid; Log3 $name, 1, "$name: DEV_Parse> UNDEFINED " . $model . " : " .$sid;
return "UNDEFINED XMI_$sid XiaomiSmartHome_Device $sid $model $name"; return "UNDEFINED XMI_$sid XiaomiSmartHome_Device $sid $model $name";
} }
} }
@@ -369,17 +422,22 @@ sub XiaomiSmartHome_Device_update($){
my $LASTCMD = ReadingsVal($name,"lastCmd",undef); my $LASTCMD = ReadingsVal($name,"lastCmd",undef);
my $value_fn = eval $value_fn; my $value_fn = eval $value_fn;
Log3 $name, 3, $name .": DEV_Update valueFn: ". $@ if($@); Log3 $name, 4, $name .": DEV_Update valueFn: ". $@ if($@);
return undef if( !defined($value_fn) ); return undef if( !defined($value_fn) );
} }
if( $model =~ /motion/) { if( $model =~ /motion/) {
XiaomiSmartHome_Device_mot($hash, $hash->{READINGS}{motionOffTimer}{VAL}) if( $hash->{READINGS}{motionOffTimer}); XiaomiSmartHome_Device_mot($hash, $hash->{READINGS}{motionOffTimer}{VAL}) if( $hash->{READINGS}{motionOffTimer});
} }
# Update delete old reading Voltage # Update delete old reading voltage & batterystate
CommandDeleteReading( undef, "$name voltage" ) if(defined(ReadingsVal($name,"voltage",undef))); CommandDeleteReading( undef, "$name voltage" ) if(defined(ReadingsVal($name,"voltage",undef)));
CommandDeleteReading( undef, "$name batterystate" ) if(defined(ReadingsVal($name,"batterystate",undef)));
CommandDeleteReading( undef, "$name round" ) if(defined(ReadingsVal($name,"round",undef)));
CommandDeleteReading( undef, "$name battery_level" ) if(defined(ReadingsVal($name,"battery_level",undef)));
CommandDeleteReading( undef, "$name battery" ) if(defined(ReadingsVal($name,"battery",undef)));
CommandDeleteReading( undef, "$name batteryLevel" ) if(defined(ReadingsVal($name,"batteryLevel",undef)));
} }
##################################### #####################################
sub XiaomiSmartHome_Device_Define($$) { sub XiaomiSmartHome_Device_Define($$) {
my ($hash, $def) = @_; my ($hash, $def) = @_;
@@ -392,7 +450,8 @@ sub XiaomiSmartHome_Device_Define($$) {
$hash->{STATE} = 'initialized'; $hash->{STATE} = 'initialized';
$modules{XiaomiSmartHome_Device}{defptr}{$sid} = $hash; $modules{XiaomiSmartHome_Device}{defptr}{$sid} = $hash;
AssignIoPort($hash,$iodev); AssignIoPort($hash,$iodev);
my $room = $attr{$iodev}{room};
if(defined($hash->{IODev}->{NAME})) { if(defined($hash->{IODev}->{NAME})) {
my $IOname = $hash->{IODev}->{NAME}; my $IOname = $hash->{IODev}->{NAME};
Log3 $name, 4, $IOname . ": DEV_Define> " .$name. ": " . $type . " I/O device is " . $hash->{IODev}->{NAME}; Log3 $name, 4, $IOname . ": DEV_Define> " .$name. ": " . $type . " I/O device is " . $hash->{IODev}->{NAME};
@@ -400,15 +459,17 @@ sub XiaomiSmartHome_Device_Define($$) {
Log3 $name, 1, "$name DEV_Define> $type - no I/O device"; Log3 $name, 1, "$name DEV_Define> $type - no I/O device";
} }
$iodev = $hash->{IODev}->{NAME}; $iodev = $hash->{IODev}->{NAME};
my $d = $modules{XiaomiSmartHome_Device}{defptr}{$name}; my $d = $modules{XiaomiSmartHome_Device}{defptr}{$sid};
return "XiaomiSmartHome device $hash->{SID} on XiaomiSmartHome $iodev already defined as $d->{NAME}." if( defined($d) && $d->{IODev} == $hash->{IODev} && $d->{NAME} ne $name ); return "XiaomiSmartHome device $hash->{SID} on XiaomiSmartHome $iodev already defined as $d->{SID}." if( defined($d) && $d->{IODev} == $hash->{IODev} && $d->{SID} ne $sid );
Log3 $name, 4, $iodev . ": DEV_Define> " . $name . ": defined as ". $hash->{MODEL}; Log3 $name, 4, $iodev . ": DEV_Define> " . $name . ": defined as ". $hash->{MODEL};
$attr{$name}{room} = "MiSmartHome" if( !defined( $attr{$name}{room} ) ); $attr{$name}{room} = $room if( !defined( $attr{$name}{room} ) );
if( $type =~ /motion/) { if( $type =~ /motion/) {
readingsSingleUpdate($hash, "state", "motion", 1 ) if( !defined( $attr{$name}{devStateIcon} ));
$attr{$name}{devStateIcon} = 'motion:motion_detector@red off:motion_detector@green no_motion:motion_detector@green' if( !defined( $attr{$name}{devStateIcon} ) ); $attr{$name}{devStateIcon} = 'motion:motion_detector@red off:motion_detector@green no_motion:motion_detector@green' if( !defined( $attr{$name}{devStateIcon} ) );
} }
elsif ( $type =~ /magnet/) { elsif ( $type =~ /magnet/) {
$attr{$name}{devStateIcon} = 'open:fts_door_open@red close:fts_door@green' if( !defined( $attr{$name}{devStateIcon} ) ); $attr{$name}{devStateIcon} = 'open:fts_door_open@red close:fts_door@green' if( !defined( $attr{$name}{devStateIcon} ) );
@@ -418,20 +479,28 @@ sub XiaomiSmartHome_Device_Define($$) {
} }
elsif ( $type eq 'weather.v1') { elsif ( $type eq 'weather.v1') {
$attr{$name}{stateFormat} = 'temperature °C, humidity %, pressure kPa' if( !defined( $attr{$name}{stateFormat} ) ); $attr{$name}{stateFormat} = 'temperature °C, humidity %, pressure kPa' if( !defined( $attr{$name}{stateFormat} ) );
} }
if( $init_done ) { if( $init_done ) {
InternalTimer(gettimeofday() + 2, "XiaomiSmartHome_Device_updateSReading", $hash, 0 ); InternalTimer(gettimeofday() + 2, "XiaomiSmartHome_Device_updateSReading", $hash, 0 );
Log3 $name, 4, $iodev . ": DEV_Define> " . $name . " Init Done set InternalTimer for Update"; Log3 $name, 4, $iodev . ": DEV_Define> " . $name . " Init Done set InternalTimer for Update";
} }
return undef; return undef;
} }
#####################################
sub XiaomiSmartHome_Device_Fingerprint($$){
my ($io_name, $msg) = @_;
Log3 $io_name, 4, "$io_name: Fingerprint> for $msg";
return ($io_name, $msg );
}
##################################### #####################################
sub XiaomiSmartHome_Device_updateSReading($) { sub XiaomiSmartHome_Device_updateSReading($) {
my $hash = shift; my $hash = shift;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
Log3 $name, 3, "$name: DEV_updateSReading> for $hash->{SID}"; Log3 $name, 4, "$name: DEV_updateSReading> for $hash->{SID}";
RemoveInternalTimer($hash,'XiaomiSmartHome_Device_updateSReading'); RemoveInternalTimer($hash,'XiaomiSmartHome_Device_updateSReading');
IOWrite($hash,'read',"$hash->{SID}"); IOWrite($hash,'read',"$hash->{SID}");
} }
@@ -440,20 +509,39 @@ sub XiaomiSmartHome_Device_updateSReading($) {
##################################### #####################################
sub XiaomiSmartHome_Device_Undef($) sub XiaomiSmartHome_Device_Undef($)
{ {
my ($hash, $arg) = @_; my ($hash, $arg) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $iodev = $hash->{IODev}->{NAME}; my $iodev = $hash->{IODev}->{NAME};
my $sid = $hash->{SID};
RemoveInternalTimer($hash); RemoveInternalTimer($hash);
delete($modules{XiaomiSmartHome_Device}{defptr}{$hash->{SID}}); Log3 $name, 1, "$iodev: DEV_Undef> ". $hash->{SID} . " > " . $modules{XiaomiSmartHome_Device}{defptr}{$hash->{SID}} . " > " . $sid ." > " . $modules{XiaomiSmartHome_Device}{defptr}{$sid};
Log3 $name, 3, "$iodev: DEV_Undef> $name - device deleted"; my $error = delete ($modules{XiaomiSmartHome_Device}{defptr}{$sid});
Log3 $name, 1, "$iodev: DEV_Undef> $name - device deleted " . $error;
return undef; return undef;
} }
#####################################
sub XiaomiSmartHome_round {
my ($n, $p, $name) = @_;
Log3 $name, 5, "$name: DEV_Round>" . " Value: " . $n . " points: " . $p;
my $sign = ($n > 0) ? 1 : -1;
$p ||= 0;
$n *= 10 ** $p;
$n = int($n + .5 * $sign);
my $res = sprintf( "%." . $p . "f", $n / 10**$p);
Log3 $name, 5, "$name: DEV_Round>" . " Result_value: " . $res;
return $res;
}
1; 1;
=pod =pod
=item device =item device
=item summary Module to control XiaomiSmartHome Gateway =item summary Module to control XiaomiSmartHome Gateway
=item summary_DE Modul zum steuern des XiaomiSmartHome Gateway
=begin html =begin html
@@ -461,7 +549,7 @@ sub XiaomiSmartHome_Device_Undef($)
<a name="XiaomiSmartHome_Device"></a> <a name="XiaomiSmartHome_Device"></a>
<h3>XiaomiSmartHome</h3> <h3>XiaomiSmartHome</h3>
<ul> <ul>
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors. <i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome"></a>
<br/> <br/>
<b>Prerequisite</b> <b>Prerequisite</b>
@@ -492,15 +580,35 @@ sub XiaomiSmartHome_Device_Undef($)
<ul> <ul>
<li>magnet: Window/Door magnetic sensor</li> <li>magnet: Window/Door magnetic sensor</li>
<li>motion: Human body motion sensor</li> <li>motion: Human body motion sensor</li>
<li>sensor_ht: Temperatur and humidity sensor</li> <li>sensor_motion.aq2: Aqara Human body motion sensor with lux readings</li>
<li>sensor_ht: Temperature and humidity sensor</li>
<li>weather.v1: Aqara Temperature, pressure and humidity sensor</li>
<li>switch: Wireless sensor switch</li> <li>switch: Wireless sensor switch</li>
<li>plug: Smart socket</li> <li>plug & 86plug: Smart socket</li>
<li>cube: Cube sensor</li> <li>cube: Cube sensor</li>
<li>86sw1: Wireless switch single</li> <li>86sw1: Wireless switch single</li>
<li>86sw2: Wireless switch double</li> <li>86sw2: Wireless switch double</li>
<li>ctrl_neutral1: Single bond ignition switch</li> <li>ctrl_neutral1: Single bond ignition switch</li>
<li>ctrl_neutral2: Double bond ignition switch</li> <li>ctrl_neutral2: Double bond ignition switch</li>
<li>rgbw_light: Smart lights (report only)</li> <li>rgbw_light: Smart lights (report only)</li>
<li>curtain: Curtain (Control only if device has reporte curtain_level)</li>
<li>water: water detector</li>
<li>smoke: smoke alarm detector</li>
<ul>
<li>0: disarm</li>
<li>1: alarm</li>
<li>8: battery alarm</li>
<li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li>
</ul>
<li>gas: gas alarm detector</li>
<ul>
<li>0: disarm</li>
<li>1: alarm</li>
<li>2: analog alarm</li>
<li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li>
</ul>
</ul> </ul>
<br/> <br/>
<b>Heartbeat</b> <b>Heartbeat</b>
@@ -515,16 +623,18 @@ sub XiaomiSmartHome_Device_Undef($)
<li>password: without password no write to the gateway is possible. Use the MI APP to find the password</li> <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>RGB(Colorpicker): set the color</li>
<li>PCT(Slider): set the brightness in percent</li> <li>PCT(Slider): set the brightness in percent</li>
<li>intervals: set the gateway to on for an time eg. set intervals 07:00-08:00</li>
<li>ringtone: set the ringtone 0-8,13,21-29,10001-.. | 10000 = off</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>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> <li>ringvol: set ringtone and volume in on step e.g. set [GWNAME] ringvol 21 10</li>
<li>learn: set the gateway in learningmode to learn new sensors now push the button from the new sensor</li>
</ul> </ul>
<br/> <br/>
<b>Set: Devices</b> <b>Set: Devices</b>
<ul> <ul>
<li>motionOffTimer: (only motionsensor) <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/>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/>the motion sensors will automatically set to off. MotionOffTimer is set to 5 by default.
<br/>Background: The motionsensors does not send off immediately. <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> <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>Power: (only smart soket) on off switch a plug on or off</li>
@@ -538,15 +648,15 @@ sub XiaomiSmartHome_Device_Undef($)
=begin html_DE =begin html_DE
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome_Device"></a>
<h3>XiaomiSmartHome</h3> <h3>XiaomiSmartHome</h3>
<ul> <ul>
<i>XiaomiSmartHome</i> Steuern des XiaomiSmartHome Gateway und deren verbundener Sensoren. <i>XiaomiSmartHome</i> Steuern des XiaomiSmartHome Gateway und deren verbundener Sensoren.
<a name="XiaomiSmartHome"></a> <a name="XiaomiSmartHome"></a>
<br/> <br/>
<b>Vorraussetzungen</b> <b>Voraussetzungen</b>
<ul> <ul>
<li>Diese Pakete m&uumlssen installiert sein: apt-get install libio-socket-multicast-perl libjson-perl libcrypt-cbc-perl</li> <li>Diese Pakete m&uuml;ssen installiert sein: apt-get install libio-socket-multicast-perl libjson-perl libcrypt-cbc-perl</li>
<li>Und mit CPAN: cpan Crypt::Cipher::AES</li> <li>Und mit CPAN: cpan Crypt::Cipher::AES</li>
</ul> </ul>
<br/> <br/>
@@ -558,11 +668,11 @@ sub XiaomiSmartHome_Device_Undef($)
<br><br> <br><br>
</ul> </ul>
<br/> <br/>
<b>Entwicklermodus am Gatway setzen!</b> <b>Entwicklermodus am Gateway setzen!</b>
<ul> <ul>
<p>Ohne Entwicklermodus ist keine Komunikation mit dem Gateway m&oumlglich. <p>Ohne Entwicklermodus ist keine Kommunikation mit dem Gateway m&ouml;glich.
<br/>Zum setzen des Entwicklermoduses braucht man ein android oder ios Ger&aumlt mit installierter MI APP. <br/>Zum setzen des Entwicklermodusses braucht man ein android oder ios Ger&auml;t mit installierter MI APP.
<br/>Um das versteckte Men&uuml zu &oumlffnen muss man mehrmals auf die Versionsnummer der MI APP klicken. <br/>Um das versteckte Men&uuml; zu &ouml;ffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<br/>Hier finden Sie eine Anleitung mit Bildern. <br/>Hier finden Sie eine Anleitung mit Bildern.
<br/>Android -> https://louiszl.gitbooks.io/lumi-gateway-local-api/content/device_discover.html <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/>IOS -> https://github.com/fooxy/homeassistant-aqara/wiki/Enable-dev-mode
@@ -571,46 +681,64 @@ sub XiaomiSmartHome_Device_Undef($)
<br/> <br/>
<b>Unterstütze Sensoren</b> <b>Unterstütze Sensoren</b>
<ul> <ul>
<li>magnet: Magnetischer Fenster/T&uumlr Sensor</li> <li>magnet: Magnetischer Fenster/T&uuml;r Sensor</li>
<li>motion: Bewegungsmelder</li> <li>motion: Bewegungsmelder</li>
<li>sensor_motion.aq2: Aqara Bewegungsmelder mit lux-Messung</li>
<li>sensor_ht: Temperatur und Luftdruck</li> <li>sensor_ht: Temperatur und Luftdruck</li>
<li>weather.v1: Aqara Temperatur, Luftdruck und Feuchtigkeit</li>
<li>switch: Funkschalter</li> <li>switch: Funkschalter</li>
<li>plug: Schaltbare Funksteckdose</li> <li>plug & 86plug: Schaltbare Funksteckdose</li>
<li>cube: W&uumlrfel Sensor</li> <li>cube: W&uuml;rfel Sensor</li>
<li>86sw1: Einfacher Wandfunkschalter</li> <li>86sw1: Einfacher Wandfunkschalter</li>
<li>86sw2: Wandfunkschalter doppelt</li> <li>86sw2: Wandfunkschalter doppelt</li>
<li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li> <li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li>
<li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li> <li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li>
<li>rgbw_light: RBGW Lampe (nur Anzeige)</li> <li>rgbw_light: RBGW Lampe (nur Anzeige)</li>
<li>curtain: Vorhangmotor (ohne dass das Device den curtain_level gemeldet hat ist ein Steuern nicht &ouml;glich)</li>
<li>water: Wasser Sensor</li>
<li>smoke: Rauchmelder</li>
<ul>
<li>0: disarm</li>
<li>1: alarm</li>
<li>8: battery alarm</li>
<li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li>
</ul>
<li>gas: Gasmelder</li>
<ul>
<li>0: disarm</li>
<li>1: alarm</li>
<li>2: analog alarm</li>
<li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li>
</ul>
</ul> </ul>
<br/> <br/>
<b>Heartbeat</b> <b>Heartbeat</b>
<ul> <ul>
<li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li> <li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li>
<li>Jedes XiaomiSmartHome Devices sendet alle 60 Minuten 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> <li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim Empfang eines Heartbeat aktualisiert</li>
</ul> </ul>
<br/> <br/>
<b>Set: Gateway</b> <b>Set: Gateway</b>
<ul> <ul>
<li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&oumlglich. Das Passwort findet man in der MI APP</li> <li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&ouml;glich. Das Passwort findet man in der MI APP</li>
<li>RGB(Colorpicker): Einstellen der LED Farbe des Gateways</li> <li>RGB(Colorpicker): Einstellen der LED Farbe des Gateways</li>
<li>PCT(Slider): Einstellen der Helligkeit 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>intervals: Einschalten des Gateways für einen Zeitraum zb. set intervals 07:00-08:00</li>
<li>volume: Einstellen der Lautst&aumlrke des Arlarmtones 1-100, (100 ist sehr laut!)</li> <li>ringtone: Wiedergeben eines Alarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges verändern der Lautst&aumlrke set [GWNAME] ringvol 21 10</li> <li>volume: Einstellen der Lautst&auml;rke des Alarmtones 1-100, (100 ist sehr laut!)</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges ver&auml;ndern der Lautst&auml;rke set [GWNAME] ringvol 21 10</li>
<li>learn: Anlernen neuer Sensoren, nach dem Set an dem neuen Sensor den Button dr&uuml;cken</li>
</ul> </ul>
<br/> <br/>
<b>Set: Devices</b> <b>Set: Devices</b>
<ul> <ul>
<li>motionOffTimer: (nur Bewegungsmelder) <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/>Durch setzen des Parameters ist es m&ouml;glich, dass das Reading des Bewegungsmelder nach 1, 5 oder 10 Sekunden
<br/>automatisch wieder auf off gestellt wird. Standardmäßig ist dieser Wert auf 5 gestellt, sodass der Sensor alle 5 Sekunden auf eine erneute Bewegung reagiert. <br/>automatisch wieder auf off gestellt wird.
<br/>Hintergrund: Der Bewegungsmelder sendet kein selber kein off. <br/>Hintergrund: Der Bewegungsmelder sendet selber kein off.
<br/>Der Bewegungsmelder sendet no_motion nach 120, 180, 300, 600, 1200 Sekunden wenn keine Bewegung festgestellt wurde.</li> <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>Power: (nur Funksteckdose) on off Funksteckdose ein oder ausschalten</li>
<li>ctrl: (nur Funkschalter) on off Funkschalter </li> <li>ctrl: (nur Funkschalter) on off Funkschalter </li>
<li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li> <li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
<li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li> <li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
@@ -619,4 +747,5 @@ sub XiaomiSmartHome_Device_Undef($)
=end html_DE =end html_DE
=cut =cut

View File

@@ -1,6 +1,43 @@
# fhem-XiaomiSmartHome Gateway # fhem-XiaomiSmartHome Gateway
With this module, the XiaomiGateway is bound to Fhem. The module listens for multicast messages from the gateway. Currently only for the sensortype Magnet, Motion, Temperature-Humidity, Switch, Cube, Curtain, Smoke and Gas. With this module, the Xiaomi Smarthome Gateway is bound to FHEM. The module listens for multicast messages from the gateway.
Changing and switching the led of the gateway and changing ringtone and volume of the gateway is also possible Changing and switching the LED from the gateway and changing ringtone and volume of the gateway is also possible
* Please read the Wiki !! you need to install some Perl modules. * Please read the Wiki !! you need to install some Perl modules.
* https://github.com/T0RST3N/fhem-XiaomiSmartHome/wiki * https://github.com/T0RST3N/fhem-XiaomiSmartHome/wiki
# Supported Sensors
* magnet: Window/Door magnetic sensor
* motion: Human body motion sensor
* sensor_motion.aq2: Aqara Human body motion sensor with lux readings
* sensor_ht: Temperature and humidity sensor
* weather.v1: Aqara Temperature, pressure and humidity sensor
* switch: Wireless sensor switch
* plug & 86plug: Smart socket
* cube: Cube sensor
* 86sw1: Wireless switch single
* 86sw2: Wireless switch double
* ctrl_neutral1: Single bond ignition switch
* ctrl_neutral2: Double bond ignition switch
* rgbw_light: Smart lights (report only)
* curtain: Curtain (Control only if device has reporte curtain_level)
* wleak: Watersensor
* smoke: smoke alarm detector
* * 0: disarm
* * 1: arlarm
* * 8: battery arlarm
* * 64: arlarm sensitivity
* * 32768: ICC communication failure
* gas: gas alarm detector
* * 0: disarm
* * 1: arlarm
* * 2: analog arlarm
* * 64: arlarm sensitivity
* * 32768: ICC communication failure
* vibration: Detect vibration
# A BIG ThankYOU to my Supporters
* StefanB from Coburg
* Hendrik S
* Karsten B
* Juergen K
* FHEM-Wohnung

View File

@@ -1,2 +1,2 @@
UPD 2017-07-17_17:26:57 36127 FHEM/71_XiaomiSmartHome.pm UPD 2019-04-26_11:40:51 40758 FHEM/71_XiaomiSmartHome.pm
UPD 2017-07-17_17:01:34 24008 FHEM/71_XiaomiSmartHome_Device.pm UPD 2019-03-20_11:32:54 30100 FHEM/71_XiaomiSmartHome_Device.pm

BIN
images/7.PNG Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB