2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-04-20 19:36:02 +00:00

Multiple SIS_PM units now work. (After fixing sispmctl-bug, see commandref.html.)

NOTE: Changing the order of the units on the USB while fhem.pl is running WILL STILL BREAK THINGS!


git-svn-id: https://svn.fhem.de/fhem/trunk@551 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
painseeker 2010-01-19 19:33:01 +00:00
parent ad6d552595
commit aeea6033a8
2 changed files with 103 additions and 25 deletions

View File

@ -29,7 +29,7 @@
#
# Contributed by Kai 'wusel' Siering <wusel+fhem@uu.org> in 2010
# Based in part on work for FHEM by other authors ...
# $Id: 70_SISPM.pm,v 1.2 2010-01-18 01:12:34 painseeker Exp $
# $Id: 70_SISPM.pm,v 1.3 2010-01-19 19:33:01 painseeker Exp $
###########################
package main;
@ -102,6 +102,7 @@ SISPM_Define($$)
if(!$FH) {
return "SISPM Can't start $dev: $!";
}
$hash->{NUMUNITS}=0;
local $_;
while (<$FH>) {
if(/^(No GEMBIRD SiS-PM found.)/) {
@ -111,9 +112,11 @@ SISPM_Define($$)
if(/^Gembird #(\d+) is USB device (\d+)./) {
Log 3, "SISPM found SISPM device number $1 as USB $2";
$hash->{UNITS}{$1}{USB}=$2;
$currentdevice=$numdetected;
$currentdevice=$1;
$numdetected++;
$hash->{NUMUNITS}=$numdetected;
}
if(/^This device has a serial number of (.*)/) {
my $serial=$1;
Log 3, "SISPM device number " . $currentdevice . " has serial $serial";
@ -179,13 +182,19 @@ SISPM_GetStatus($)
my $name = $hash->{NAME};
my $dev = $hash->{DeviceName};
my $FH;
my $i;
# Call us in n seconds again.
# InternalTimer(gettimeofday()+ $hash->{Timer}, "SISPM_GetStatus", $hash, 1);
Log 4, "SISPM contacting device";
my $tmpdev=sprintf("%s -s -g all 2>&1 |", $dev);
my $tmpdev=sprintf("%s -s ", $dev);
for($i=0; $i<$hash->{NUMUNITS}; $i++) {
$tmpdev=sprintf("%s -d %d -g all ", $tmpdev, $i);
}
$tmpdev=sprintf("%s 2>&1 |", $tmpdev);
open($FH, $tmpdev);
if(!$FH) {
return "SISPM Can't open pipe: $dev: $!";
@ -232,6 +241,10 @@ SISPM_Read($)
my $reading;
my $readingforstatus;
my $currentserial="none";
my $currentdevice=0;
my $currentusbid=0;
my $renumbered=0;
my $newPMfound=0;
($eof, @lines) = nonblockGetLinesSISPM($FH);
@ -255,39 +268,65 @@ SISPM_Read($)
next;
}
# wusel, 2010-01-19: Multiple (2) SIS PM do work now. But USB renumbering will still
# break things rather badly. Thinking about dropping it altogether,
# that is wipe old state data ($hash->{UNITS} et. al.) and rebuild
# data each time from scratch. That should work as SIS_PMS uses the
# serial as key; unfortunately, sispmctl doesn't offer this (and it
# wont work due to those FFFFFFxx readings), so we need to keep
# track of unit number <-> serial ... But if between reading this
# data and a "set" statement something changes, we still could switch
# the wrong socket.
#
# As sispmctl 2.7 is broken already for multiple invocations with -d,
# I consider fixing both the serial number issue as well as add the
# serial as selector ... Drat. Instead of getting the ToDo list shorter,
# it just got longer ;-)
if($inputline =~ /^(No GEMBIRD SiS-PM found.)/) {
Log 3, "SISPM woops? $1";
Log 3, "SISPM Whoopsie? $1";
next;
}
if($inputline =~ /^Gembird #(\d+) is USB device (\d+)\./ ||
$inputline =~ /^Accessing Gembird #(\d+) USB device (\d+)/) {
Log 5, "SISPM found SISPM device number $1 as USB $2";
if($hash->{UNITS}{$1}{USB}!=$2) {
# -wusel, 2010-01-15: FIXME! Verify that this IS the device we're
# looking for. As USB renumbering can happen,
# if the $hash->{UNITS}{$1}{USB}=$2 not matches
# we'd need to redo a "sispmctl -s", maybe by
# going to SISPM_Define() again?
#
# Hoping the best for now -- DON'T TOUCH RUNNING
# BOX WITH MORE THAN ONE SISPM CONNECTED OR HELL
# MAY BREAK LOOSE ;)
Log 3, "SISPM: Odd, got unit $1 as USB $2, have $1 on file as " . $hash->{UNITS}{$1}{USB} . "?";
if($1 < $hash->{NUMUNITS}) {
if($hash->{UNITS}{$1}{USB}!=$2) {
Log 3, "SISPM: USB ids changed (unit $1 is now USB $2 but was " . $hash->{UNITS}{$1}{USB} . "); will fix.";
$renumbered=1;
}
} else { # Something wonderful has happened, we have a new SIS PM!
Log 3, "SISPM: Wuuuhn! Found a new unit $1 as USB $2. Will assimilate it.";
$newPMfound=1;
}
$currentdevice=$1;
$currentusbid=$2;
$currentserial="none";
if(defined($hash->{UNITS}{$currentdevice}{SERIAL})) {
$currentserial=$hash->{UNITS}{$currentdevice}{SERIAL};
}
}
# -wusel, 2010-01-15: FIXME! This will break on >1 PMS!
if($inputline =~ /^This device has a serial number of (.*)/) {
$currentserial=FixSISPMSerial($1);
if($currentserial eq "00:00:00:00:00") {
Log 3, "SISPM Whooopsie! Your serial nullified ($currentserial). Skipping ...";
next;
}
if($newPMfound==1) {
$hash->{UNITS}{$currentdevice}{USB}=$currentusbid;
$hash->{UNITS}{$currentdevice}{SERIAL}=$currentserial;
$hash->{SERIALS}{$currentserial}{UNIT}=$currentdevice;
$hash->{SERIALS}{$currentserial}{USB}=$currentusbid;
$hash->{NUMUNITS}+=1;
}
}
if($inputline =~ /^Status of outlet (\d):\s+(.*)/) {
if($currentserial ne "none") {
Log 5, "SISPM found socket $1 on $currentserial, state $2";
Log 3, "SISPM found socket $1 on $currentserial, state $2";
my $dmsg="socket " . $currentserial . " $1 state " . $2;
my %addvals;
Dispatch($hash, $dmsg, \%addvals);
@ -332,7 +371,7 @@ sub SISPM_Write($$$) {
}
if(defined($hash->{SERIALS}{$serial}{UNIT})) {
$deviceno=($hash->{SERIALS}{$serial}{UNIT})+1;
$deviceno=($hash->{SERIALS}{$serial}{UNIT});
$cmdline=sprintf("%s -d %d -%s %d 2>&1 >/dev/null", $dev, $deviceno, $cmdletter, $socket);
system($cmdline);
} else {

View File

@ -3467,13 +3467,52 @@ Forecast Cloudy</pre>
<code>define &lt;name&gt; SISPM &lt;/path/to/sispmctl&gt;</code>
<br><br>
<i><b>PLEASE NOTE:</b> This module is to be considered alpha quality; it has not been
tested extensively, especially the interaction between "set" commands and the sheduled
status reading needs more obervation. (Testing with FIFOs seems as if it's working
without blocking nor interference, but that's on a mostly unloaded, fast system.)<br><br>
BE CAREFUL when using multiple PMs on one host; the parser in SISPM_Define() is MOST
PROBABLY broken here, I haven't had the opportunity to test this yet. YOU HAVE BEEN
WARNED.</i> And now to what's this disclaimer tries to prevent you from using ;)<br><br>
<div style="background-color: #ffaaaa;">
<i><b>PLEASE NOTE:</b> This module is still work in progess; please treat it as such.
(That is, don't but your central heating on SISPM in a cold winter just yet ;))</i><br><br>
Further tests should be done regarding the interaction between "set" commands and the sheduled
status reading. (Testing with FIFOs seems as if it's working without blocking nor interference,
but that's on a mostly unloaded, fast system.)<br><br>
When <i>using multiple SIS PMs on one host</i>, sispmctl up to and including V 2.7 has a bug:
<pre>plug-2:# sispmctl -v -s -d 1 -g all -d 2 -g all
SiS PM Control for Linux 2.7
(C) 2004, 2005, 2006, 2007, 2008 by Mondrian Nuessle, (C) 2005, 2006 by Andreas Neuper.
This program is free software.
[...]
Gembird #0 is USB device 013.This device is a 4-socket SiS-PM.
[...]
Gembird #1 is USB device 015.This device is a 4-socket SiS-PM.
[...]
Accessing Gembird #1 USB device 015
Status of outlet 1: on
Status of outlet 2: on
Status of outlet 3: on
Status of outlet 4: on
Error performing requested action
Libusb error string: error sending control message: Invalid argument
Terminating
*** glibc detected *** sispmctl: double free or corruption (fasttop): 0x000251e0 ***
[...]</pre>
Well, the fix is simple and will be sent upstream, but in case it's not incorporated
at the time you need it, here it is; it's easy to apply even by hand ;-)
<pre>
--- src/main.c-old 2010-01-19 16:56:15.000000000 +0100
+++ src/main.c 2010-01-19 16:54:56.000000000 +0100
@@ -441,7 +441,7 @@
}
break;
case 'd': // replace previous (first is default) device by selected one
- if(udev!=NULL) usb_close (udev);
+ if(udev!=NULL) { usb_close (udev); udev=NULL; }
devnum = atoi(optarg);
if(devnum>=count) devnum=count-1;
break;
</pre></div><br>
Defines a path to the program "sispmctl", which is used to control (locally attached)
"Silver Shield Power Manager" devices. Usually these are connected to the local computer