Misterhouse

From LinuxMCE
Revision as of 22:35, 7 December 2008 by Bulek (Talk | contribs) (Integration with LMCE)

Jump to: navigation, search

Misterhouse is a great integrated Home automation program and much more.

Installation

Template

It seems that template for Misterhouse is already in LMCE - I only needed to add Computers to "controlled by category", so it can be added as child of Core or MD...

In template, there is an "/usr/local/misterhouse/start.sh" entry in Command line data- that means that LMCE will start this script and therefore also misterhouse. Installation should be made regarding this fact.

HowTo

Currently there are no Ubuntu packages for MH, so it has to be installed from scratch. An detailed guide can be found on Misterhouse's site, I also have found isntructions for ubuntu and MH MisterhouseOnUbuntu

Integration with LMCE

Here's a dirty code snippet for LinuxMCE's listener script under Misterhouse. Be careful since it intercepts all messages and that could become quite greedy...

Before using this script you have to add listener as device under LinuxMCE as explained in LinuxMCE's docs... You have to follow first few steps from LinuxMCE's text message intercepting tutorial (create logic handler device) and then add this script to your Misterhouse setup :


# Category=LinuxMCE
#
#@ Connection with LinuxMCE DCE Router via TCP port localhost:3450 (mh.ini -> pluto_DCE_router). 
#
use strict;

############################################################################## 
$pluto_event_receiver = new  Socket_Item(undef, undef, '193.77.90.224:3450','event_receiver','tcp','record');

$pluto_command_sender = new  Socket_Item(undef, undef, '193.77.90.224:3450','command_sender','tcp','record');

if ($Startup) {
	start $pluto_event_receiver;
        set $pluto_event_receiver "COMMAND 6778";
        	
	start $pluto_command_sender;
	set $pluto_command_sender "EVENT 6778";
	set $pluto_command_sender "PLAIN_TEXT";
# purge other interceptors on same device ID
#	set $pluto_command_sender "MESSAGET 13";
#	set $pluto_command_sender "6778 -1000 13";
	send_command_to_pluto("6778 -1000 13");

# intercepts all messages, I guess it's better to be selective here !!!!	
#	set $pluto_command_sender "MESSAGET 22";
#	set $pluto_command_sender "6778 -1000 8 0 0 0 0 0";
	send_command_to_pluto("6778 -1000 8 0 0 0 0 0");

} 
     
sub send_command_to_pluto {
 my ($message) = @_;
	set $pluto_command_sender "MESSAGET " . length ($message);
	set $pluto_command_sender $message;
        print_log "Sending Command to Pluto DCE : $message\n";
        print     "Sending Command to Pluto DCE : $message\n";
}

if (my $msg = said $pluto_event_receiver) {
        print_log "Pluto Event received: $msg\n";
        print      "Pluto Event received: $msg\n";
}

Some additional work on this matter is described on forum threads here : [1] [2] [3]


Adding some useful snippets :

if (my $msg = said $pluto_device_event_receiver) {
        print_log "Pluto Device Message received: $msg\n";

        $msg =~ s/[\"\']//g;    # remove quotes before splitting on whitespace

        if ($msg =~/(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)/ ) {
                print_log "DeviceFrom: $1";
                print_log "DeviceTo:: $2";
                print_log "MsgType: $3 (1=Command, 2=Event)";
                print_log "MsgId: $4";
                print_log "param1id: $5";
                print_log "param2value (X10 Device): $6";
                print_log "param2id: $7";
                print_log "param2value (X10 Command): $8";
                if ($8 == '192') {
                  print_log "Turn $6 ON";
                  set $6 ON;
                }
                if ($8 == '193') {
                  print_log "Turn $6 OFF";
                  set $6 OFF;
                }
        }
}


# Category=Pluto
#
#@ Connection with Pluto DCE Router via TCP port localhost:3450 (mh.ini -> pluto_DCE_router).
#
use strict;
$restartTimer = new Timer;



##############################################################################

sub connect_lmce {
        print_log "Configuring sockets";
        $pluto_device_event_receiver = new  Socket_Item(undef, undef, '192.168.1.1:3450','device_event_receiver','tcp','record');
        $pluto_device_command_sender = new  Socket_Item(undef, undef, '192.168.1.1:3450','device_command_sender','tcp','record');

        print_log "Closing sockets if any left open";
        if (active_now $pluto_device_event_receiver) {stop $pluto_device_event_receiver;}
        if (active_now $pluto_device_command_sender) {stop $pluto_device_command_sender;}

        print_log "Open and setup new sockets";

        start $pluto_device_event_receiver;
        set $pluto_device_event_receiver "COMMAND 179";

        start $pluto_device_command_sender;
        set $pluto_device_command_sender "EVENT 179";
        set $pluto_device_command_sender "PLAIN_TEXT";
}

if ($Startup) {
        print_log "Starting connection to LMCE";
        set $restartTimer 10, sub {connect_lmce;};
}

if (inactive_now $pluto_device_event_receiver or inactive_now $pluto_device_command_sender) {
        print_log "Connection to LMCE terminated, restarting";
        set $restartTimer 10, sub {connect_lmce;};
}

if (new_minute 1 and !active $pluto_device_event_receiver or new_minute 1 and !active $pluto_device_command_sender) {
        print_log "Connection to LMCE still terminated, restarting";
        connect_lmce;
}



#my $motion=0;

if (my $msg = said $pluto_device_event_receiver) {
        print_log "Pluto Device Message received: $msg\n";

        $msg =~ s/[\"\']//g;    # remove quotes before splitting on whitespace

        if ($msg =~/(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)/ or $msg =~/(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)/) {
                print_log "DeviceFrom: $1";
                print_log "DeviceTo: $2";
                print_log "MsgType: $3 (1=Command, 2=Event)";
                print_log "MsgId: $4";
                print_log "param1id: $5";
                print_log "param2value: $6";
                if (defined $7) { print_log "param2id: $7";}
                if (defined $8) { print_log "param2value: $8";}

                #############################################################
                # $1    $2      $3      $4      $5      $6      $7      $8
                # from  to      msgtype msgid   p1id    p1val   p2id    p2val
                # Example command from orbiter
                # 69    206     1       192     97      ""      98      ""
                # 69    206     1       193     97      ""
                # 69    205     1       184     76      "100"
                # Example command from admin site
                # 0     204     1       760     10      "C2"    154     "192"
                # 0     204     1       760     10      "C2"    154     "193"
                #############################################################

                my $target;
                my $x10_id;

                if ($2 == '162') { $x10_id = 'A5'; }
                if ($2 == '186') { $x10_id = 'A3'; }
                if ($2 == '187') { $x10_id = 'B1'; }
                if ($2 == '188') { $x10_id = 'A8'; }
                if ($2 == '189') { $x10_id = 'B3'; }
                if ($2 == '190') { $x10_id = 'B4'; }
                if ($2 == '191') { $x10_id = 'A10'; }
                if ($2 == '192') { $x10_id = 'A9'; }
                if ($2 == '218') { $x10_id = 'A6'; }
                if (defined $x10_id) { $target = new X10_Item("$x10_id");}

                if ($4 == '760' ) { $target = new X10_Item("$6");}

                if ($8 == '192' or $4 == '192') {
                  print_log "Turn device $x10_id ON";
                  set $target ON;
                }
                if ($8 == '193' or $4 == '193') {
                  print_log "Turn device $x10_id OFF";
                  set $target OFF;
                }
                if ($4 == '184') {
                  print_log "Setting device $x10_id to $6%";
                  set $target "$6%";
                }
        }
}

sub send_pluto_message {
        my($message) = @_;
        set $pluto_device_command_sender "MESSAGET " . length ($message);
        set $pluto_device_command_sender $message;
}

sub update_temp {
        # Example message@
        # 167=temp sensor ID, 2=event, 25=event ID (temp changed), 30=value, temperature (string)
        # my $message = sprintf("167 -1000 2 25 30 %d.2",$random_number);

        my($sensor, $temp) = @_;
        my $lmce_device;

        ### map iButtons to lmce device numbers - there are better ways of doing this! ###
        if ($sensor == 0) { $lmce_device = 166; }
        if ($sensor == 1) { $lmce_device = 167; }

        my $message = sprintf("$lmce_device -1000 2 25 30 %d.2",$temp);
        send_pluto_message($message);
        print_log "Updating sensor $lmce_device $temp";
}

sub lmce_motion {
        my($device_id) = @_;
        # 6780=Detector ID, 2=event, 9=event ID (tripped), 25=tripped value, 0=value (tripped OFF)
        my $message = "$device_id -1000 2 9 25 0";
        send_pluto_message($message);
}

sub lmce_still {
        my($device_id) = @_;
        # 6780=Detector ID, 2=event, 9=event ID (tripped), 25=tripped value, 1=value (tripped ON)
        my $message = "$device_id -1000 2 9 25 1";
        send_pluto_message($message);
}

if ($state = state_now $Kitchen_Motion) {
  if ($state eq MOTION) {
        lmce_motion(185);
  }
  if ($state eq STILL) {
        lmce_still(185);
  }
}

if ($state = state_now $Landing_Motion) {
  if ($state eq MOTION) {
        lmce_motion(184);
  }
  if ($state eq STILL) {
        lmce_still(184);
  }
}

if ($state = state_now $Hall_Motion) {
  if ($state eq MOTION) {
        lmce_motion(183);
  }
  if ($state eq STILL) {
        lmce_still(183);
  }
}


        if ($msg =~/(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)/ or $msg =~/(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)\s(\w*)/
                        or $msg =~/(\w*)\s(\w*)\s(\w*)\s(\w*)/ ) {
                print_log "DeviceFrom: $1";
                print_log "DeviceTo: $2";
                print_log "MsgType: $3 (1=Command, 2=Event)";
                print_log "MsgId: $4";
                if (defined $5) { print_log "param1id: $5";}
                if (defined $6) { print_log "param2value: $6";}
                if (defined $7) { print_log "param2id: $7";}
                if (defined $8) { print_log "param2value: $8";}

                #############################################################
                # $1    $2      $3      $4      $5      $6      $7      $8
                # from  to      msgtype msgid   p1id    p1val   p2id    p2val
                # Example command from orbiter
                # 69    206     1       192     97      ""      98      ""
                # 69    206     1       193     97      ""
                # 69    205     1       184     76      "100"
                # 69    218     1       193
                # Example command from admin site
                # 0     204     1       760     10      "C2"    154     "192"
                # 0     204     1       760     10      "C2"    154     "193"
                #############################################################


It seems this is the most current version of MH connecting to LMCE:

# Category=Pluto
#
#@ Connection with Pluto DCE Router via TCP port localhost:3450 (mh.ini -> pluto_DCE_router).


# strict Perl syntax
use strict;


# Use timer.
$restartTimer = new Timer;


if($Startup)
{
        print_log "Starting connection to LMCE";
        set $restartTimer 10, sub {connect_lmce;};
}


if
(
        inactive_now($pluto_device_event_receiver) ||
        inactive_now($pluto_device_command_sender)
)
{
        print_log "Connection to LMCE terminated, restarting";
        set $restartTimer 10, sub {connect_lmce;};
}


# Should parenthesize &&/|| expressions to make precedence explicit
if(new_minute 1 && !active $pluto_device_event_receiver || new_minute 1 && !active $pluto_device_command_sender)
{
        print_log "Connection to LMCE still terminated, restarting";
        connect_lmce();
}


#my $motion=0;

if(my($msg) = said($pluto_device_event_receiver))
{ # Process message.
        print_log "Pluto Device Message received: $msg\n";

        # Remove quotes before splitting on whitespace.
        $msg =~ s/[\"\']//g;

        #############################################################
        # message Parameters as ordered fields
        #############################################################
        # $1    $2      $3      $4      $5      $6      $7      $8
        # from  to      msgtype msgid   p1id    p1val   p2id    p2val
        #############################################################
        # Example command from orbiter
        # 69    206     1       192     97      ""      98      ""
        # 69    206     1       193     97      ""
        # 69    205     1       184     76      "100"
        # Example command from admin site
        # 0     204     1       760     10      "C2"    154     "192"
        # 0     204     1       760     10      "C2"    154     "193"
        #############################################################

        # Decode message into required and optional fields as validation.
        my
        (
                $reqFieldsPat = '(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)\s+(\w+)';
                $optFieldsPat = '\s*(\w*)\s*(\w*)';
        );
        if
        (
                my
                (
                        # required fields
                        $deviceFrom, $deviceTo, $msgType, $msgId,
                        $param1Id, $param1Value,

                        # optional fields
                        $param2Id, $param2Value
                )
                = ($msg =~ /$reqFieldsPat$optFieldsPat/)
        )
        { # Process valid message.
                %msgTypes =
                {
                        '1' => 'Command',
                        '2' => 'Event'
                };
                $msgType .=
                        ': ' . defined($msgTypes{$msgType})?
                                        $msgTypes{$msgType} : 'unknown type';

                # Log required fields.
                print_log <<EOT;
DeviceFrom: $deviceFrom
DeviceTo: $deviceTo
MsgType: $msgType
MsgId: $msgId
param1id: $param1Id
param2value: $param1Val
EOT

                # Log optional fields.
                if(defined($param2Id))
                {
                        print_log "param2id: $$param2Id";
                        print_log 'param2value: ' .
                                (defined($param2Val))? $param2Val : 'undefined';
                }

                # Use X10 ID as target.
                my($target);
                my $x10_id;
                %dev2x10 =
                { # device ID to X10 ID
                        '162' => 'A5',
                        '186' => 'A3',
                        '187' => 'B1',
                        '188' => 'A8',
                        '189' => 'B3',
                        '190' => 'B4',
                        '191' => 'A10',
                        '192' => 'A9',
                        '218' => 'A6'
                }; # dev2x10

                $x10_id = $dev2x10{$deviceTo};
                if(defined($x10_id))
                {
                        $target = new X10_Item($x10_id);
                }

                # Probably can convert arbitrary msgID / setting rules
                #   to %msg2Setting if they're exclusive and regular.
                if($msgId eq '760' )
                { # new item in param1
                        $target = new X10_Item($param1Val);
                }


                # Execute message on target.
                if($msgId eq '192' || $param2Val eq '192')
                { # ON
                  print_log "Turn device $x10_id ON";
                  set $target ON;
                }
                if($msgId eq '193' || $param2Val eq '193')
                { # OFF
                  print_log "Turn device $x10_id OFF";
                  set $target OFF;
                }
                if($msgId eq '184')
                { # in param1
                  print_log "Setting device $x10_id to $param1Val%";
                  set $target "$param1Val%";
                }
        } # Process message.
}


my(%motionStates) =
{
        'MOTION' => '0',
        'STILL' => '1'
};
my(%motionLocation2DeviceId) =
{
        $Hall_Motion => '183',
        $Landing_Motion => '184',
        $Kitchen_Motion => '185'
};
my(@motionLocations) = keys(motionLocation2DeviceId);
foreach my($motionLocation) (@motionLocations)
{
        if($state = state_now($motionLocation)
        {
                lmce_motion($motionStates{$state}, $motionLocation);
        }
}


# subs ########################################################################

sub connect_lmce
{
        print_log "Configuring sockets";
        $pluto_device_event_receiver =
                new  Socket_Item(undef, undef, '192.168.1.1:3450','device_event_receiver','tcp','record');
        $pluto_device_command_sender =
                new  Socket_Item(undef, undef, '192.168.1.1:3450','device_command_sender','tcp','record');


        print_log "Closing sockets if any left open";
        if(active_now($pluto_device_event_receiver))
        {
                stop($pluto_device_event_receiver);
        }
        if(active_now($pluto_device_command_sender))
        {
                stop($pluto_device_command_sender);
        }


        print_log "Open and setup new sockets";
        start($pluto_device_event_receiver);
        set $pluto_device_event_receiver "COMMAND 179";

        start($pluto_device_command_sender);
        set $pluto_device_command_sender "EVENT 179";
        set $pluto_device_command_sender "PLAIN_TEXT";
}


sub send_pluto_message
{
        my($message) = @_;


        set $pluto_device_command_sender "MESSAGET " . length($message);
        set $pluto_device_command_sender $message;
}


sub update_temp
{
        my($sensor, $temp) = @_;


        # Example message@
        # 167=temp sensor ID, 2=event, 25=event ID (temp changed), 30=value, temperature (string)
        # my($message) = "167 -1000 2 25 30 $random_number.2";


        # Map iButtons to lmce device numbers.
        my(%sensorId2LMCEDeviceId) =
        {
                0 => 166,
                1 => 167
        }
        my($lmce_device) = $sensorId2LMCEDeviceId{$sensor};

        my($message) = "$lmce_device -1000 2 25 30 $temp.2";
        send_pluto_message($message);
        print_log "Updating sensor $lmce_device $temp";
}


sub lmce_motion
{
        my($motionState, $device_id) = @_;


        # 6780=Detector ID, 2=event, 9=event ID (tripped), 25=tripped value, 1=value (tripped 0=OFF || 1=ON)
        my($message) = "$device_id -1000 2 9 25 $motionState";
        send_pluto_message($message);
}