########################################################################################
#
# OWTEMP.pm
#
# FHEM module to commmunicate with 1-Wire temperature sensors
#
# Attention: This module works as a replacement for the standard 21_OWTEMP.pm,
#            therefore may communicate with the 1-Wire File System OWFS,
#            but also with the newer and more direct OWX module
#
# Prefixes for subroutines of this module:
# OW   = General 1-Wire routines (Martin Fischer, Peter Henning)
# OWFS = 1-Wire file system (Martin Fischer)
# OWX  = 1-Wire bus master interface (Peter Henning)
#
# Martin Fischer, 2011
# Prof. Dr. Peter A. Henning, 2012
# 
# Version 1.01 - February 23, 2012
#   
# Setup bus device in fhem.cfg as
# define <name> OWTEMP [<model>] <ROM_ID> [interval] [alarminterval]
#
# where <name> may be replaced by any name string 
#     
#       <model> is a 1-Wire device type. If omitted, we assume this to be an
#              DS1820 temperature sensor 
#       <ROM_ID> is a 12 character (6 byte) 1-Wire ROM ID 
#                without Family ID, e.g. A2D90D000800 
#       [interval] is an optional query interval in seconds
#       [alarminterval] as an additional parameter is ignored so far !
#
# Additional attributes are defined in fhem.cfg as
#
# attr <name> offset <float> = a temperature offset added to the temperature reading 
#
########################################################################################
#
#  This programm 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.
#
#  The GNU General Public License can be found at
#  http://www.gnu.org/copyleft/gpl.html.
#  A copy is found in the textfile GPL.txt and important notices to the license
#  from the author is found in LICENSE.txt distributed with these scripts.
#
#  This script 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.
#
########################################################################################
package main;

#-- Prototypes to make komodo happy
use vars qw{%attr %defs};
use strict;
use warnings;
sub Log($$);

#-- declare variables
my $ownet;
my %gets    = ();
my %sets    = ();
my %updates = ();

#-- temperature globals
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"     => "",
  "temperature" => "",
  "temphigh"    => "",
  "templow"     => ""
  #,
  #"type"        => "",
);

%sets = (
  #-- obsolete "alias"         => "",
  "temphigh"      => "",
  "templow"       => "",
  "interval"      => ""
  #-- taken out into I/O-Device parameters,
  #"alarminterval" => "",
);

%updates = (
  "present"     => "",
  "temperature" => "",
  "templow"     => "",
  "temphigh"    => "",
);

my %dummy = (
  "crc8"         => "4D",
  "alias"        => "dummy",
  "locator"      => "FFFFFFFFFFFFFFFF",
  "power"        => "0",
  "present"      => "1",
  "temphigh"     => "75",
  "templow"      => "10",
  "type"         => "DS18S20",
  "warnings"     => "none",
);

########################################################################################
#
# The following subroutines in alphabetical order are independent of the bus interface
#
# Prefix = OWTEMP
#
#########################################################################################
#
# OWTEMP_Define - Implements DefFn function
# 
# Parameter hash = hash of device addressed, def = definition string
#
########################################################################################

sub OWTEMP_Define ($$) {
  my ($hash, $def) = @_;
  
  # define <name> OWTEMP [<model>] <id> [interval] [alarminterval]
  # e.g.: define flow OWTEMP 525715020000 300
  my @a = split("[ \t][ \t]*", $def);
  
  my ($name,$model,$id,$interval,$alarminterval,$scale,$ret);
  
  #-- default
  $name          = $a[0];
  $interval      = 300;
  $scale         = "";
  $ret           = "";

  #-- check syntax
  return "OWTEMP: Wrong syntax, must be define <name> OWTEMP [<model>] <id> [interval] [alarminterval]"
       if(int(@a) < 2 || int(@a) > 6);
       
  #-- check if this is an old style definition, e.g. <model> is missing
  my $a2 = lc($a[2]);
  my $a3 = defined($a[3]) ? lc($a[3]) : "";
  if(  ($a2 eq "none") || ($a2 =~ m/^[0-9|a-f]{12}$/) ) {
    $model         = "DS1820";
    $id            = $a[2];
    if(int(@a)>=4) { $interval = $a[3]; }
    Log 1, "OWTEMP: Parameter [alarminterval] is obsolete now - must be set with I/O-Device"
      if(int(@a) == 5);
  } elsif(  ($a3 eq "none") || ($a3 =~ m/^[0-9|a-f]{12}$/) ) {
    $model         = $a[2];
    return "OWTEMP: Wrong 1-Wire device model $model"
      if( $model ne "DS1820");
    $id            = $a[3];
    if(int(@a)>=5) { $interval = $a[4]; }
    Log 1, "OWTEMP: Parameter [alarminterval] is obsolete now - must be set with I/O-Device"
      if(int(@a) == 6);
  } 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 !
  #-- define device internals
  $hash->{ALARM}      = 0;
  $hash->{INTERVAL}   = $interval;
  $hash->{ROM_ID}     = "10.".$id."00";
  $hash->{OW_ID}      = $id;
  $hash->{OW_FAMILY}  = 10;
  $hash->{PRESENT}    = 0;

  $modules{OWTEMP}{defptr}{$id} = $hash;

  AssignIoPort($hash);
  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}.")";
    foreach my $r (sort keys %gets) {
      $hash->{READINGS}{$r}{TIME} = $now;
      $hash->{READINGS}{$r}{VAL}  = $dummy{$r};
      Log 4, "OWTEMP: $hash->{NAME} $r: ".$dummy{$r};
    }
  #-- Initial readings temperature sensor
  } else {
    $hash->{READINGS}{temp}{VAL}      = 0.0;
    $hash->{READINGS}{templow}{VAL}   = 0.0;
    $hash->{READINGS}{temphigh}{VAL}  = 0.0;
    $hash->{READINGS}{temp}{TIME}     = "";
    $hash->{READINGS}{templow}{TIME}  = "";
    $hash->{READINGS}{temphigh}{TIME} = "";
    $hash->{STATE}                    = "Defined";
    Log 3, "OWTEMP: Device $name defined."; 
  }  
  # start timer for updates
  InternalTimer(time()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $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 ";
  }
  
########################################################################################
#
# OWTEMP_Get - Implements GetFn function 
#
#  Parameter hash = hash of device addressed, a = argument array
#
########################################################################################

sub OWTEMP_Get($@) {
  my ($hash, @a) = @_;
  my $name  = $hash->{NAME};
  my $ret;

  #-- check argument
  return "OWTEMP: Get with unknown argument $a[1], choose one of ".join(",", sort keys %gets)
    if(!defined($gets{$a[1]}));
  #-- check syntax
  return "OWTEMP: Get argument is missing @a"
    if(int(@a) != 2);

  # define vars
  my $reading = $a[1];
  my $value = undef;

  # get interval
  if($a[1] eq "interval") {
    $value = $hash->{INTERVAL};
     return "$a[0] $reading => $value";
  } 
  
  # get present
  if($a[1] eq "present") {
    $value = $hash->{PRESENT};
     return "$a[0] $reading => $value";
  } 

  #-- Get other values according to interface type
  my $interface= $hash->{IODev}->{TYPE};
   #-- OWX interface
  if( $interface eq "OWX" ){
    #-- not different from getting all values ..
    $ret = OWXTEMP_GetValues($hash);
  #-- OWFS interface
  }elsif( $interface eq "OWFS" ){
    $ret = OWFSTEMP_GetValues($hash);
  #-- Unknown interface
  }else{
    return "OWTEMP: Get with wrong IODev type $interface";
  }
  
  #-- process results
  my $tn = TimeNow();
  
  #-- correct for proper offset
  $owg_temp += $attr{$name}{offset} if ($attr{$name}{offset} );
  #-- Test for alarm condition
  if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){
    $hash->{STATE} = "Alarmed";
  } else {
    $hash->{STATE} = "Normal";
  }
  
  #-- put into READINGS
  $hash->{READINGS}{temp}{VAL}      = $owg_temp;
  $hash->{READINGS}{temp}{TIME}     = $tn;
  $hash->{READINGS}{templow}{VAL}   = $owg_tl;
  $hash->{READINGS}{templow}{TIME}  = $tn;
  $hash->{READINGS}{temphigh}{VAL}  = $owg_th;
  $hash->{READINGS}{temphigh}{TIME} = $tn;
  
  #-- return the special reading
  $reading = "temp" if( $reading eq "temperature");
  if(defined($hash->{READINGS}{$reading})) {
    $value = $hash->{READINGS}{$reading}{VAL};
  }
 if(!defined($value)) {
    Log GetLogLevel($name,4), "OWTEMP: Can't get value for $name.$reading";
    return "OWTEMP: Can't get value for $name.$reading";
  }
  return "OWTEMP: $name.$reading => $value";
}

#######################################################################################
#
# OWTEMP_GetUpdate - Updates the reading from one device
#
# Parameter hash = hash of device addressed
#
########################################################################################

sub OWTEMP_GetUpdate($@) {
  my $hash  = shift;
  
  my $name  = $hash->{NAME};
  my $model = $hash->{OW_MODEL};
  my $owx_dev  = $hash->{ROM_ID};
    my $now     = TimeNow();
  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";

  my $interface= $hash->{IODev}->{TYPE};
  #-- real sensor
  if($hash->{OW_ID} ne "none") {
    $hash->{PRESENT}    = 0;
    #-- Get values according to interface type
    my $interface= $hash->{IODev}->{TYPE};
    if( $interface eq "OWX" ){
      $ret = OWXTEMP_GetValues($hash);
    }elsif( $interface eq "OWFS" ){
      $ret = OWFSTEMP_GetValues($hash);
    }else{
      return "OWTEMP: GetUpdate with wrong IODev type $interface";
    }
  #-- dummy sensor
  } else {
    $owg_temp = sprintf("%.4f",rand(85));
    $dummy{temperature} = $owg_temp;
    $dummy{present}     = "1";
    $hash->{PRESENT}    = 1;
  }
  
  #-- process results
  my $tn = TimeNow();
  
  #-- correct for proper offset
  $owg_temp += $attr{$name}{offset} if ($attr{$name}{offset} );
  #-- Test for alarm condition
  if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){
    $hash->{STATE} = "Alarmed";
  } else {
    $hash->{STATE} = "Normal";
  }
  
  #-- put into READINGS
  $hash->{READINGS}{temp}{VAL}      = $owg_temp;
  $hash->{READINGS}{temp}{TIME}     = $tn;
  $hash->{READINGS}{templow}{VAL}   = $owg_tl;
  $hash->{READINGS}{templow}{TIME}  = $tn;
  $hash->{READINGS}{temphigh}{VAL}  = $owg_th;
  $hash->{READINGS}{temphigh}{TIME} = $tn;
  
  #--logging
  my $rv = sprintf "temp: %3.1f templow: %3.0f temphigh: %3.0f",$owg_temp,$owg_tl,$owg_th;
  Log 5, $rv;
  $hash->{CHANGED}[0] = $rv;
  DoTrigger($name, undef);
  
  return undef;
}

#######################################################################################
#
# OWTEMP_Set - Set values for one device
#
#  Parameter hash = hash of device addressed
#            a = argument string
#
########################################################################################

sub OWTEMP_Set($@) {
  my ($hash, @a) = @_;
  my $name  = $hash->{NAME};
  my $model = $hash->{OW_MODEL};
  my $path  = "10.".$hash->{OW_ID};

  #-- for the selector: which values are possible
  return join(" ", sort keys %sets) if(@a == 2);
  #-- check syntax
  return "OWTEMP: Set needs one parameter"
    if(int(@a) != 3);
  #-- check argument
  return "OWTEMP: Set with unknown argument $a[1], choose one of ".join(",", sort keys %sets)
      if(!defined($sets{$a[1]}));
      
  #-- define vars
  my $key   = $a[1];
  my $value = $a[2];
  my $ret   = undef;

  #-- set warnings
  if($key eq "templow" || $key eq "temphigh") {
    # check range
    return "OWTEMP: Set with wrong temperature value, range is  -55°C - 125°C"
      if(int($value) < -55 || int($value) > 125);
  }

 #-- set new timer interval
  if($key eq "interval") {
    # check value
    return "OWTEMP: Set with too short time value, interval must be > 10"
      if(int($value) < 10);
    # update timer
    $hash->{INTERVAL} = $value;
    RemoveInternalTimer($hash);
    InternalTimer(gettimeofday()+$hash->{INTERVAL}, "OWTEMP_GetUpdate", $hash, 1);
    return undef;
  }

  #-- set other values depending on interface type
  Log 4, "OWTEMP: Set $hash->{NAME} $key $value";
  
  my $interface= $hash->{IODev}->{TYPE};
  #-- real sensor
  if($hash->{OW_ID} ne "none") {
    #-- OWX interface
    if( $interface eq "OWX" ){
      $ret = OWXTEMP_SetValues($hash,@a);
      return $ret
        if(defined($ret));
    #-- OWFS interface
    }elsif( $interface eq "OWFS" ){
      $ret = OWFSTEMP_SetValues($hash,@a);
      return $ret
        if(defined($ret));
    } else {
    return "OWTEMP: Set with wrong IODev type $interface";
    }
  #-- dummy sensor
  } else {
      $dummy{$key} = $value;
  }
  
  #-- process results
  my $tn = TimeNow();
  
  #-- correct for proper offset
  $owg_temp += $attr{$name}{offset} if ($attr{$name}{offset} );
  #-- Test for alarm condition
  if( ($owg_temp <= $owg_tl) | ($owg_temp >= $owg_th) ){
    $hash->{STATE} = "Alarmed";
  } else {
    $hash->{STATE} = "Normal";
  }
  
  #-- put into READINGS
  $hash->{READINGS}{temp}{VAL}      = $owg_temp;
  $hash->{READINGS}{temp}{TIME}     = $tn;
  $hash->{READINGS}{templow}{VAL}   = $owg_tl;
  $hash->{READINGS}{templow}{TIME}  = $tn;
  $hash->{READINGS}{temphigh}{VAL}  = $owg_th;
  $hash->{READINGS}{temphigh}{TIME} = $tn;
  
  return undef;
}

########################################################################################
#
# OWTEMP_Undef - Implements UndefFn function
#
# Parameter hash = hash of device addressed
#
########################################################################################

sub OWTEMP_Undef ($) {
  my ($hash) = @_;
  #delete($modules{OWTEMP}{defptr}{$hash->{CODE}});
  RemoveInternalTimer($hash);
  return undef;
}

########################################################################################
#
# The following subroutines in alphabetical order are only for a 1-Wire bus connected 
# via OWFS
#
# Prefix = OWFSTEMP
#
########################################################################################
#
# OWFSTEMP_GetValues - Get reading from one device
#
# Parameter hash = hash of device addressed
#
########################################################################################

sub OWFSTEMP_GetValues($)
{
  my ($hash) = @_;

  my $ret = OW::get("/uncached/10.".$hash->{OW_ID}."/temperature");
  if( defined($ret) ) {
    $hash->{PRESENT} = 1;
    $owg_temp = $ret;
    $owg_th   = OW::get("/uncached/10.".$hash->{OW_ID}."/temphigh");
    $owg_tl   = OW::get("/uncached/10.".$hash->{OW_ID}."/templow");
  } else {
    $hash->{PRESENT} = 0;
    $owg_temp = 0.0;
    $owg_th   = 0.0;
    $owg_tl   = 0.0;
  }

  return undef;
  
}

#######################################################################################
#
# OWFSTEMP_SetValues - Implements SetFn function
# 
# Parameter hash = hash of the device addressed here, a = argument array
#
########################################################################################

sub OWFSTEMP_SetValues($@) {
  my ($hash, @a) = @_;
  
  #-- define vars
  my $key   = $a[1];
  my $value = $a[2];
  
  return OW::put("10.".$hash->{OW_ID}."/$key",$value);
}

########################################################################################
#
# The following subroutines in alphabetical order are only for a 1-Wire bus connected 
# directly to the FHEM server
#
# Prefix = OWXTEMP
#
########################################################################################
#
# OWXTEMP_GetValues - Get reading from one device
#
# Parameter hash = hash of device addressed
#
########################################################################################

sub OWXTEMP_GetValues($) {

  my ($hash) = @_;
  
  #-- For now, switch of temperature conversion command
  my $con=0;
  
  #-- ID of the device
  my $owx_dev = $hash->{ROM_ID};
  my $owx_rnf = substr($owx_dev,3,12);
  my $owx_f   = substr($owx_dev,0,2);
  
  #-- hash of the busmaster
  my $master = $hash->{IODev};
  
  my ($i,$j,$k);

  #-- 8 byte 1-Wire device address
  my @owx_ROM_ID  =(0,0,0,0 ,0,0,0,0); 
  #-- from search string to byte id
  my $devs=$owx_dev;
  $devs=~s/\.//g;
  for($i=0;$i<8;$i++){
     $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2));
  }

  #-- if the conversion has not been called before 
  if( $con==1 ){
    OWX_Reset($master);
    #-- issue the match ROM command \x55 and the start conversion command
    my $select=sprintf("\x55%c%c%c%c%c%c%c%c\x44",@owx_ROM_ID); 
    if( OWX_Block($master,$select) eq 0 ){
      return "OWXTEMP: Device $owx_dev not accessible";
    } 
    #-- conversion needs some 950 ms
    sleep(1);
  }

  #-- NOW ask the specific device 
  OWX_Reset($master);
  #-- issue the match ROM command \x55 and the read scratchpad command \xBE
  my $select=sprintf("\x55%c%c%c%c%c%c%c%c\xBE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF",
     @owx_ROM_ID); 
     
  my $res=OWX_Block($master,$select);
  #-- process results
  if( $res eq 0 ){
    return "OWXTEMP: Device $owx_dev not accessible in 2nd step"; 
  }
  my $res2 = "====> OWXTEMP Received ";
  for(my $i=0;$i<19;$i++){  
    my $j=int(ord(substr($res,$i,1))/16);
    my $k=ord(substr($res,$i,1))%16;
    $res2.=sprintf "0x%1x%1x ",$j,$k;
  }
  Log 1, $res2;
     
  #-- process results
  my  @data=split(//,$res);
  if ( (@data == 19) && (ord($data[17])>0) ){
    my $count_remain = ord($data[16]);
    my $count_perc   = ord($data[17]);
    my $delta        = -0.25 + ($count_perc - $count_remain)/$count_perc;
  
    #-- 2's complement form = signed bytes
    if( $data[11] eq "\x00" ){
      $owg_temp = int(ord($data[10])/2) + $delta;
    } else {
      $owg_temp = 128-(int(ord($data[10])/2) + $delta);
    }
    $owg_th = ord($data[12]) > 127 ? 128-ord($data[12]) : ord($data[12]);
    $owg_tl = ord($data[13]) > 127 ? 128-ord($data[13]) : ord($data[13]);
    
    Log 1, "====> OWXTEMP Conversion result is temp = $owg_temp, delta $delta";
   
    return undef;
  } else {
    return "OWXTEMP: Device $owx_dev returns invalid data";
  }
}

#######################################################################################
#
# OWXTEMP_SetValues - Implements SetFn function
# 
# Parameter hash = hash of the device addressed here, a = argument array
#
########################################################################################

sub OWXTEMP_SetValues($@) {
  my ($hash, @a) = @_;
  
  my $name = $hash->{NAME};
 
  #-- ID of the device
  my $owx_dev = $hash->{ROM_ID};
  my $owx_rnf = substr($owx_dev,3,12);
  my $owx_f   = substr($owx_dev,0,2);
  
  #-- hash of the busmaster
  my $master = $hash->{IODev};
 
  my ($i,$j,$k);

  #-- 8 byte 1-Wire device address
  my @owx_ROM_ID  =(0,0,0,0 ,0,0,0,0); 
  #-- from search string to byte id
  my $devs=$owx_dev;
  $devs=~s/\.//g;
  for($i=0;$i<8;$i++){
     $owx_ROM_ID[$i]=hex(substr($devs,2*$i,2));
  }
  
  # define vars
  my $key   = $a[1];
  my $value = $a[2];
  
  #-- get the old values
  $owg_temp = $hash->{READINGS}{temp}{VAL};
  $owg_tl   = $hash->{READINGS}{templow}{VAL};
  $owg_th   = $hash->{READINGS}{temphigh}{VAL};
  
  $owg_tl = int($value) if( $key eq "templow" );
  $owg_th = int($value) if( $key eq "temphigh" );

  #-- put into 2's complement formed (signed byte)
  my $tlp = $owg_tl < 0 ? 128 - $owg_tl : $owg_tl; 
  my $thp = $owg_th < 0 ? 128 - $owg_th : $owg_th; 
  
  OWX_Reset($master);
  
  #-- issue the match ROM command \x55 and the write scratchpad command \x4E,
  #   followed by the write EEPROM command \x48
  #
  #   so far writing the EEPROM does not work properly.
  #   1. \x48 directly appended to the write scratchpad command => command ok, no effect on EEPROM
  #   2. \x48 appended to match ROM => command not ok. 
  #   3. \x48 sent by WriteBytePower after match ROM => command ok, no effect on EEPROM
  
  my $select=sprintf("\x55%c%c%c%c%c%c%c%c\x4E%c%c\x48",@owx_ROM_ID,$thp,$tlp); 
  my $res=OWX_Block($master,$select);

  if( $res eq 0 ){
    return "OWXTEMP: Device $owx_dev not accessible"; 
  } 
  
  #-- issue the match ROM command \x55 and the copy scratchpad command \x48
  #$select=sprintf("\x55%c%c%c%c%c%c%c%c",@owx_ROM_ID); 
  #$res=OWX_Block($hash,$select);
  #$res=OWX_WriteBytePower($hash,"\x48");

  #if( $res eq 0 ){
  #  Log 3, "OWXTEMP_SetTemp: Device $romid not accessible in the second step"; 
  #  return 0;
  #} 
  
  DoTrigger($name, undef) if($init_done);
  return undef;
}



1;