2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2024-11-22 02:59:49 +00:00
fhem-mirror/fhem/contrib/98_WIFILED.pm
betateilchen d5215a25d1 98_WIFILED.pm - added for simple use with LW12
git-svn-id: https://svn.fhem.de/fhem/trunk@6151 2b470e98-0d58-463d-a4d8-8e2adae1ed80
2014-06-21 21:47:17 +00:00

429 lines
12 KiB
Perl

# ############################################################################
#
# FHEM Modue for WLAN based LED Driver
#
# ############################################################################
#
# This is absolutley open source. Please feel free to use just as you
# like. Please note, that no warranty is given and no liability
# granted
#
# ############################################################################
#
# we have the following readings
# state on|off
#
# ############################################################################
#
# we have the following attributes
# timeout the timeout in seconds for the TCP connection
#
# ############################################################################
# we have the following internals (all UPPERCASE)
# RED last red value
# GREEN last green value
# BLUE last blue value
# IP the IP of the device
# RGB for the RGB Values of color-picker
# MODE the last number of the built in modes
#
# ############################################################################
# TODO: the speed of the animation: 0xBB, ??, ??, 0x44
# ############################################################################
package main;
use strict;
use warnings;
use IO::Socket;
# include this for the self-calling timer we use later on
use Time::HiRes qw(gettimeofday);
# for the color picker module
use Color;
use SetExtensions;
# ----------------------------------------------------------------------------
# Initialisation routine called upon start-up of FHEM
# ----------------------------------------------------------------------------
sub WIFILED_Initialize( $ ) {
my ($hash) = @_;
# the commands we provide to FHEM
# installs the respecitive call-backs for FHEM. The call back in quotes
# must be realised as a sub later on in the file
$hash->{DefFn} = "WIFILED_Define";
$hash->{SetFn} = "WIFILED_Set";
$hash->{GetFn} = "WIFILED_Get";
# the attributes we have. Space separated list of attribute values in
# the form name:default1,default2
$hash->{AttrList} = "timeout loglevel:0,1,2,3,4,5,6 " . $readingFnAttributes;
# initialize the color picker
FHEM_colorpickerInit();
}
# ----------------------------------------------------------------------------
# Definition of a module instance
# called when defining an element via fhem.cfg
# ----------------------------------------------------------------------------
sub WIFILED_Define( $$ ) {
my ( $hash, $def ) = @_;
my $name = $hash->{NAME};
my @a = split("[ \t][ \t]*", $def);
# do we have the right number of arguments?
if( @a != 3 ) {
Log( $attr{$name}{loglevel}, "WIFILED_Define: falsche Anzahl an Argumenten" );
return( "wrong syntax: define <name> WIFILED <serverip> " );
}
# preset the internals
$hash->{IP} = $a[ 2 ];
$hash->{RED} = 255;
$hash->{GREEN} = 255;
$hash->{BLUE} = 255;
$hash->{MODE} = 0;
if( !defined( $attr{$name}{timeout} ) ) {
$attr{$name}{timeout} = 2;
}
if( !defined( $attr{$name}{loglevel} ) ) {
$attr{$name}{loglevel} = 4;
}
# Preset our readings if undefined
my $tn = TimeNow();
if( !defined( $hash->{READINGS}{state}{VAL} ) ) {
$hash->{READINGS}{state}{VAL} = "?";
$hash->{READINGS}{state}{TIME} = $tn;
}
if( !defined( $hash->{READINGS}{rgb}{VAL} ) ) {
$hash->{READINGS}{rgb}{VAL} = "FFFFFF";
$hash->{READINGS}{rgb}{TIME} = $tn;
}
if( !defined( $hash->{READINGS}{RGB}{VAL} ) ) {
$hash->{READINGS}{RGB}{VAL} = "FFFFFF";
$hash->{READINGS}{RGB}{TIME} = $tn;
}
if( !defined( $hash->{READINGS}{dim}{VAL} ) ) {
$hash->{READINGS}{dim}{VAL} = 100;
$hash->{READINGS}{dim}{TIME} = $tn;
}
return( undef );
}
# ----------------------------------------------------------------------------
# Set of a module
# called upon set <name> cmd, arg1, arg2, ....
# ----------------------------------------------------------------------------
sub WIFILED_Set( $@ ) {
my ( $hash, $name, $cmd, @arg ) = @_;
# check if we have received a command
if( !defined( $cmd ) ) {
return( "$name: set needs at least one parameter" );
}
my $cmdList = "" .
"on off next:noArg prev:noArg mode " .
"color brightness:slider,0,1,100 dim:slider,0,1,100 " .
"rgb:colorpicker,RGB ";
# now parse the commands
if( $cmd eq "?" ) {
# this one should give us a drop down list
return SetExtensions( $hash, $cmdList, $name, $cmd, @arg );
} elsif( $cmd eq "on" ) {
WIFILED_Write( $hash, "\x{CC}\x{23}\x{33}" );
# and update the state
readingsSingleUpdate( $hash,
"state",
"on",
1 );
Log( GetLogLevel( $name, 4 ), "$name switched on" );
} elsif( $cmd eq "off" ) {
WIFILED_Write( $hash, "\x{CC}\x{24}\x{33}" );
# and update the state
readingsSingleUpdate( $hash,
"state",
"off",
1 );
Log( GetLogLevel( $name, 4 ), "$name switched off" );
} elsif( $cmd eq "run" ) {
WIFILED_Write( $hash, "\x{CC}\x{21}\x{33}" );
} elsif( $cmd eq "stop" ) {
WIFILED_Write( $hash, "\x{CC}\x{22}\x{33}" );
} elsif( $cmd eq "next" ) {
my $offset = 38;
my $mode = $offset + $hash->{MODE};
if( $mode > ( $offset + 20 ) ) {
$mode = $offset;
}
$hash->{MODE} = $mode;
WIFILED_Write( $hash, "\x{BB}" . chr( $mode ) . "\x{19}\x{44}" );
} elsif( $cmd eq "prev" ) {
my $offset = 38;
my $mode = $offset + $hash->{MODE};
if( $mode < $offset ) {
$mode = $offset + 20;
}
$hash->{MODE} = $mode;
WIFILED_Write( $hash, "\x{BB}" . chr( $mode ) . "\x{19}\x{44}" );
} elsif( $cmd eq "mode" ) {
my $offset = 38;
if( ( $arg[ 0 ] < 0 ) || ( $arg[ 0 ] > 19 ) ) {
my $msg = "WIFILED_Set: wrong mode number given";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
}
$hash->{MODE} = $arg[ 0 ] + $offset;
WIFILED_Write( $hash, "\x{BB}" . chr( $hash->{MODE} ) . "\x{19}\x{44}" );
} elsif( $cmd eq "color" ) {
if( @arg != 3 ) {
my $msg = "WIFILED_Set: wrong number of arguments for set color";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
} else {
$hash->{RED} = $arg[ 0 ];
$hash->{GREEN} = $arg[ 1 ];
$hash->{BLUE} = $arg[ 2 ];
WIFILED_Write( $hash, "\x{56}" .
chr( $arg[ 0 ] ) .
chr( $arg[ 1 ] ) .
chr( $arg[ 2 ] ) .
"\x{AA}" );
WIFILED_UpdateRGB( $hash );
Log( GetLogLevel( $name, 4 ), "$name set to " .
"$hash->{RED} $hash->{GREEN} $hash->{BLUE}" );
}
} elsif( $cmd eq "rgb" ) {
if( @arg != 1 ) {
my $msg = "WIFILED_Set: wrong number of arguments for set rgb";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
} else {
$arg[ 0 ] = uc( $arg[ 0 ] );
my @colors = ( $arg[ 0 ] =~ m/..?/g );
if( @colors != 3 ) {
my $msg = "WIFILED_Set: malformed RBG given.";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
} else {
$hash->{RED} = hex( $colors[ 0 ] );
$hash->{GREEN} = hex( $colors[ 1 ] );
$hash->{BLUE} = hex( $colors[ 2 ] );
WIFILED_Write( $hash, "\x{56}" .
chr( $hash->{RED} ) .
chr( $hash->{GREEN} ) .
chr( $hash->{BLUE} ) .
"\x{AA}" );
WIFILED_UpdateRGB( $hash );
Log( GetLogLevel( $name, 4 ), "$name set to " .
"$hash->{RED} $hash->{GREEN} $hash->{BLUE}" );
}
}
} elsif( ( $cmd eq "brightness" ) || ( $cmd eq "dim" ) ) {
if( @arg != 1 ) {
my $msg = "WIFILED_Set: wrong number of arguments for set brightness";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
} else {
# brightness is in percent (0..100)
my $bright = $arg[ 0 ];
my $red = $hash->{RED};
my $green = $hash->{GREEN};
my $blue = $hash->{BLUE};
if( ( $bright > 100 ) || ( $bright < 0 ) ) {
$bright = 50;
}
# we need to determine what is 100%
my $upscale = 0;
# what is the smallest upscale factor?
if( $red > $green ) {
if( $red > $blue ) {
$upscale = 255 / $red;
} else {
$upscale = 255 / $blue;
}
} else {
if( $green > $blue ) {
$upscale = 255 / $green;
} else {
$upscale = 255 / $blue;
}
}
$red = int( ( ( $red * $upscale ) * $bright ) / 100 );
$blue = int( ( ( $blue * $upscale ) * $bright ) / 100 );
$green = int( ( ( $green * $upscale ) * $bright ) / 100 );
WIFILED_Write( $hash, "\x{56}" . chr( $red ) . chr( $green ) .
chr( $blue ) . "\x{AA}\n" );
$hash->{RED} = $red;
$hash->{GREEN} = $green;
$hash->{BLUE} = $blue;
WIFILED_UpdateRGB( $hash );
readingsSingleUpdate( $hash, "dim", $bright, 1 );
}
} else {
# my $msg = "WIFILED_Set: unsupported command given $cmd @arg";
# Log( $attr{$name}{loglevel}, $msg );
# return( $msg );
return SetExtensions ($hash, $cmdList, $name, $cmd, @arg);
}
return( undef );
}
# ----------------------------------------------------------------------------
# Get of a module
# called upon get <name> arg1
# ----------------------------------------------------------------------------
sub WIFILED_Get( $@ ) {
my ($hash, @a) = @_;
my $name = $a[ 0 ];
if( int( @a ) != 2 ) {
my $msg = "WIFILED_Get: wrong number of arguments";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
}
if( ( $a[ 1 ] eq "rgb" ) || ( $a[ 1 ] eq "RGB" ) ) {
return( ReadingsVal( "$name", "rgb", "F0F0F0" ) );
} elsif( ( $a[ 1 ] eq "dim" ) || ( $a[ 1 ] eq "DIM" ) ) {
return( ReadingsVal( "$name", "dim", "50" ) );
} else {
my $msg = "WIFILED_Get: unkown argument";
Log( $attr{$name}{loglevel}, $msg );
return( $msg );
}
}
# ----------------------------------------------------------------------------
# write something to the WIFI LED
# ----------------------------------------------------------------------------
sub WIFILED_Write( $$ ) {
my ( $hash, $out ) = @_;
my $name = $hash->{NAME};
my $s = new IO::Socket::INET( PeerAddr => $hash->{IP},
PeerPort => 5577,
Proto => 'tcp',
Timeout => int( $attr{$name}{timeout} ) );
if( defined $s ) {
my $res = "";
$s->autoflush( 1 );
print $s $out;
close( $s );
}
}
# ----------------------------------------------------------------------------
# Update the RGB Readings for the color picker
# ----------------------------------------------------------------------------
sub WIFILED_UpdateRGB( $ ) {
my ( $hash, @rest ) = @_;
my $name = $hash->{NAME};
my $buf = sprintf( "%02X%02X%02X",
$hash->{RED},
$hash->{GREEN},
$hash->{BLUE} );
readingsSingleUpdate( $hash,
"RGB",
$buf,
1 );
readingsSingleUpdate( $hash,
"rgb",
$buf,
1 );
CommandTrigger( "", "$hash->{NAME} RGB: $buf" );
return;
}
# DO NOT WRITE BEYOND THIS LINE
1;
=pod
=begin html
<a name="WIFILED"></a>
<h3>WIFILED</h3>
<ul>
Define a WIFI LED Controler.
<br><br>
<a name="WIFILEDdefine"></a>
<b>Define</b>
<ul>
<code>define &lt;name&gt; WIFILED &lt;ip&gt;</code>
<br><br>
Example:
define myled WIFILED 192.168.38.17
<ul>
</ul>
</ul>
<br>
<a name="WIFILEDset"></a>
<b>Set</b>
<ul>
<code>set &lt;name&gt; &lt;value&gt</code><br>
Set any value.
</ul>
<br>
<a name="WIFILEDget"></a>
<b>Get</b> <ul>N/A</ul><br>
<a name="WIFILEDattr"></a>
<b>Attributes</b>
<ul>
<li><a name="setList">setList</a><br>
Space separated list of commands, which will be returned upon "set name ?",
so the FHEMWEB frontend can construct a dropdown and offer on/off
switches. Example: attr WIFILEDName setList on off
</li>
<li><a href="#readingFnAttributes">readingFnAttributes</a></li>
</ul>
<br>
</ul>
=end html
=cut