Compare commits

44 Commits
pr/5 ... master

Author SHA1 Message Date
0cd97cd6a1 Update README.md 2019-07-10 12:21:22 +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 293 deletions

View File

@@ -41,15 +41,15 @@ return "\nERROR: Please install Crypt::CBC" if($@);
eval "use Net::Ping";
return "\nERROR: Please install Net::Ping" if($@);
use Color;
use SetExtensions;
sub XiaomiSmartHome_Notify($$);
sub XiaomiSmartHome_updateSingleReading($$);
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.41";
my %XiaomiSmartHome_gets = (
"getDevices" => ["get_id_list", '^.+get_id_list_ack' ],
@@ -64,6 +64,7 @@ my %sets = (
"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,
"ringvol" => 2,
"learn" => 0,
);
@@ -71,8 +72,8 @@ my %sets = (
sub XiaomiSmartHome_Initialize($) {
my ($hash) = @_;
$hash->{Clients} = "XiaomiSmartHome_Device";
$hash->{Clients} = 'XiaomiSmartHome_Device';
$hash->{DefFn} = 'XiaomiSmartHome_Define';
$hash->{UndefFn} = 'XiaomiSmartHome_Undef';
$hash->{NotifyFn} = 'XiaomiSmartHome_Notify';
@@ -80,15 +81,16 @@ sub XiaomiSmartHome_Initialize($) {
$hash->{GetFn} = 'XiaomiSmartHome_Get';
$hash->{AttrFn} = 'XiaomiSmartHome_Attr';
$hash->{ReadFn} = 'XiaomiSmartHome_Read';
$hash->{WriteFn} = "XiaomiSmartHome_Write";
$hash->{AttrList} = "disable:1,0 " .
$hash->{ReadyFn} = 'XiaomiSmartHome_Ready';
$hash->{WriteFn} = 'XiaomiSmartHome_Write';
$hash->{AttrList} = 'disable:1,0 ' .
$readingFnAttributes;
$hash->{MatchList} = { "1:XiaomiSmartHome_Device" => ".*magnet.*",
"2:XiaomiSmartHome_Device" => ".*motion.*",
"3:XiaomiSmartHome_Device" => "^.+sensor_ht",
"4:XiaomiSmartHome_Device" => ".*switch.*",
"5:XiaomiSmartHome_Device" => "^.+cube",
"5:XiaomiSmartHome_Device" => ".*cube.*",
"6:XiaomiSmartHome_Device" => "^.+plug",
"7:XiaomiSmartHome_Device" => "^.+86sw1",
"8:XiaomiSmartHome_Device" => "^.+86sw2",
@@ -102,7 +104,12 @@ sub XiaomiSmartHome_Initialize($) {
"16:XiaomiSmartHome_Device" => "^.+natgas",
"17:XiaomiSmartHome_Device" => "^.+smoke",
"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();
}
#####################################
@@ -110,10 +117,13 @@ sub XiaomiSmartHome_Read($) {
my ($hash) = @_;
my $name = $hash->{NAME};
my $self = {}; # my new hash
my $new_hash = {};
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);
if (!defined($ret) || $ret <= 0)
{
@@ -122,7 +132,7 @@ sub XiaomiSmartHome_Read($) {
InternalTimer(gettimeofday() + 2, "XiaomiSmartHome_connect", $hash, 0);
return;
}
my $json = $hash->{helper}{JSON}->incr_parse($buf);
my $json = $hash->{helper}{JSON}->incr_parse($buf);
my $decoded = eval{decode_json($buf)};
if ($@) {
Log3 $name, 1, "$name: Read> Error while request: $@";
@@ -134,23 +144,69 @@ sub XiaomiSmartHome_Read($) {
}
if ($json)
{
Log3 $name, 5, "$name: Read> " . $buf;
Log3 $name, 5, "$name: Read> [PLAIN] " . $buf;
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') {
Log3 $name, 5, "$name: Read> Dispatch " . $buf;
Dispatch($hash, $buf, undef);
# devices does not exist yet
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} ){
$self = $modules{XiaomiSmartHome}{defptr}{$rsid};
Log3 $name, 5, "$name: Read> Change HASH Ref to $self->{NAME}";
XiaomiSmartHome_Reading ($self, $buf);
Log3 $name, 5, "$name: Read> Wrong Modul HASH skipping $self->{NAME}";
#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";
XiaomiSmartHome_Reading ($hash, $buf);
}
}
return;
}
}
}
#####################################
sub XiaomiSmartHome_Reading ($@) {
@@ -199,7 +255,7 @@ sub XiaomiSmartHome_Reading ($@) {
#$hash->{SID} = $decoded->{'sid'};
}
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;
}
if ($data->{error}){
readingsBulkUpdate($hash, 'heartbeat', $data->{error}, 1 );
readingsBulkUpdate($hash, 'heartbeat', $data->{error}, 1 );
}
else {
readingsBulkUpdate($hash, 'heartbeat', "Write_OK", 1 );
readingsBulkUpdate($hash, 'heartbeat', "Write_OK", 1 );
readingsBulkUpdate($hash, "proto_version", $data->{proto_version} , 1 );
}
}
@@ -235,11 +291,14 @@ sub XiaomiSmartHome_Reading ($@) {
Log3 $name, 1, "$name: Reading> Error while request: $@";
return;
}
foreach my $sensor (@sensors)
my $all_sensors = "";
foreach my $sensor (@sensors)
{
Log3 $name, 4, "$name: Reading> PushRead:" . $sensor;
XiaomiSmartHome_Write($hash, 'read', $sensor );
$all_sensors = $all_sensors . $sensor . ",";
}
$hash->{helper}{sensors} = $all_sensors;
return;
}
}
@@ -286,16 +345,16 @@ sub XiaomiSmartHome_getGatewaySID($){
}
if ($json) {
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();
$hash->{SID} = $decoded->{sid};
$modules{XiaomiSmartHome}{defptr}{$decoded->{sid}} = $hash;
return $decoded->{sid};
}
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 ($@) {
Log3 $name, 1, "$name: getGatewaySID> Error no response from whois!! STOP!!";
@@ -326,8 +385,8 @@ sub XiaomiSmartHome_Define($$) {
if ( ! $p->ping($param[2])){
$hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash);
Log3 $name, 5, "$name: Define> Ping ERROR Gateway disconnecting";
$p->close();
Log3 $name, 1, "$name: Define> Ping ERROR Gateway disconnecting";
$p->close();
}
my $GATEWAY_IP = $param[2];
my $definition = $param[2];
@@ -339,12 +398,12 @@ sub XiaomiSmartHome_Define($$) {
$hash->{helper}{JSON} = JSON->new->utf8();
$hash->{FHEMIP} = XiaomiSmartHome_getLocalIP();
$hash->{STATE} = "initialized";
$hash->{helper}{host} = $definition;
$hash->{helper}{host} = $definition;
if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){
eval {
$GATEWAY_IP = inet_ntoa(inet_aton($hash->{GATEWAY})) ;
$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 ($@) {
Log3 $name, 1, "$name: Define> Error $@\n";
@@ -354,24 +413,24 @@ sub XiaomiSmartHome_Define($$) {
}
}
$hash->{GATEWAY_IP} = $GATEWAY_IP;
$modules{XiaomiSmartHome}{defptr}{$GATEWAY_IP} = $hash;
#$modules{XiaomiSmartHome}{defptr}{$GATEWAY_IP} = $hash;
#$hash->{SID} = XiaomiSmartHome_getGatewaySID($hash);
Log3 $name, 5, "$name: Define> $definition";
# Define 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} ) );
InternalTimer(gettimeofday() + 5, "XiaomiSmartHome_connect", $hash, 0);
InternalTimer(gettimeofday() + 5, "XiaomiSmartHome_connect", $hash, 0);
return undef;
}
#####################################
sub XiaomiSmartHome_Undef($$) {
my ($hash, $arg) = @_;
my ($hash, $arg) = @_;
XiaomiSmartHome_disconnect($hash);
# nothing to do
return undef;
@@ -382,8 +441,8 @@ sub XiaomiSmartHome_Write($@)
{
my ($hash,$cmd,$val,$iohash) = @_;
my $name = $hash->{NAME};
if ( $hash->{helper}{ConnectionState} eq 'Disconnected') {
Log3 $name, 1, "$name: Write> Cannot write iam disconnected";
if ( $hash->{helper}{ConnectionState} eq 'Disconnected') {
Log3 $name, 1, "$name: Write> Cannot write iam Disconnected";
return undef;
}
else{
@@ -393,7 +452,7 @@ sub XiaomiSmartHome_Write($@)
Log3 $name, 1, "$name: Write> Ping to $hash->{helper}{host} failed";
$hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash);
$p->close();
$p->close();
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) .'\"}" }';
}
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});
@@ -482,7 +546,7 @@ sub XiaomiSmartHome_Write($@)
my $sock = $hash->{CD};
my $MAXLEN = 1024;
$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;
}
#####################################
@@ -493,9 +557,9 @@ sub XiaomiSmartHome_EncryptKey($)
my $name = $hash->{NAME};
if ( $hash->{READINGS}{password}{VAL} =~ /^[a-zA-Z0-9]{16}$/ ) {
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});
$encryptkey = substr($encryptkey, 0, 32);
$encryptkey = substr($encryptkey, 0, 32);
return $encryptkey;
}
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($@)
{
my ($hash , $name, $opt, $args ) = @_;
if ($opt eq "UpdateAll")
{
XiaomiSmartHome_updateAllReadings($hash);
Log3 $name, 5, "$name: Get> UpdateALLReadings Started";
Log3 $name, 3, "$name: Get> UpdateALLReadings Started";
return "UpdateALLReadings Started";
}
elsif($opt eq "UpdateSingle")
{
XiaomiSmartHome_updateSingleReading($hash,$args);
Log3 $name, 5, "$name: Get> UpdateSingel Started";
Log3 $name, 3, "$name: Get> UpdateSingel Started";
return "UpdateSingel " . $args . " Started";
}
else
{
@@ -531,12 +613,23 @@ sub XiaomiSmartHome_Notify($$)
{
my ($hash, $dev_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
$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, "ringtone", 21, 1) if ( ! $hash->{READINGS}{ringtone}{VAL});
readingsSingleUpdate($hash, "volume", 10, 1) if ( ! $hash->{READINGS}{volume}{VAL});
readingsSingleUpdate($hash, "pct", 100, 1) if ( ! $hash->{READINGS}{pct}{VAL});
readingsSingleUpdate($hash, "ringtone", 21, 1) if ( ! $hash->{READINGS}{ringtone}{VAL});
readingsSingleUpdate($hash, "volume", 10, 1) if ( ! $hash->{READINGS}{volume}{VAL});
my $devName = $dev_hash->{NAME}; # Device that created the events
my $events = deviceEvents($dev_hash, 1);
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 $dec_num;
@@ -557,14 +650,14 @@ sub XiaomiSmartHome_Set($@)
#-- check argument
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 "\"set $name\" needs at least one argument" unless(defined($cmd));
if (!defined $hash->{READINGS}{pct}) {
$MIpct = $hash->{READINGS}{pct}{VAL};
}
else {
$MIpct = 64;
}
}
if($cmd eq "password")
{
#if($args[0] =~ /^[a-zA-Z0-9_.-]*$/)
@@ -576,7 +669,7 @@ sub XiaomiSmartHome_Set($@)
else
{
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}$/)
{
@@ -587,7 +680,7 @@ sub XiaomiSmartHome_Set($@)
elsif($cmd eq "rgb")
{
my $ownName = $hash->{NAME};
Log3 $ownName, 4, "$ownName: Set> $cmd, $args[0]";
$dec_num = sprintf("%d", hex($MIpct . $args[0]));
Log3 $ownName, 4, "$ownName: Set> $cmd, $dec_num";
@@ -613,13 +706,17 @@ sub XiaomiSmartHome_Set($@)
readingsBulkUpdate( $hash, 'rgb', $hash->{helper}{prevrgbvalue}, 1 );
XiaomiSmartHome_Write($hash,'rgb', $dec_num);
}
else
else
{
readingsBulkUpdate( $hash, 'rgb', "00ff00", 1 );
XiaomiSmartHome_Write($hash,'rgb', 1677786880);
}
readingsEndUpdate( $hash, 1 );
}
elsif($cmd eq "learn")
{
XiaomiSmartHome_Write($hash,'learn', 1);
}
elsif($cmd eq "pct")
{
my $ownName = $hash->{NAME};
@@ -663,7 +760,7 @@ sub XiaomiSmartHome_Set($@)
sub XiaomiSmartHome_Attr(@) {
my ($cmd,$NAME,$name, $val) = @_;
if ($cmd eq "delete"){
delete $attr{$NAME}{$name};
delete $attr{$NAME}{$name};
CommandDeleteAttr(undef, "$NAME $name");
Log3 $name, 1, "$name: Attr> delete $name";
}
@@ -681,21 +778,19 @@ sub XiaomiSmartHome_connect($)
my $name = $hash->{NAME};
my $GATEWAY_IP;
Log3 $name, 5, "$name: connect> ConnectStart";
Log3 $name, 4, "$name: connecting";
my $p = Net::Ping->new();
if ( ! $p->ping($hash->{GATEWAY})){
Log3 $name, 1, "$name: connect> Ping to $hash->{helper}{host} failed";
$hash->{STATE} = "Disconnected";
XiaomiSmartHome_disconnect($hash);
$p->close();
$p->close();
return undef;
}
if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){
eval {
$GATEWAY_IP = inet_ntoa(inet_aton($hash->{GATEWAY})) ;
$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 ($@) {
Log3 $name, 1, "$name: Connect> Error $@\n";
@@ -706,12 +801,12 @@ sub XiaomiSmartHome_connect($)
}
XiaomiSmartHome_getGatewaySID($hash);
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: $!";
if ($sock)
{
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_loopback(1);
$hash->{helper}{ConnectionState} = "Connected";
@@ -748,13 +843,13 @@ sub XiaomiSmartHome_disconnect($)
}
return if (!$hash->{CD});
Log3 $name, 3, "$name: disconnect> disconnecting";
Log3 $name, 1, "$name: disconnect> disconnecting";
close($hash->{CD}) if($hash->{CD});
delete($hash->{FD});
delete($hash->{CD});
delete($selectlist{$name});
return undef;
}
@@ -767,10 +862,10 @@ sub XiaomiSmartHome_updateSingleReading($$)
my $GATEWAY = $hash->{GATEWAY};
my $sock = $hash->{CD};
my $MAXLEN = 1024;
Log3 $name, 4, "$name: updateSingleReading> PushSingelRead:" . $sensor;
XiaomiSmartHome_Write($hash, 'read', $sensor);
}
#####################################
@@ -782,10 +877,10 @@ sub XiaomiSmartHome_updateAllReadings($)
my $GATEWAY;
my $p = Net::Ping->new();
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";
XiaomiSmartHome_disconnect($hash);
$p->close();
$p->close();
return undef;
}
if( $hash->{GATEWAY} !~ m/^\d+\.\d+\.\d+\.\d+$/ ){
@@ -805,13 +900,13 @@ sub XiaomiSmartHome_updateAllReadings($)
$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}";
XiaomiSmartHome_connect($hash);
return undef;
}
XiaomiSmartHome_Write($hash, 'get_id_list');
}
@@ -829,7 +924,7 @@ sub XiaomiSmartHome_updateAllReadings($)
<a name="XiaomiSmartHome"></a>
<h3>XiaomiSmartHome</h3>
<ul>
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<a name="XiaomiSmartHome"></a>
<br/>
<b>Prerequisite</b>
@@ -872,20 +967,21 @@ sub XiaomiSmartHome_updateAllReadings($)
<li>ctrl_neutral2: Double bond ignition switch</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: arlarm</li>
<li>8: battery arlarm</li>
<li>64: arlarm sensitivity</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: arlarm</li>
<li>2: analog arlarm</li>
<li>64: arlarm sensitivity</li>
<li>1: alarm</li>
<li>2: analog alarm</li>
<li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li>
</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>RGB(Colorpicker): set the color</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>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>learn: set the gateway in learningmode to learn new sensors now push the button from the new sensor</li>
</ul>
<br/>
<b>Set: Devices</b>
@@ -928,12 +1026,12 @@ sub XiaomiSmartHome_updateAllReadings($)
<a name="XiaomiSmartHome"></a>
<h3>XiaomiSmartHome</h3>
<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>
<br/>
<b>Vorraussetzungen</b>
<b>Voraussetzungen</b>
<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>
</ul>
<br/>
@@ -945,11 +1043,11 @@ sub XiaomiSmartHome_updateAllReadings($)
<br><br>
</ul>
<br/>
<b>Entwicklermodus am Gatway setzen!</b>
<b>Entwicklermodus am Gateway setzen!</b>
<ul>
<p>Ohne Entwicklermodus ist keine Komunikation mit dem Gateway m&oumlglich.
<br/>Zum setzen des Entwicklermoduses braucht man ein android oder ios Ger&aumlt mit installierter MI APP.
<br/>Um das versteckte Men&uuml zu &oumlffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<p>Ohne Entwicklermodus ist keine Kommunikation mit dem Gateway m&ouml;glich.
<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 &ouml;ffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<br/>Hier finden Sie eine Anleitung mit Bildern.
<br/>Android -> https://louiszl.gitbooks.io/lumi-gateway-local-api/content/device_discover.html
<br/>IOS -> https://github.com/fooxy/homeassistant-aqara/wiki/Enable-dev-mode
@@ -958,32 +1056,33 @@ sub XiaomiSmartHome_updateAllReadings($)
<br/>
<b>Unterstütze Sensoren</b>
<ul>
<li>magnet: Magnetischer Fenster/T&uumlr Sensor</li>
<li>magnet: Magnetischer Fenster/T&uuml;r Sensor</li>
<li>motion: Bewegungsmelder</li>
<li>sensor_ht: Temperatur und Luftdruck</li>
<li>switch: Funkschalter</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>86sw2: Wandfunkschalter doppelt</li>
<li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li>
<li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li>
<li>rgbw_light: RBGW Lampe (nur Anzeige)</li>
<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>
<ul>
<li>0: disarm</li>
<li>1: arlarm</li>
<li>8: battery arlarm</li>
<li>64: arlarm sensitivity</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: arlarm</li>
<li>2: analog arlarm</li>
<li>64: arlarm sensitivity</li>
<li>1: alarm</li>
<li>2: analog alarm</li>
<li>64: alarm sensitivity</li>
<li>32768: ICC communication failure</li>
</ul>
</ul>
@@ -992,27 +1091,29 @@ sub XiaomiSmartHome_updateAllReadings($)
<ul>
<li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li>
<li>Jedes XiaomiSmartHome Devices sendet alle 60 Minuten einen heartbeat</li>
<li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim empfang eines Heartbeat aktualisiert</li>
<li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim Empfang eines Heartbeat aktualisiert</li>
</ul>
<br/>
<b>Set: Gateway</b>
<ul>
<li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&oumlglich. Das Passwort findet man in der MI APP</li>
<li>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>PCT(Slider): Einstellen der Helligkeit des Gateways</li>
<li>ringtone: Wiedergeben eines Arlarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</li>
<li>volume: Einstellen der Lautst&aumlrke des Arlarmtones 1-100, (100 ist sehr laut!)</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges verändern der Lautst&aumlrke set [GWNAME] ringvol 21 10</li>
<li>intervals: Einschalten des Gateways für einen Zeitraum zb. set intervals 07:00-08:00</li>
<li>ringtone: Wiedergeben eines Alarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</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>
<br/>
<b>Set: Devices</b>
<ul>
<li>motionOffTimer: (nur Bewegungsmelder)
<br/>Durch setzen des Parameters ist es m&oumlglich das das Reading des Bewegungsmelder nach 1, 5 oder 10 Sekunden
<br/>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/>Hintergrund: Der Bewegungsmelder sendet kein selber kein off.
<br/>Der Bewegungsmelder sendet no_motion nach 120, 180, 300, 600, 1200 Sekunden wenn keine Bewegung festgestellt wurde.</li>
<li>Power: (nur Funksteckdose) on off Funktsteckdose ein oder ausschalten</li>
<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>
<li>Power: (nur Funksteckdose) on off Funksteckdose ein oder ausschalten</li>
<li>ctrl: (nur Funkschalter) on off Funkschalter </li>
<li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
<li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
@@ -1024,5 +1125,3 @@ sub XiaomiSmartHome_updateAllReadings($)
=cut

View File

@@ -25,7 +25,10 @@ package main;
use strict;
use warnings;
my $version = "1.08";
my $version = "1.40";
sub XiaomiSmartHome_Device_updateSReading($);
@@ -34,16 +37,21 @@ sub XiaomiSmartHome_Device_updateSReading($);
sub XiaomiSmartHome_Device_Initialize($)
{
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->{SetFn} = "XiaomiSmartHome_Device_Set";
$hash->{UndefFn} = "XiaomiSmartHome_Device_Undef";
$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 ".
$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 ) = @_;
return "\"set $name\" needs at least one argument" unless(defined($cmd));
my $setlist = "";
$setlist .= "motionOffTimer:1,5,10 " if ($hash->{MODEL} =~ /motion/);
#$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_ln2');
$setlist .= "status:open,close,stop,auto level:slider,1,1,100 " if ($hash->{MODEL} eq 'curtain');
if($cmd eq "power")
{
if($args[0] eq "on")
@@ -144,22 +152,22 @@ sub XiaomiSmartHome_Device_Set($@)
{
IOWrite($hash,"status","close",$hash) ;
return;
}
}
elsif($args[0] eq "stop")
{
IOWrite($hash,"status","stop",$hash) ;
return;
}
}
elsif($args[0] eq "auto")
{
IOWrite($hash,"status","auto",$hash) ;
return;
}
}
}
if($cmd eq "level")
{
IOWrite($hash,"level", $args[0] ,$hash) ;
return;
return;
}
# if($cmd eq "open")
# {
@@ -171,7 +179,7 @@ sub XiaomiSmartHome_Device_Set($@)
readingsSingleUpdate($hash, "motionOffTimer", "$args[0]", 1 );;
return;
}
return "Unknown argument $cmd, choose one of $setlist";
}
@@ -190,6 +198,12 @@ sub XiaomiSmartHome_Device_on_timeout($){
#####################################
sub XiaomiSmartHome_Device_Read($$$){
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)};
if ($@) {
Log3 $name, 1, "$name: DEV_Read> Error while request: $@";
@@ -197,6 +211,7 @@ sub XiaomiSmartHome_Device_Read($$$){
}
my $sid = $decoded->{'sid'};
my $model = $decoded->{'model'};
my $cmd = $decoded->{'cmd'};
Log3 $name, 5, "$name: DEV_Read> SID: " . $hash->{SID} . " " . $hash->{TYPE};
my $data = eval{decode_json($decoded->{data})};
if ($@) {
@@ -204,128 +219,164 @@ sub XiaomiSmartHome_Device_Read($$$){
return;
}
readingsBeginUpdate( $hash );
if (defined $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 );
if ($data->{status} eq 'motion' && $hash->{MODEL} =~ /motion/){
readingsBulkUpdate($hash, "no_motion", "0", 1 );
}
if ($data->{status} eq 'close' && $hash->{MODEL} =~ /magnet/){
readingsBulkUpdate($hash, "no_close", "0", 1 );
if (defined $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 );
if ($data->{status} eq 'motion' && $hash->{MODEL} =~ /motion/){
readingsBulkUpdate($hash, "no_motion", "0", 1 );
}
if ($data->{status} eq 'close' && $hash->{MODEL} =~ /magnet/){
readingsBulkUpdate($hash, "no_close", "0", 1 );
}
}
}
if (defined $data->{no_motion}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " NO_motion: " . $data->{no_motion};
readingsBulkUpdate($hash, "no_motion", "$data->{no_motion}", 1 );
}
if (defined $data->{no_close}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " NO_close: " . $data->{no_close};
readingsBulkUpdate($hash, "no_close", "$data->{no_close}", 1 );
}
if (defined $data->{voltage}){
my $bat = ($data->{voltage}/1000);
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Voltage: " . $data->{voltage};
readingsBulkUpdate($hash, "battery", $bat, 1 );
}
if (defined $data->{temperature}){
my $temp = $data->{temperature};
$temp =~ 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} . " Temperature: " . $temp;
readingsBulkUpdate($hash, "temperature", "$temp", 1 );
}
if (defined $data->{humidity}){
my $hum = $data->{humidity};
$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} . " Humidity: " . $hum;
readingsBulkUpdate($hash, "humidity", "$hum", 1 );
}
if (defined $data->{pressure}){
my $pres = $data->{pressure};
$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->{lux}){
my $lux = $data->{lux};
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Illuminance: " . $lux;
readingsBulkUpdate($hash, "lux", "$lux", 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};
readingsBulkUpdate($hash, "channel_0", "$data->{channel_0}", 1 );
}
if (defined $data->{channel_1}){
Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_1: " . $data->{channel_1};
readingsBulkUpdate($hash, "channel_1", "$data->{channel_1}", 1 );
}
#86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 end
#plug & 86plug start
if (defined $data->{load_voltage}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Voltage: " . $data->{load_voltage};
readingsBulkUpdate($hash, "LOAD_Voltage", "$data->{load_voltage}", 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};
readingsBulkUpdate($hash, "LOAD_Power", "$data->{load_power}", 1 );
}
if (defined $data->{power_consumed}){
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->{inuse}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " InUse: " . $data->{inuse};
readingsBulkUpdate($hash, "inuse", "$data->{inuse}", 1 );
}
#plug & 86plug end
#rgbw_light start
if (defined $data->{level}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Level: " . $data->{level};
readingsBulkUpdate($hash, "level", "$data->{level}", 1 );
}
if (defined $data->{hue}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Hue: " . $data->{hue};
readingsBulkUpdate($hash, "hue", "$data->{hue}", 1 );
}
if (defined $data->{saturation}){
Log3 $name, 3, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Saturation: " . $data->{saturation};
readingsBulkUpdate($hash, "saturation", "$data->{saturation}", 1 );
}
if (defined $data->{color_temperature}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Color_temperature: " . $data->{color_temperature};
readingsBulkUpdate($hash, "color_temperature", "$data->{color_temperature}", 1 );
}
if (defined $data->{x}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " X: " . $data->{x};
readingsBulkUpdate($hash, "x", "$data->{x}", 1 );
}
if (defined $data->{y}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Y: " . $data->{y};
readingsBulkUpdate($hash, "y", "$data->{y}", 1 );
}
#rgbw_light end
#cube start
if (defined $data->{rotate}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Rotate: " . $data->{rotate};
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} . " Rotate: " . $data->{arlarm};
readingsBulkUpdate($hash, "arlarm", "$data->{arlarm}", 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} . " Rotate: " . $data->{curtain_level};
readingsBulkUpdate($hash, "arlarm", "$data->{curtain_level}", 1 );
}
#curtain end
if ($decoded->{'cmd'} eq 'heartbeat'){
if (defined $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 );
}
if (defined $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 );
}
if (defined $data->{voltage}){
my $bat = ($data->{voltage}/1000);
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Voltage: " . $data->{voltage};
if ($bat < 2.2) {
readingsBulkUpdate($hash, "batteryState", "low", 1 );
}
else {
readingsBulkUpdate($hash, "batteryState", "ok", 1 )
}
$bat = XiaomiSmartHome_round($bat, $XMIround_bat, $name );
readingsBulkUpdate($hash, "batteryVoltage", $bat, 1 );
}
if (defined $data->{temperature}){
if ($data->{temperature} ne "10000"){
my $temp = sprintf( "%#.4d", $data->{temperature});
$temp =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
$temp = XiaomiSmartHome_round($temp, $XMIround_tmp, $name );
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Temperature: " . $temp . " Round: " . $XMIround_tmp;
readingsBulkUpdate($hash, "temperature", "$temp", 1 );
}
}
if (defined $data->{humidity}){
if ($data->{humidity} ne "0"){
my $hum = $data->{humidity};
$hum =~ s/(^[-+]?\d+?(?=(?>(?:\d{2})+)(?!\d))|\G\d{2}(?=\d))/$1./g;
$hum = XiaomiSmartHome_round($hum, $XMIround_hum, $name );
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Humidity: " . $hum . " Round: " . $XMIround_hum;
readingsBulkUpdate($hash, "humidity", "$hum", 1 );
}
}
if (defined $data->{pressure}){
if ($data->{pressure} ne "0"){
my $pres = $data->{pressure};
$pres =~ s/(^[-+]?\d+?(?=(?>(?:\d{3})+)(?!\d))|\G\d{3}(?=\d))/$1./g;
$pres = XiaomiSmartHome_round($pres, $XMIround_pres, $name );
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Pressure: " . $pres . " Round: " . $XMIround_pres;
readingsBulkUpdate($hash, "pressure", "$pres", 1 );
}
}
if (defined $data->{lux}){
my $lux = $data->{lux};
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Illuminance: " . $lux;
readingsBulkUpdate($hash, "lux", "$lux", 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};
readingsBulkUpdate($hash, "channel_0", "$data->{channel_0}", 1 );
}
if (defined $data->{channel_1}){
Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Channel_1: " . $data->{channel_1};
readingsBulkUpdate($hash, "channel_1", "$data->{channel_1}", 1 );
}
if (defined $data->{dual_channel}){
Log3 $name, 3, "$name: DEV_Read>" . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Dual_Channel: " . $data->{dual_channel};
readingsBulkUpdate($hash, "dual_channel", "$data->{dual_channel}", 1 );
}
#86sw1 + 86sw2 + ctrl_neutral1 + ctrl_neutral2 end
#plug & 86plug start
if (defined $data->{load_voltage}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " LOAD_Voltage: " . $data->{load_voltage};
readingsBulkUpdate($hash, "LOAD_Voltage", "$data->{load_voltage}", 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};
readingsBulkUpdate($hash, "LOAD_Power", "$data->{load_power}", 1 );
}
if (defined $data->{power_consumed}){
Log3 $name, 4, "$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->{inuse}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " InUse: " . $data->{inuse};
readingsBulkUpdate($hash, "inuse", "$data->{inuse}", 1 );
}
#plug & 86plug end
#rgbw_light start
if (defined $data->{level}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Level: " . $data->{level};
readingsBulkUpdate($hash, "level", "$data->{level}", 1 );
}
if (defined $data->{hue}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Hue: " . $data->{hue};
readingsBulkUpdate($hash, "hue", "$data->{hue}", 1 );
}
if (defined $data->{saturation}){
Log3 $name, 4, "$name:" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Saturation: " . $data->{saturation};
readingsBulkUpdate($hash, "saturation", "$data->{saturation}", 1 );
}
if (defined $data->{color_temperature}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Color_temperature: " . $data->{color_temperature};
readingsBulkUpdate($hash, "color_temperature", "$data->{color_temperature}", 1 );
}
if (defined $data->{x}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " X: " . $data->{x};
readingsBulkUpdate($hash, "x", "$data->{x}", 1 );
}
if (defined $data->{y}){
Log3 $name, 4, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Y: " . $data->{y};
readingsBulkUpdate($hash, "y", "$data->{y}", 1 );
}
#rgbw_light end
#cube start
if (defined $data->{rotate}){
Log3 $name, 3, "$name: DEV_Read>" . " Name: " . $hash->{NAME} . " SID: " . $sid . " Type: " . $hash->{MODEL} . " Rotate: " . $data->{rotate};
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 );
}
readingsEndUpdate( $hash, 1 );
XiaomiSmartHome_Device_update($hash);
return $hash->{NAME};
@@ -343,15 +394,17 @@ sub XiaomiSmartHome_Device_Parse($$) {
}
my $sid = $decoded->{'sid'};
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);
}
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";
}
}
@@ -369,17 +422,22 @@ sub XiaomiSmartHome_Device_update($){
my $LASTCMD = ReadingsVal($name,"lastCmd",undef);
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) );
}
if( $model =~ /motion/) {
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 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($$) {
my ($hash, $def) = @_;
@@ -392,7 +450,8 @@ sub XiaomiSmartHome_Device_Define($$) {
$hash->{STATE} = 'initialized';
$modules{XiaomiSmartHome_Device}{defptr}{$sid} = $hash;
AssignIoPort($hash,$iodev);
my $room = $attr{$iodev}{room};
if(defined($hash->{IODev}->{NAME})) {
my $IOname = $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";
}
$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 );
my $d = $modules{XiaomiSmartHome_Device}{defptr}{$sid};
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};
$attr{$name}{room} = "MiSmartHome" if( !defined( $attr{$name}{room} ) );
$attr{$name}{room} = $room if( !defined( $attr{$name}{room} ) );
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} ) );
}
elsif ( $type =~ /magnet/) {
$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') {
$attr{$name}{stateFormat} = 'temperature °C, humidity %, pressure kPa' if( !defined( $attr{$name}{stateFormat} ) );
}
}
if( $init_done ) {
InternalTimer(gettimeofday() + 2, "XiaomiSmartHome_Device_updateSReading", $hash, 0 );
Log3 $name, 4, $iodev . ": DEV_Define> " . $name . " Init Done set InternalTimer for Update";
}
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($) {
my $hash = shift;
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');
IOWrite($hash,'read',"$hash->{SID}");
}
@@ -440,20 +509,39 @@ sub XiaomiSmartHome_Device_updateSReading($) {
#####################################
sub XiaomiSmartHome_Device_Undef($)
{
my ($hash, $arg) = @_;
my ($hash, $arg) = @_;
my $name = $hash->{NAME};
my $iodev = $hash->{IODev}->{NAME};
my $sid = $hash->{SID};
RemoveInternalTimer($hash);
delete($modules{XiaomiSmartHome_Device}{defptr}{$hash->{SID}});
Log3 $name, 3, "$iodev: DEV_Undef> $name - device deleted";
Log3 $name, 1, "$iodev: DEV_Undef> ". $hash->{SID} . " > " . $modules{XiaomiSmartHome_Device}{defptr}{$hash->{SID}} . " > " . $sid ." > " . $modules{XiaomiSmartHome_Device}{defptr}{$sid};
my $error = delete ($modules{XiaomiSmartHome_Device}{defptr}{$sid});
Log3 $name, 1, "$iodev: DEV_Undef> $name - device deleted " . $error;
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;
=pod
=item device
=item summary Module to control XiaomiSmartHome Gateway
=item summary_DE Modul zum steuern des XiaomiSmartHome Gateway
=begin html
@@ -461,7 +549,7 @@ sub XiaomiSmartHome_Device_Undef($)
<a name="XiaomiSmartHome_Device"></a>
<h3>XiaomiSmartHome</h3>
<ul>
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<i>XiaomiSmartHome</i> implements the XiaomiSmartHome Gateway and Sensors.
<a name="XiaomiSmartHome"></a>
<br/>
<b>Prerequisite</b>
@@ -492,15 +580,35 @@ sub XiaomiSmartHome_Device_Undef($)
<ul>
<li>magnet: Window/Door magnetic 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>plug: Smart socket</li>
<li>plug & 86plug: Smart socket</li>
<li>cube: Cube sensor</li>
<li>86sw1: Wireless switch single</li>
<li>86sw2: Wireless switch double</li>
<li>ctrl_neutral1: Single bond ignition switch</li>
<li>ctrl_neutral2: Double bond ignition switch</li>
<li>rgbw_light: Smart lights (report only)</li>
<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>
<br/>
<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>RGB(Colorpicker): set the color</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>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>learn: set the gateway in learningmode to learn new sensors now push the button from the new sensor</li>
</ul>
<br/>
<b>Set: Devices</b>
<ul>
<li>motionOffTimer: (only motionsensor)
<br/>You can set a motion Off Timer Attribut on the motion sensor device. You can set 1, 5 or 10 seconds after
<br/>the motion sensors will automatically set to off.
<br/>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/>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>
@@ -538,15 +648,15 @@ sub XiaomiSmartHome_Device_Undef($)
=begin html_DE
<a name="XiaomiSmartHome"></a>
<a name="XiaomiSmartHome_Device"></a>
<h3>XiaomiSmartHome</h3>
<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>
<br/>
<b>Vorraussetzungen</b>
<b>Voraussetzungen</b>
<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>
</ul>
<br/>
@@ -558,11 +668,11 @@ sub XiaomiSmartHome_Device_Undef($)
<br><br>
</ul>
<br/>
<b>Entwicklermodus am Gatway setzen!</b>
<b>Entwicklermodus am Gateway setzen!</b>
<ul>
<p>Ohne Entwicklermodus ist keine Komunikation mit dem Gateway m&oumlglich.
<br/>Zum setzen des Entwicklermoduses braucht man ein android oder ios Ger&aumlt mit installierter MI APP.
<br/>Um das versteckte Men&uuml zu &oumlffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<p>Ohne Entwicklermodus ist keine Kommunikation mit dem Gateway m&ouml;glich.
<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 &ouml;ffnen muss man mehrmals auf die Versionsnummer der MI APP klicken.
<br/>Hier finden Sie eine Anleitung mit Bildern.
<br/>Android -> https://louiszl.gitbooks.io/lumi-gateway-local-api/content/device_discover.html
<br/>IOS -> https://github.com/fooxy/homeassistant-aqara/wiki/Enable-dev-mode
@@ -571,46 +681,64 @@ sub XiaomiSmartHome_Device_Undef($)
<br/>
<b>Unterstütze Sensoren</b>
<ul>
<li>magnet: Magnetischer Fenster/T&uumlr Sensor</li>
<li>magnet: Magnetischer Fenster/T&uuml;r Sensor</li>
<li>motion: Bewegungsmelder</li>
<li>sensor_motion.aq2: Aqara Bewegungsmelder mit lux-Messung</li>
<li>sensor_ht: Temperatur und Luftdruck</li>
<li>weather.v1: Aqara Temperatur, Luftdruck und Feuchtigkeit</li>
<li>switch: Funkschalter</li>
<li>plug: Schaltbare Funksteckdose</li>
<li>cube: W&uumlrfel Sensor</li>
<li>plug & 86plug: Schaltbare Funksteckdose</li>
<li>cube: W&uuml;rfel Sensor</li>
<li>86sw1: Einfacher Wandfunkschalter</li>
<li>86sw2: Wandfunkschalter doppelt</li>
<li>ctrl_neutral1: Einfacher Wandschalter schaltbar</li>
<li>ctrl_neutral2: Doppelter Wandschalter schaltbar</li>
<li>rgbw_light: RBGW Lampe (nur Anzeige)</li>
<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>
<br/>
<b>Heartbeat</b>
<ul>
<li>Das XiaomiSmartHome Gateway sendet alle 10 seconds einen heartbeat</li>
<li>Jedes XiaomiSmartHome Devices sendet alle 60 Minuten einen heartbeat</li>
<li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim empfang eines Heartbeat aktualisiert</li>
<li>Das Reading heartbeat wird mit der SID des jeweiligen Gerätes beim Empfang eines Heartbeat aktualisiert</li>
</ul>
<br/>
<b>Set: Gateway</b>
<ul>
<li>password: Ohne Passwort ist ein Schalten des GATEWAY nicht m&oumlglich. Das Passwort findet man in der MI APP</li>
<li>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>PCT(Slider): Einstellen der Helligkeit des Gateways</li>
<li>ringtone: Wiedergeben eines Arlarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</li>
<li>volume: Einstellen der Lautst&aumlrke des Arlarmtones 1-100, (100 ist sehr laut!)</li>
<li>ringvol: Wiedergeben eines Arlamtones und gleichzeitiges verändern der Lautst&aumlrke set [GWNAME] ringvol 21 10</li>
<li>intervals: Einschalten des Gateways für einen Zeitraum zb. set intervals 07:00-08:00</li>
<li>ringtone: Wiedergeben eines Alarmtones 0-8,13,21-29,10001-.. Benutzerdefinierte| 10000 = aus</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>
<br/>
<b>Set: Devices</b>
<ul>
<li>motionOffTimer: (nur Bewegungsmelder)
<br/>Durch setzen des Parameters ist es m&oumlglich das das Reading des Bewegungsmelder nach 1, 5 oder 10 Sekunden
<br/>automatisch wieder auf off gestellt wird. Standardmäßig ist dieser Wert auf 5 gestellt, sodass der Sensor alle 5 Sekunden auf eine erneute Bewegung reagiert.
<br/>Hintergrund: Der Bewegungsmelder sendet kein selber kein off.
<br/>Der Bewegungsmelder sendet no_motion nach 120, 180, 300, 600, 1200 Sekunden wenn keine Bewegung festgestellt wurde.</li>
<li>Power: (nur Funksteckdose) on off Funktsteckdose ein oder ausschalten</li>
<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/>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>
<li>Power: (nur Funksteckdose) on off Funksteckdose ein oder ausschalten</li>
<li>ctrl: (nur Funkschalter) on off Funkschalter </li>
<li>channel_0: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
<li>channel_1: (nur Doppelter Wandschalter schaltbar) ein oder ausschalten </li>
@@ -619,4 +747,5 @@ sub XiaomiSmartHome_Device_Undef($)
=end html_DE
=cut
=cut

View File

@@ -1,6 +1,44 @@
# 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.
Changing and switching the led of the gateway and changing ringtone and volume of the gateway is also possible
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 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.
* 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
* Chrisnitt

View File

@@ -1,2 +1,2 @@
UPD 2017-07-17_17:26:57 36127 FHEM/71_XiaomiSmartHome.pm
UPD 2017-07-17_17:01:34 24008 FHEM/71_XiaomiSmartHome_Device.pm
UPD 2019-04-26_11:40:51 40758 FHEM/71_XiaomiSmartHome.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