diff --git a/FHEM/44_TEK603.pm b/FHEM/44_TEK603.pm new file mode 100644 index 000000000..b8e8fd65c --- /dev/null +++ b/FHEM/44_TEK603.pm @@ -0,0 +1,248 @@ +# $Id$ +#################################################################################################### +# +# 44_TEK603.pm +# +# Copyright: Stephan Eisler +# Email: fhem.dev@hausautomatisierung.co +# +# This file is part of fhem. +# +# Fhem is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# Fhem is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with fhem. If not, see . +# +#################################################################################################### + +package main; + +use strict; +use warnings; + +sub TEK603_Initialize($); +sub TEK603_define($$); +sub TEK603_doInit($); +sub TEK603_undef($$); +sub TEK603_ready($); +sub TEK603_read($); +sub TEK603_reconnect($); + + +sub TEK603_Initialize($) { + my ($hash) = @_; + + require $attr{global}{modpath} . '/FHEM/DevIo.pm'; + + $hash->{ReadFn} = 'TEK603_read'; + $hash->{ReadyFn} = 'TEK603_ready'; + $hash->{DefFn} = 'TEK603_define'; + $hash->{UndefFn} = 'TEK603_undef'; + + $hash->{AttrList} = 'do_not_notify:0,1 dummy:1,0 loglevel:0,1,2,3,4,5,6 '; +} + +sub TEK603_define($$) { + my ($hash, $def) = @_; + my @a = split('[ \t][ \t]*', $def); + + my $name = $a[0]; + my $dev = $a[2]; + + $hash->{DEF} = $dev; + + my $msg = ''; + + if( @a != 3) { + $msg = 'wrong syntax: define TEK603 {none | devicename}'; + Log3 $name, 3, $msg; + return $msg; + } + + DevIo_CloseDev($hash); + $hash->{PORTSTATE} = $hash->{STATE}; + + if($dev eq 'none') { + Log3 $name, 3, "device is none, commands will be echoed only"; + $attr{$name}{dummy} = 1; + return undef; + } + + $hash->{DeviceName} = $dev; + my $ret = DevIo_OpenDev($hash, 0, 'TEK603_doInit'); + + return $ret; +} + +sub TEK603_doInit($) { + my ($hash) = @_; + + my $po = $hash->{USBDev}; + my $dev = $hash->{DeviceName}; + my $name = $hash->{NAME}; + + # Parameter 115200, 8, 1, even, none + $po->reset_error(); + $po->baudrate(115200); + $po->databits(8); + $po->stopbits(1); + $po->parity('none'); + $po->handshake('none'); + $po->dtr_active(1); + $po->rts_active(1); + + if (!$po->write_settings) { + undef $po; + $hash->{STATE} = $name . 'Error on write serial line settings on device ' . $dev; + Log3 $name, 3, $hash->{STATE}; + return $hash->{STATE} . "\n"; + } + + Log3 $name, 3, "connected to device $dev"; + $hash->{STATE} = 'open'; + $hash->{PORTSTATE} = $hash->{STATE}; + + return undef; +} + +sub TEK603_undef($$) { + my ($hash, $name) = @_; + + foreach my $d (sort keys %defs) { + if(defined($defs{$d}) && defined($defs{$d}{IODev}) && $defs{$d}{IODev} == $hash) { + Log3 $name, 4, "deleting port for $d"; + delete $defs{$d}{IODev}; + } + } + + DevIo_CloseDev($hash); + $hash->{PORTSTATE} = $hash->{STATE}; + + return undef; +} + + +sub TEK603_ready($) { + my ($hash) = @_; + + return DevIo_OpenDev($hash, 1, 'TEK603_doInit') if($hash->{STATE} eq 'disconnected'); + + # This is relevant for windows/USB only + my $po = $hash->{USBDev}; + my ($BlockingFlags, $InBytes, $OutBytes, $ErrorFlags) = $po->status; + return ($InBytes > 0); +} + +sub TEK603_read($) { + my ($hash) = @_; + my $name = $hash->{NAME}; + + my $buf = DevIo_SimpleRead($hash); + return '' if(!defined($buf)); + + # convert to hex string + $hash->{buffer} = unpack ('H*', $buf); + + my $lenght = hex(substr($hash->{buffer},4,4))*2; + #my $cmd = substr($hash->{buffer},8,2); + #my $flags = substr($hash->{buffer},10,2); + my $time = sprintf '%02d:%02d:%02d', hex(substr($hash->{buffer},12,2)), hex(substr($hash->{buffer},14,2)), hex(substr($hash->{buffer},16,2)); + #my $epromStart = hex(substr($hash->{buffer},18,4)); + #my $epromEnd = hex(substr($hash->{buffer},22,4)); + my $payloadlenght = $lenght - 26 - 4; + my $payload = substr($hash->{buffer},26,$payloadlenght); + #my $crc = substr($hash->{buffer},26 + $payloadlenght,4); + + # payload + my $temp = sprintf '%.2f', ((hex(substr($payload, 0,2)) - 40 - 32) / 1.8); + my $Ullage = hex(substr($payload,2,2)) * 256 + hex(substr($payload,4,2)); + my $RemainingUsableLevel= hex(substr($payload,6,2)) * 256 + hex(substr($payload,8,2)); + my $TotalUsableCapacity = hex(substr($payload,10,2)) * 256 + hex(substr($payload,12,2)); + + #Log3 $name, 5, $hash->{buffer}; + Log3 $name, 5, "Time:$time Temp:$temp Ullage:$Ullage RemainingUsableLevel:$RemainingUsableLevel TotalUsableCapacity:$TotalUsableCapacity"; + + + readingsBeginUpdate($hash); + readingsBulkUpdate($hash, "Time", $time); + readingsBulkUpdate($hash, "Temperature", $temp); + readingsBulkUpdate($hash, "Ullage", $Ullage); + readingsBulkUpdate($hash, "RemainingUsableLevel", $RemainingUsableLevel); + readingsBulkUpdate($hash, "TotalUsableCapacity", $TotalUsableCapacity); + readingsEndUpdate($hash, 1); +} + + +sub TEK603_reconnect($) { + my ($hash) = @_; + my $name = $hash->{NAME}; + + Log3 $name, 3, "Wrong Data received. We reconnect Device"; + + # Sometime the device sends a lot of waste and we must reconnect. + DevIo_CloseDev($hash); + $hash->{PORTSTATE} = $hash->{STATE}; + + select(undef, undef, undef, 0.1); + DevIo_OpenDev($hash, 0, 'TEK603_doInit'); +} + +1; + +=pod +=begin html + + +

TEK603

+
+ +=end html + +=cut + + +