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

Kleiner Änderungen, neues Modul 21_OWAD.pm

git-svn-id: https://svn.fhem.de/fhem/trunk@1306 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
pahenning 2012-02-29 12:14:25 +00:00
parent 84ee5a4cd4
commit 716f7befec
3 changed files with 1210 additions and 165 deletions

View File

@ -6,7 +6,7 @@
# via an active DS2480/DS2490/DS9097U bus master interface or
# via a passive DS9097 interface
#
# Version 1.01 - February 23, 2012
# Version 1.02 - February 29, 2012
#
# Prof. Dr. Peter A. Henning, 2011
#
@ -203,9 +203,13 @@ sub OWX_Convert($) {
#
# OWX_CRC - Check the CRC8 code of a device address in @owx_ROM_ID
#
# Parameter romid = if not zero, return the CRC8 value instead of checking it
#
########################################################################################
sub OWX_CRC () {
sub OWX_CRC ($) {
my ($romid) = @_;
my @crc8_table = (
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
@ -225,13 +229,75 @@ sub OWX_CRC () {
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53);
my $crc8=0;
for(my $i=0; $i<8; $i++){
$crc8 = $crc8_table[ $crc8 ^ $owx_ROM_ID[$i] ];
}
return $crc8;
if( $romid eq "0" ){
for(my $i=0; $i<8; $i++){
$crc8 = $crc8_table[ $crc8 ^ $owx_ROM_ID[$i] ];
}
return $crc8;
} else {
#-- from search string to byte id
$romid=~s/\.//g;
for(my $i=0;$i<8;$i++){
$owx_ROM_ID[$i]=hex(substr($romid,2*$i,2));
}
for(my $i=0; $i<7; $i++){
$crc8 = $crc8_table[ $crc8 ^ $owx_ROM_ID[$i] ];
}
return $crc8;
}
}
########################################################################################
#
# OWX_CRC16 - Calculate the CRC16 code of a string
#
# Parameter crc - previous CRC code, c next character
#
########################################################################################
sub OWX_CRC16($) {
my ($data) = @_;
my $crc=0;
for( my $i=0; $i<length($data); $i++) {
$crc = OWX_DOCRC16($crc,substr($data,$i,1));
printf "=====> New CRC value = %x",$crc;
}
return $crc;
}
sub OWX_DOCRC16($$) {
my ($crc,$c) = @_;
#-- polynomial for x^16 + x^15 + x^2 + 1
my $mask = 0xA001;
my $i;
for($i=0;$i<8;$i++) {
if(($crc ^ ord($c)) & 1) {
$crc=($crc>>1)^$mask;
} else {
$crc>>=1;
}
$c>>=1;
}
return ($crc);
}
#//-------------------------------------------------------------------#
#Aufruf der Funktion im Programm:
#{
#//...
# unsigned int DEVICE_CRC16=0;
# DEVICE_CRC16 = calcCRC16r (DEVICE_CRC16,chr,0xA001);
#//...
#}
########################################################################################
#
@ -312,26 +378,39 @@ sub OWX_Define ($$) {
sub OWX_Detect ($) {
my ($hash) = @_;
my ($i,$j,$k);
my ($i,$j,$k,$l,$res,$ret);
#-- timing byte for DS2480
OWX_Query_2480($hash,"\xC1");
#-- write 1-Wire bus (Fig. 2 of Maxim AN192)
my $res = OWX_Query_2480($hash,"\x17\x45\x5B\x0F\x91");
#-- process 4/5-byte string for detection
if( $res eq "\x16\x44\x5A\x00\x93"){
Log 1, "OWX: 1-Wire bus master DS2480 detected for the first time";
$owx_interface="DS2480";
return 1;
} elsif( $res eq "\x17\x45\x5B\x0F\x91"){
Log 1, "OWX: 1-Wire bus master DS2480 re-detected";
$owx_interface="DS2480";
return 1;
} elsif( ($res eq "\x17\x0A\x5B\x0F\x02") || ($res eq "\x00\x17\x0A\x5B\x0F\x02") ){
Log 1, "OWX: Passive 1-Wire bus interface DS9097 detected";
$owx_interface="DS9097";
return 1;
} else {
#-- Max 4 tries to detect an interface
for($l=0;$l<4;$l++) {
#-- write 1-Wire bus (Fig. 2 of Maxim AN192)
$res = OWX_Query_2480($hash,"\x17\x45\x5B\x0F\x91");
#-- process 4/5-byte string for detection
if( $res eq "\x16\x44\x5A\x00\x93"){
Log 1, "OWX: 1-Wire bus master DS2480 detected for the first time";
$owx_interface="DS2480";
$ret=1;
} elsif( $res eq "\x17\x45\x5B\x0F\x91"){
Log 1, "OWX: 1-Wire bus master DS2480 re-detected";
$owx_interface="DS2480";
$ret=1;
} elsif( ($res eq "\x17\x0A\x5B\x0F\x02") || ($res eq "\x00\x17\x0A\x5B\x0F\x02") ){
Log 1, "OWX: Passive 1-Wire bus interface DS9097 detected";
$owx_interface="DS9097";
$ret=1;
} else {
$ret=0;
}
last
if( $ret==1 );
Log 1, "OWX: Trying again to detect an interface";
#-- sleeping for some time
select(undef,undef,undef,0.5);
}
if( $ret == 0 ){
my $ress = "OWX: No 1-Wire bus interface detected, answer was ";
for($i=0;$i<length($res);$i++){
$j=int(ord(substr($res,$i,1))/16);
@ -339,8 +418,8 @@ sub OWX_Detect ($) {
$ress.=sprintf "0x%1x%1x ",$i,$j,$k;
}
Log 1, $ress;
return 0;
}
return $ret;
}
########################################################################################
@ -406,6 +485,14 @@ sub OWX_Discover ($) {
CommandAttr (undef,"$name IODev $hash->{NAME}");
CommandAttr (undef,"$name room OWX");
push(@owx_names,$name);
} elsif( $owx_f eq "20" ){
#-- Family 20 = A/D converter, assume DS2450 as default
CommandDefine(undef,"$name OWAD DS2450 $owx_rnf");
$main::defs{$name}{PRESENT}=1;
#-- default room
CommandAttr (undef,"$name IODev $hash->{NAME}");
CommandAttr (undef,"$name room OWX");
push(@owx_names,$name);
} else {
Log 1, "OWX: Undefined device family $owx_f";
}
@ -494,7 +581,7 @@ sub OWX_Initialize ($) {
my ($hash) = @_;
#-- Provider
#$hash->{Clients} = ":OWCOUNT:OWHUB:OWLCD:OWMULTI:OWSWITCH:OWTEMP:";
$hash->{Clients} = ":OWTEMP:";
$hash->{Clients} = ":OWTEMP:OWAD:";
#-- Normal Devices
$hash->{DefFn} = "OWX_Define";
@ -586,7 +673,7 @@ sub OWX_Search ($$) {
return 0;
}
#--check if we really found a device
if( OWX_CRC()!= 0){
if( OWX_CRC(0)!= 0){
#-- reset the search
Log 1, "OWX: Search CRC failed ";
$owx_LastDiscrepancy = 0;
@ -705,25 +792,6 @@ sub OWX_Undef ($$) {
return undef;
}
########################################################################################
#
# OBSOLETE subroutine OWX_Values - stub function for OWX_yy
# Necessary, because at time of first scheduling the OWX_yy subs are not yet knwon
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWX_Values ($) {
my ($hash) = @_;
my $fam;
foreach $fam (@owx_fams) {
}
my $res=OWXTEMP_Values($hash);
return $res;
}
########################################################################################
#
# OWX_Verify - Verify a particular device on the 1-Wire bus
@ -794,14 +862,7 @@ sub OWX_Block_2480 ($$) {
}
#-- write 1-Wire bus as a single string
my $res =OWX_Query_2480($hash,$data2);
#-- process result
if( length($res) == length($data) ){
Log 5, "OWX_Block: OK";
return $res;
} else {
Log 3, "OWX_Block: DAS 2480 failure, received ".length($data)." bytes";
return 0;
}
return $res;
}
########################################################################################
@ -900,7 +961,7 @@ sub OWX_Query_2480 ($$) {
select(undef,undef,undef,0.04);
#-- read the data
my ($count_in, $string_in) = $owx_serport->read(32);
my ($count_in, $string_in) = $owx_serport->read(48);
if( $owx_debug > 1){
my $res = "OWX: Receiving ";
@ -941,7 +1002,7 @@ sub OWX_Reset_2480 ($) {
$cmd = "\xE3";
}
#-- Reset command \xC5
$cmd = $cmd."\xC5";
$cmd = $cmd."\xC1";
#-- write 1-Wire bus
my $res =OWX_Query_2480($hash,$cmd);
#-- process result
@ -1134,13 +1195,7 @@ sub OWX_Block_9097 ($$) {
$res = OWX_TouchByte_9097($hash,ord(substr($data,$i,1)));
$data2 = $data2.chr($res);
}
#-- process result
if( length($data2) == length($data) ){
return $data2;
} else {
Log 3, "OWX: DS9097 block failure, received ".length($data2)." bytes";
return 0;
}
return $data2;
}
########################################################################################
@ -1190,7 +1245,7 @@ sub OWX_Query_9097 ($$) {
select(undef,undef,undef,0.01);
#-- read the data
my ($count_in, $string_in) = $owx_serport->read(32);
my ($count_in, $string_in) = $owx_serport->read(48);
if( $owx_debug > 1){
my $res = "OWX: Receiving ";

File diff suppressed because it is too large Load Diff

View File

@ -16,7 +16,7 @@
# Martin Fischer, 2011
# Prof. Dr. Peter A. Henning, 2012
#
# Version 1.01 - February 23, 2012
# Version 1.02 - February 29, 2012
#
# Setup bus device in fhem.cfg as
# define <name> OWTEMP [<model>] <ROM_ID> [interval] [alarminterval]
@ -52,6 +52,9 @@
# GNU General Public License for more details.
#
########################################################################################
#
# TODO: offset in alarm values
#
package main;
#-- Prototypes to make komodo happy
@ -71,32 +74,18 @@ my $owg_temp=0;
my $owg_th=0;
my $owg_tl=0;
# temperature scale from IODev
my $scale;
%gets = (
#"address" => "",
#"alias" => "",
#"crc8" => "",
#"family" => "10",
#"id" => "",
#"locator" => "",
"interval" => "",
"present" => "",
"interval" => "",
"temperature" => "",
"temphigh" => "",
"templow" => ""
#,
#"type" => "",
);
%sets = (
#-- obsolete "alias" => "",
"interval" => "",
"temphigh" => "",
"templow" => "",
"interval" => ""
#-- taken out into I/O-Device parameters,
#"alarminterval" => "",
"templow" => ""
);
%updates = (
@ -120,11 +109,32 @@ my %dummy = (
########################################################################################
#
# The following subroutines in alphabetical order are independent of the bus interface
# The following subroutines are independent of the bus interface
#
# Prefix = OWTEMP
#
#########################################################################################
########################################################################################
#
# OWTEMP_Initialize
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWTEMP_Initialize ($) {
my ($hash) = @_;
$hash->{DefFn} = "OWTEMP_Define";
$hash->{UndefFn} = "OWTEMP_Undef";
$hash->{GetFn} = "OWTEMP_Get";
$hash->{SetFn} = "OWTEMP_Set";
#offset = a temperature offset added to the temperature reading for correction
#scale = a unit of measure: C/F/K/R
$hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS18S20 loglevel:0,1,2,3,4,5 ".
"offset scale:C,F,K,R";
}
########################################################################################
#
# OWTEMP_Define - Implements DefFn function
#
@ -139,12 +149,12 @@ sub OWTEMP_Define ($$) {
# e.g.: define flow OWTEMP 525715020000 300
my @a = split("[ \t][ \t]*", $def);
my ($name,$model,$id,$interval,$alarminterval,$scale,$ret);
my ($name,$model,$id,$interval,$alarminterval,$ret);
my $tn = TimeNow();
#-- default
$name = $a[0];
$interval = 300;
$scale = "";
$ret = "";
#-- check syntax
@ -171,17 +181,15 @@ sub OWTEMP_Define ($$) {
} else {
return "OWTEMP: $a[0] ID $a[2] invalid, specify a 12 digit value or set it to none for demo mode";
}
#-- 1-Wire ROM identifier in the form "FF.XXXXXXXXXXXX.YY"
#
# Careful: For now this is effectively only 14 characters = 7 byte long and
# must not be passed back to the 1-Wire bus. The 8th byte is the CRC code
# and will be appended in the first call of GetTemperatures
# TODO: should be replaced by a calculation of the CRC value !
# YY must be determined from id
my $crc = sprintf("%02x",OWX_CRC("10.".$id."00"));
#-- define device internals
$hash->{ALARM} = 0;
$hash->{INTERVAL} = $interval;
$hash->{ROM_ID} = "10.".$id."00";
$hash->{ROM_ID} = "10.".$id.$crc;
$hash->{OW_ID} = $id;
$hash->{OW_FAMILY} = 10;
$hash->{PRESENT} = 0;
@ -192,24 +200,15 @@ sub OWTEMP_Define ($$) {
Log 3, "OWTEMP: Warning, no 1-Wire I/O device found for $name."
if(!defined($hash->{IODev}->{NAME}));
#-- get scale from I/O device
$scale = $attr{$hash->{IODev}->{NAME}}{"temp-scale"};
# define scale for temperature values
$scale = "Celsius" if ($scale eq "C");
$scale = "Fahrenheit" if ($scale eq "F");
$scale = "Kelvin" if ($scale eq "K");
$scale = "Rankine" if ($scale eq "R");
$hash->{OW_SCALE} = $scale;
#-- define dummy values for testing
if($hash->{OW_ID} eq "none") {
my $now = TimeNow();
$dummy{address} = $hash->{OW_FAMILY}.$hash->{OW_ID}.$dummy{crc8};
$dummy{family} = $hash->{OW_FAMILY};
$dummy{id} = $hash->{OW_ID};
$dummy{temperature} = "80.0000 (".$hash->{OW_SCALE}.")";
$dummy{temperature} = "80.0000";
foreach my $r (sort keys %gets) {
$hash->{READINGS}{$r}{TIME} = $now;
$hash->{READINGS}{$r}{TIME} = $tn;
$hash->{READINGS}{$r}{VAL} = $dummy{$r};
Log 4, "OWTEMP: $hash->{NAME} $r: ".$dummy{$r};
}
@ -224,39 +223,12 @@ sub OWTEMP_Define ($$) {
$hash->{STATE} = "Defined";
Log 3, "OWTEMP: Device $name defined.";
}
# start timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 0);
#-- Start timer for updates
InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 0);
# initialize device
#$ret = OWFS_InitializeDevice($hash);
#return "OWFS Can't initialize Device $name" if (!defined($ret));
#$hash->{STATE} = "Initialized";
#-- InternalTimer blocks if init_done is not true
#my $oid = $init_done;
$hash->{STATE} = "Initialized";
return undef;
}
#########################################################################################
#
# OWTEMP_Initialize
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWTEMP_Initialize ($) {
my ($hash) = @_;
$hash->{DefFn} = "OWTEMP_Define";
$hash->{UndefFn} = "OWTEMP_Undef";
$hash->{GetFn} = "OWTEMP_Get";
$hash->{SetFn} = "OWTEMP_Set";
#offset = a temperature offset added to the temperature reading
$hash->{AttrList}= "IODev do_not_notify:0,1 showtime:0,1 model:DS18S20 loglevel:0,1,2,3,4,5 ".
"offset ";
}
########################################################################################
#
@ -268,8 +240,12 @@ sub OWTEMP_Initialize ($) {
sub OWTEMP_Get($@) {
my ($hash, @a) = @_;
my $name = $hash->{NAME};
my $ret;
my $reading = $a[1];
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $value = undef;
my $ret = "";
#-- check argument
return "OWTEMP: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets)
@ -278,17 +254,13 @@ sub OWTEMP_Get($@) {
return "OWTEMP: Get argument is missing @a"
if(int(@a) != 2);
# define vars
my $reading = $a[1];
my $value = undef;
# get interval
#-- get interval
if($a[1] eq "interval") {
$value = $hash->{INTERVAL};
return "$a[0] $reading => $value";
}
# get present
#-- get present
if($a[1] eq "present") {
$value = $hash->{PRESENT};
return "$a[0] $reading => $value";
@ -342,38 +314,26 @@ sub OWTEMP_Get($@) {
#######################################################################################
#
# OWTEMP_GetUpdate - Updates the reading from one device
# OWTEMP_GetValues - Updates the readings from device
#
# Parameter hash = hash of device addressed
#
########################################################################################
sub OWTEMP_GetUpdate($@) {
my $hash = shift;
sub OWTEMP_GetValues($@) {
my $hash = shift;
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $owx_dev = $hash->{ROM_ID};
my $now = TimeNow();
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $value = "";
my $temp = "";
my $ret = "";
my $count = 0;
#-- define warnings
my $warn = "none";
$hash->{ALARM} = "0";
#-- restart timer for updates
#if(!$hash->{LOCAL}) {
RemoveInternalTimer($hash);
InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 1);
#}
# set new state
#($temp,undef) = split(" ",$hash->{READINGS}{temperature}{VAL});
#$warn = $hash->{READINGS}{warnings}{VAL};
#$hash->{STATE} = "T: $temp W: $warn";
RemoveInternalTimer($hash);
InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 1);
my $interface= $hash->{IODev}->{TYPE};
#-- real sensor
@ -386,7 +346,7 @@ sub OWTEMP_GetUpdate($@) {
}elsif( $interface eq "OWFS" ){
$ret = OWFSTEMP_GetValues($hash);
}else{
return "OWTEMP: GetUpdate with wrong IODev type $interface";
return "OWTEMP: GetValues with wrong IODev type $interface";
}
#-- dummy sensor
} else {
@ -427,7 +387,7 @@ sub OWTEMP_GetUpdate($@) {
#######################################################################################
#
# OWTEMP_Set - Set values for one device
# OWTEMP_Set - Set on values for device
#
# Parameter hash = hash of device addressed
# a = argument string
@ -436,6 +396,7 @@ sub OWTEMP_GetUpdate($@) {
sub OWTEMP_Set($@) {
my ($hash, @a) = @_;
my $name = $hash->{NAME};
my $model = $hash->{OW_MODEL};
my $path = "10.".$hash->{OW_ID};
@ -469,7 +430,7 @@ sub OWTEMP_Set($@) {
# update timer
$hash->{INTERVAL} = $value;
RemoveInternalTimer($hash);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 1);
InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWTEMP_GetValues", $hash, 1);
return undef;
}
@ -530,7 +491,8 @@ sub OWTEMP_Set($@) {
sub OWTEMP_Undef ($) {
my ($hash) = @_;
#delete($modules{OWTEMP}{defptr}{$hash->{CODE}});
delete($modules{OWTEMP}{defptr}{$hash->{OW_ID}});
RemoveInternalTimer($hash);
return undef;
}
@ -608,7 +570,7 @@ sub OWXTEMP_GetValues($) {
my ($hash) = @_;
#-- For now, switch of temperature conversion command
#-- For now, switch off temperature conversion command
my $con=0;
#-- ID of the device