mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-01-31 06:39:11 +00:00
USF1000S support for FHEM added (Boris 2009-06-20)
git-svn-id: https://svn.fhem.de/fhem/trunk@394 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
37d116eba0
commit
ed7893570e
@ -502,6 +502,7 @@
|
||||
- feature: CUL FHT sending added
|
||||
- bugfix: workaround to make M232 counter wraparound
|
||||
- feature: sequence module added
|
||||
- feature: Google Weather API support form FHEM (Boris 2009-06-01)
|
||||
- feature: Google Weather API support for FHEM (Boris 2009-06-01)
|
||||
- feature: lazy attribute for FHT devices (Boris 2009-06-09)
|
||||
- feature: tmpcorr attribute for FHT devices
|
||||
- feature: USF1000S support for FHEM added (Boris 2009-06-20)
|
||||
|
@ -57,12 +57,13 @@ FHZ_Initialize($)
|
||||
# Provider
|
||||
$hash->{ReadFn} = "FHZ_Read";
|
||||
$hash->{WriteFn} = "FHZ_Write";
|
||||
$hash->{Clients} = ":FHZ:FS20:FHT:HMS:KS300:";
|
||||
$hash->{Clients} = ":FHZ:FS20:FHT:HMS:KS300:USF1000:";
|
||||
my %mc = (
|
||||
"1:FS20" => "^81..(04|0c)..0101a001",
|
||||
"2:FHT" => "^81..(04|09|0d)..(0909a001|83098301|c409c401)..",
|
||||
"3:HMS" => "^810e04....(1|5|9).a001",
|
||||
"4:KS300" => "^810d04..4027a001"
|
||||
"4:KS300" => "^810d04..4027a001",
|
||||
"5:USF1000" => "^810c04..0101a001a5ceaa00...."
|
||||
);
|
||||
$hash->{MatchList} = \%mc;
|
||||
$hash->{ReadyFn} = "FHZ_Ready";
|
||||
|
170
fhem/FHEM/09_USF1000.pm
Normal file
170
fhem/FHEM/09_USF1000.pm
Normal file
@ -0,0 +1,170 @@
|
||||
#
|
||||
#
|
||||
# 09_USF1000.pm
|
||||
# written by Dr. Boris Neubert 2009-06-20
|
||||
# e-mail: omega at online dot de
|
||||
#
|
||||
##############################################
|
||||
package main;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
my $PI= 3.141592653589793238;
|
||||
|
||||
my %defptr;
|
||||
my $dev= "a5ce aa";
|
||||
|
||||
#############################
|
||||
sub
|
||||
USF1000_Initialize($)
|
||||
{
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{Match} = "^810c04..0101a001a5ceaa00....";
|
||||
$hash->{DefFn} = "USF1000_Define";
|
||||
$hash->{UndefFn} = "USF1000_Undef";
|
||||
$hash->{ParseFn} = "USF1000_Parse";
|
||||
$hash->{AttrList} = "IODev do_not_notify:1,0 showtime:0,1 dummy:1,0 model:usf1000s loglevel:0,1,2,3,4,5,6";
|
||||
|
||||
}
|
||||
|
||||
|
||||
#############################
|
||||
sub
|
||||
USF1000_Define($$)
|
||||
{
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
|
||||
my $u= "wrong syntax: define <name> USF1000 geometry";
|
||||
my $g= "wrong geometry for USF1000";
|
||||
|
||||
# geometry (units: meter)
|
||||
# cub length width height offset cuboid 3+4
|
||||
# cylv diameter height offset vertical cylinder 3+3
|
||||
# the offset is measured from the TOP of the box!
|
||||
|
||||
return $u if(int(@a)< 6);
|
||||
|
||||
my $name = $a[0];
|
||||
my $geometry = $a[2];
|
||||
|
||||
if($geometry eq "cub") {
|
||||
# cuboid
|
||||
return $g if(int(@a)< 7);
|
||||
$hash->{GEOMETRY}= $geometry;
|
||||
$hash->{LENGTH}= $a[3];
|
||||
$hash->{WIDTH}= $a[4];
|
||||
$hash->{HEIGHT}= $a[5];
|
||||
$hash->{OFFSET}= $a[6];
|
||||
$hash->{CAPACITY}= int($hash->{LENGTH}*$hash->{WIDTH}*$hash->{HEIGHT}*100.0+0.5)*10.0;
|
||||
} elsif($geometry eq "cylv") {
|
||||
# vertical cylinder
|
||||
return $g if(int(@a)< 6);
|
||||
$hash->{GEOMETRY}= $geometry;
|
||||
$hash->{DIAMETER}= $a[3];
|
||||
$hash->{HEIGHT}= $a[4];
|
||||
$hash->{OFFSET}= $a[5];
|
||||
$hash->{CAPACITY}= int($PI*$hash->{DIAMETER}*$hash->{DIAMETER}/4.0*$hash->{HEIGHT}*100.0+0.5)*10.0;
|
||||
} else {
|
||||
return $g;
|
||||
}
|
||||
|
||||
$defptr{$dev} = $hash;
|
||||
AssignIoPort($hash);
|
||||
}
|
||||
|
||||
#############################
|
||||
sub
|
||||
USF1000_Undef($$)
|
||||
{
|
||||
my ($hash, $name) = @_;
|
||||
delete($defptr{$dev});
|
||||
return undef;
|
||||
}
|
||||
|
||||
#############################
|
||||
sub
|
||||
USF1000_Parse($$)
|
||||
{
|
||||
my ($hash, $msg) = @_; # hash points to the FHZ, not to the USF1000
|
||||
|
||||
if(!defined($defptr{$dev})) {
|
||||
Log 3, "USF1000 Unknown device, please define it";
|
||||
return "UNDEFINED USF1000";
|
||||
}
|
||||
|
||||
my $def= $defptr{$dev};
|
||||
my $name= $def->{NAME};
|
||||
|
||||
return "" if($def->{IODev} && $def->{IODev}{NAME} ne $hash->{NAME});
|
||||
|
||||
|
||||
# Msg format:
|
||||
# 01 23 45 67 8901 2345 6789 01 23 45 67
|
||||
# 81 0c 04 .. 0101 a001 a5ce aa 00 cc xx
|
||||
|
||||
my $cc= substr($msg, 24, 2);
|
||||
my $xx= substr($msg, 26, 2);
|
||||
|
||||
|
||||
my $lowbattery= (hex($cc) & 0x40 ? 1 : 0);
|
||||
my $testmode= (hex($cc) & 0x80 ? 1 : 0);
|
||||
my $distance= hex($xx)/100.0; # in meters
|
||||
|
||||
my $wlevel = $def->{HEIGHT}-($distance-$def->{OFFSET}); # water level
|
||||
|
||||
my $geometry= $def->{GEOMETRY};
|
||||
my $capacity= $def->{CAPACITY}; # capacity of tank (for distance= offset) in liters
|
||||
my $volume; # current volume in tank in liters
|
||||
my $flevel; # fill level in percent
|
||||
|
||||
|
||||
if($geometry eq "cub") {
|
||||
# cuboid
|
||||
$volume = $def->{LENGTH}*$def->{WIDTH}*$wlevel*1000.0;
|
||||
} elsif($geometry eq "cylv") {
|
||||
# vertical cylinder
|
||||
$volume = $PI*$def->{DIAMETER}*$def->{DIAMETER}/4.0*$wlevel*1000.0;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
$flevel = int($volume/$capacity*100.0+0.5);
|
||||
$volume= int($volume/10.0+0.5)*10.0;
|
||||
|
||||
my $t= TimeNow();
|
||||
|
||||
my $state= sprintf("v: %d V: %d", $flevel, $volume);
|
||||
|
||||
$def->{CHANGED}[0] = $state;
|
||||
$def->{STATE} = $state;
|
||||
$def->{READINGS}{state}{TIME} = $t;
|
||||
$def->{READINGS}{state}{VAL} = $state;
|
||||
Log GetLogLevel($name, 4), "USF1000 $name: $state";
|
||||
|
||||
$def->{READINGS}{distance}{TIME} = $t;
|
||||
$def->{READINGS}{distance}{VAL} = $distance;
|
||||
$def->{READINGS}{level}{TIME} = $t;
|
||||
$def->{READINGS}{level}{VAL} = $flevel;
|
||||
$def->{READINGS}{volume}{TIME} = $t;
|
||||
$def->{READINGS}{volume}{VAL} = $volume;
|
||||
|
||||
my $warnings= ($lowbattery ? "Battery low" : "");
|
||||
if($testmode) {
|
||||
$warnings.= "; " if($warnings);
|
||||
$warnings.= "Test mode";
|
||||
}
|
||||
$warnings= $warnings ? $warnings : "none";
|
||||
|
||||
$def->{READINGS}{"warnings"}{TIME} = $t;
|
||||
$def->{READINGS}{"warnings"}{VAL} = $warnings;
|
||||
|
||||
return $name;
|
||||
|
||||
}
|
||||
|
||||
#############################
|
||||
|
||||
1;
|
@ -412,5 +412,8 @@
|
||||
- Tue Jun 09 2009 (Boris)
|
||||
- 11_FHT.pm: lazy attribute for FHT devices
|
||||
|
||||
- Sun Jun 14 2009 (Rudi
|
||||
- Sun Jun 14 2009 (Rudi)
|
||||
- 11_FHT.pm: tmpcorr attribute for FHT devices
|
||||
|
||||
- Sat Jun 20 2009 (Boris)
|
||||
- 09_USF1000.pm: new module to support USF1000S devices.
|
||||
|
41
fhem/docs/USF1000.txt
Executable file
41
fhem/docs/USF1000.txt
Executable file
@ -0,0 +1,41 @@
|
||||
2009-06-20bn
|
||||
|
||||
This document describes the protocol for the ultrasound fill-meter USF 1000 S.
|
||||
|
||||
Datagram is of FS20 sensor message type:
|
||||
|
||||
81 0C 04 ?? 01 01 A0 01 A5 CE AA 00 cc xx
|
||||
|
||||
81: begin of FS20/FHT communication
|
||||
0C: remaining length of datagram (12 bytes)
|
||||
04: type of datagram
|
||||
??: checksum
|
||||
01 01 A0 01: FS20 fix sequence, always 01 01 A0 01
|
||||
A5 CE: FS20 housecode, always A5CE
|
||||
AA: FS20 command, always AA
|
||||
00: always 00
|
||||
cc: code, see below
|
||||
xx: measured distance in cm
|
||||
|
||||
code:
|
||||
|
||||
hex bin
|
||||
37 00110111 30s message interval, normal operation
|
||||
B7 10110111 3s message interval, normal operation
|
||||
F7 11110111 3s message interval, battery low
|
||||
|||+++++-- 0x17 always 0x17
|
||||
||+------- 0x20 always 1 (= value byte follows)
|
||||
|+-------- 0x40 battery warning
|
||||
+--------- 0x80 test mode (3s message interval)
|
||||
|
||||
|
||||
measured distance from ultrasound sender/transmitter:
|
||||
|
||||
distance hex dec
|
||||
0.50 m 0x30 48
|
||||
1.00 m 0x60 96
|
||||
1.50 m 0x92 146
|
||||
2.00 m 0xC4 196
|
||||
|
||||
It is assumed that xx is the distance in centimeters from the top of the box
|
||||
(4 cm box height + 1 cm height of ultrasound sender/transmitter).
|
@ -74,6 +74,7 @@
|
||||
<a href="#WS2000">WS2000</a>
|
||||
<a href="#WS300">WS300</a>
|
||||
<a href="#Weather">Weather</a>
|
||||
<a href="#USF1000">USF1000</a>
|
||||
<a href="#X10">X10</a>
|
||||
<a href="#FHEMRENDERER">FHEMRENDERER</a>
|
||||
|
||||
@ -2149,7 +2150,7 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
<ul>
|
||||
<br>
|
||||
|
||||
<a name="WS300"></a>
|
||||
<a name="WS300define"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define WS300Device WS300 <serial device></code><br>
|
||||
@ -2205,7 +2206,7 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
<ul>
|
||||
<br>
|
||||
|
||||
<a name="Weather"></a>
|
||||
<a name="Weatherdefine"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> Weather <location> [<interval>]</code><br>
|
||||
@ -2277,6 +2278,71 @@ A line ending with \ will be concatenated with the next one, so long lines
|
||||
</ul>
|
||||
|
||||
|
||||
<a name="USF1000"></a>
|
||||
<h3>USF1000</h3>
|
||||
<ul>
|
||||
Fhem can receive your tank's fill level from the USF1000S device
|
||||
through a <a href="#FHZ">FHZ</a> device, so one must be defined first.
|
||||
The state contains the fill level in % (lower case v in the device state)
|
||||
and the current volume in liters (upper case V in the device state).
|
||||
Measured distance to the liquid's surface, fill level, volume and warnings
|
||||
(Test mode, Battery low) are available.<br>
|
||||
<br>
|
||||
|
||||
<a name="USF1000Define"></a>
|
||||
<b>Define</b>
|
||||
<ul>
|
||||
<code>define <name> USF1000 <geometry></code>
|
||||
<br><br>
|
||||
|
||||
<code><geometry></code> determines the form of the tank and the
|
||||
position of the sensor. The following geometries are currently
|
||||
supported:<br><br>
|
||||
<ul>
|
||||
<li><code>cub <length> <width> <height> <offset></code></li>
|
||||
<li><code>cylv <diameter> <height> <offset></code></li>
|
||||
</ul>
|
||||
<br>
|
||||
<code>cub</code> stands for a cuboid whose base is <length> × <width>.
|
||||
<code>cylv</code> stands for a vertical cylinder whose diameter is <diameter>.
|
||||
<height> is the distance of the surface of the liquid from the ground
|
||||
if the tank is full. <offset> is the distance of the sensor relative to
|
||||
the surface of the liquid. All quantities are expressed in meters.<br>
|
||||
<br>
|
||||
|
||||
Example:<br>
|
||||
<ul>
|
||||
<code>define MyTank USF1000 cylv 2 1 0.3</code>: a cylindrical water tank with
|
||||
2 meters diameter. The water stands 1 meter high if the tank is full. The
|
||||
sensor is fixed 1,3 meters above ground.<br>
|
||||
</ul>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<b>Set </b>
|
||||
<ul>
|
||||
N/A
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<b>Get</b>
|
||||
<ul>
|
||||
N/A
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
<b>Attributes</b>
|
||||
<ul>
|
||||
<li><a href="#do_not_notify">do_not_notify</a></li>
|
||||
<li><a href="#showtime">showtime</a></li>
|
||||
<li><a href="#loglevel">loglevel</a></li>
|
||||
<li><a href="#model">model</a> (usf1000s)</li>
|
||||
</ul>
|
||||
<br>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<a name="SCIVT"></a>
|
||||
<h3>SCIVT</h3>
|
||||
|
Loading…
Reference in New Issue
Block a user