From ed7893570ecd20f24c58e3f68ceba9742aa443b4 Mon Sep 17 00:00:00 2001 From: borisneubert <borisneubert@users.noreply.github.com> Date: Sat, 20 Jun 2009 17:18:59 +0000 Subject: [PATCH] USF1000S support for FHEM added (Boris 2009-06-20) git-svn-id: https://svn.fhem.de/fhem/trunk@394 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/CHANGED | 3 +- fhem/FHEM/00_FHZ.pm | 5 +- fhem/FHEM/09_USF1000.pm | 170 ++++++++++++++++++++++++++++++++++++++ fhem/HISTORY | 5 +- fhem/docs/USF1000.txt | 41 +++++++++ fhem/docs/commandref.html | 70 +++++++++++++++- 6 files changed, 288 insertions(+), 6 deletions(-) create mode 100644 fhem/FHEM/09_USF1000.pm create mode 100755 fhem/docs/USF1000.txt diff --git a/fhem/CHANGED b/fhem/CHANGED index fa1d6e0d3..bc9f0839c 100644 --- a/fhem/CHANGED +++ b/fhem/CHANGED @@ -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) diff --git a/fhem/FHEM/00_FHZ.pm b/fhem/FHEM/00_FHZ.pm index dcd7e6e35..8495bbde4 100755 --- a/fhem/FHEM/00_FHZ.pm +++ b/fhem/FHEM/00_FHZ.pm @@ -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"; diff --git a/fhem/FHEM/09_USF1000.pm b/fhem/FHEM/09_USF1000.pm new file mode 100644 index 000000000..312e81b2f --- /dev/null +++ b/fhem/FHEM/09_USF1000.pm @@ -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; diff --git a/fhem/HISTORY b/fhem/HISTORY index 24281040e..092cc318a 100644 --- a/fhem/HISTORY +++ b/fhem/HISTORY @@ -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. diff --git a/fhem/docs/USF1000.txt b/fhem/docs/USF1000.txt new file mode 100755 index 000000000..260cc8475 --- /dev/null +++ b/fhem/docs/USF1000.txt @@ -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). \ No newline at end of file diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index 30df39a93..cbc9a0f34 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -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>