package RFC::Templog;
#$Id: Templog.pm,v 1.107 2025/06/14 05:50:45 sqko Exp $
#######################################################################
#
#
#     RFC::Templog
#
#
#  This class manages temperature logging as usually more than one measuremnt 
#  is needed to correctly measure temperatures using thermocouples and/or
#  PT-type resistance measurements
#
#  To obtain a Templog instance call the constructor as shown below:
#
#  $id = RFC::Templog->new($name,$rig) 
#
#  The Templog class defines no new functions.
#
#######################################################################

use strict;
use warnings;
use RFC::BaseDevice;
use RFC::Main qw();
use RFC::Header;
use File::stat;
use File::Copy;
use RFC::Cache;
our @ISA = qw(RFC::BaseDevice);

BEGIN {
    use Exporter ();
    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
    $VERSION = 1.0;
    %EXPORT_TAGS = (
        'standard'=>[],
                    );
    Exporter::export_ok_tags('standard');
    Exporter::export_tags('standard');
    @ISA = qw(Exporter);
}

sub new()
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_html_template'} = 'Templog.tt';
    $self->{'_mode'} = 'Readonly';
    my @hide_tags = ();
    $self->{'_reload_tags'} = ['class','type','mode','channel_name','cold_junction_name','internal_compensation','callibration_file','lead_res_name','cj_type'];
    $self->{'_setup_tags'} = ['mode','channel_name','type','internal_compensation','callibration_file','cj_type','cold_junction_name','cold_junction_device','cj_temp','lead_res_name','lead_res','lead_res_input_type','title','show_plot','use_cache','unit'];
    $self->{'_legacy_tags'} = ['mode','channel_name','channel','channel_input_type','channel_tty','channel_address','type','internal_compensation','callibration_file','cold_junction_name','cold_junction_device','cj_channel','cj_channel_input_type','cj_channel_tty','cj_channel_address','cj_type','cj_temp','lead_res_name','lead_res','lead_res_input_type','lead_res_tty','lead_res_address','title','show_plot','use_cache','unit'];
    $self->{'_desc'} = {
	'unit' => 'Temperuature scale (Celcius of Kelvin)',
        'mode' => 'Device control mode',
	'channel_name' => 'Input device name',
        'channel' => 'Input device channel, only used if no channel name. Note that the measure channel must report the value in either mV (for thermocouples) or Ohm (for resistive elements such as pt1000 or similar',
	'channel_input_type' => 'Input device type , only used if no channel name',
	'channel_tty' => 'Input device communication device, only used if no device name and device input type is not Keithley',
	'channel_address' => 'Input device address, only used if no device name and device input type is not Keithley',
	'type' => 'Sensor type',
	'offset' => 'Voltage offset added to input device value (mV)',
	'internal_compensation' => 'Switch for controling if the input device reports raw voltage or does internal compensation, thus reporting temperatures directly',
	'cold_junction_name' => 'Name of cold junction input device if using raw input (in conjuction with resistance input device)',
        'cold_junction_device' => 'Name of temperature log device for determining cold junction temperature',
        'cj_channel' => 'Cold junction device channel, only used if no cold junction name',
	'cj_channel_input_type' => 'Cold junction input type, only used if no cold junction name',
	'cj_channel_tty' => 'Cold junction communication device, only used if no cold junction name and cond junction input type is not Keithley)',
	'cj_channel_address' => 'Cold junction device address, only used if no cold junction name and cond junction input type is not Keithley)',
	'cj_type' => 'Cold junction sensor type',
	'cj_temp' => 'Cold junction temperature (if fixed)',
	'lead_res_name' => 'Lead resistance input device',
	'lead_res' => 'Lead ressistance if fixed value or lead resistance channel if not fixed value',
	'lead_res_input_type' => 'Lead resistance input device type',
	'lead_res_tty' => 'Lead resistance input device communication device, only used if no lead ressistance name and lead resistance input type is not Keithley',
	'lead_res_address' => 'Lead resistance input device device address, only used if no lead ressistance name and lead resistance input type is not Keithley',
	'callibration_file' => 'File name of callibration file if custom callibration file is to be used for calculations (Default is NIST tables)',
	'title' => 'Optional device title',
        'use_cache'=>'Determines if persisten caching of read values is allowed',
    };
    $self->{'_default'} = {
	'unit' => 'C',
        'mode' => 'Readonly',
        'channel' => 0,
	'channel_input_type' => 'Keithley',
	'channel_tty' => 'ttyS0',
	'channel_address' => 0,
	'type' => 'S',
	'internal_compensation' => 'No',
        'cold_junction_name' => '',
        'cj_channel' => 0,
	'cj_channel_input_type' => 'Keithley',
	'cj_channel_tty' => 'ttyS0',
	'cj_channel_address' => 0,
	'cj_type' => 'pt1000',
	'cj_temp' => 25,
	'lead_res' => 0,
	'offset' => 0,
	'lead_res_name' => '',
	'lead_res_input_type' => 'fixed_value',
	'lead_res_tty' => 'ttyS0',
	'lead_res_address' => 0,
	'callibration_file' => 'DEFAULT',
        'show_plot'=>'Yes',
        'use_cache'=>'No',
    };
    $self->{'_readstring_furnace'} = 1;
    $self->{'_channel_device'} = undef;
    $self->{'_cj_channel_device'} = undef;
    $self->{'_lead_res_device'} = undef;
    $self->{'_values_unit'} = ['C','K'];
    $self->{'_values_type'} = ['K','N','S','R','B','pt100','pt1000','MCP9700','MCP9701','Thermistor_NTCLE100E3103_B0'];
    $self->{'_values_internal_compensation'} = ['Yes','No'];
    $self->{'_values_cj_type'} = ['fixed','pt100','pt1000','templog_device'];
    $self->{'_values_channel_name'} = [('',$self->{'_rig'}->avaliable_devices('simplechannel'))];
    $self->{'_values_cold_junction_name'} = [('',$self->{'_rig'}->avaliable_devices('simplechannel'))];
    my @list = ();
    foreach my $d ($self->{'_rig'}->avaliable_devices('templog'))
    {
	next if ($d eq $self->name());
	push @list,$d;
    }
    $self->{'_values_cold_junction_device'} = [('',@list)];
    $self->{'_values_lead_res_name'} = [('',$self->{'_rig'}->avaliable_devices('simplechannel'))];
    $self->{'_values_channel_input_type'} = [(RFC::Device::list_SimpleChannel())];
    $self->{'_values_cj_channel_input_type'} = [(RFC::Device::list_SimpleChannel())];
    $self->{'_values_lead_res_input_type'} = ['fixed_value',(RFC::Device::list_SimpleChannel())];
    $self->{'_values_mode'} = ['Readonly'];
    $self->{'_values_callibration_file'} = ['DEFAULT',RFC::Main::spline_user_files()];
    bless $self,$class;
    $self->{'_section'} = 'temp_'.$self->name;
    $self->{'_title'} = $self->get_conf('title');
    foreach my $tag ($self->setup_tags_legacy)
    {
	$self->{'_'.$tag} = $self->get_default($tag);
        my $conf = $self->get_conf($tag);
        $self->{'_'.$tag} = $conf if (defined($conf) && $conf =~ /\w/);
    }
    my $dev = undef;
    if ($self->{'_channel_name'})
    {
	push @hide_tags,'channel_input_type','channel_address','channel_tty';
	$dev = $self->rig->get_device('simplechannel',$self->{'_channel_name'});
	unless ($dev)
	{
	    $dev = $self->rig->init_device('simplechannel',$self->{'_channel_name'});
	    $dev->readstring_ignore(1);
	}
	$self->die("Error: no simplechannel with name '".$self->{'_channel_name'}."' returned from rig ".$self->rig->name) unless ($dev);
    }
    my $devname = 'measure_channel_'.$self->name;
    $dev = $self->rig->get_device('simplechannel',$devname) unless ($dev);
    unless ($dev)
    {
	if ($self->{'_channel_input_type'} !~ /Keithley/i)
	{
	    my $tty = $self->{'_channel_tty'};
	    my $addr = $self->{'_channel_address'};
	    $dev = RFC::Device::new_SimpleChannel($self->rig,$devname,$self->{'_channel_input_type'},$tty,$addr,$self->{'_channel'});
	}
	else
	{
	    $dev = RFC::Device::new_SimpleChannel($self->rig,$devname,$self->{'_channel_input_type'},$self->{'_channel'});
	}
	$dev->readstring_ignore(1);
	$self->rig->register_device('simplechannel',$dev);
    }
    $self->{'_channel_device'} = $dev;
    push @hide_tags,'type','lead_res_name','lead_res_input_type','lead_res_tty','lead_res_address','lead_res','cold_junction_name','cj_temp','cj_type','callibration_file' if ($self->{'_internal_compensation'} =~ /yes/i);
    if ($self->{'_cj_type'} =~ /templog/i)
    {
	push @hide_tags,'lead_res_name','lead_res_input_type','lead_res_tty','lead_res_address','lead_res','cold_junction_name','cj_temp';
	my $cj_name = $self->get_conf('cold_junction_device');
	my $dev = undef;
	$dev = $self->rig->get_device('templog',$cj_name) if ($cj_name);
	unless ($dev || !$cj_name)
	{
	    $dev = $self->rig->init_device('templog',$cj_name);
	    $dev->readstring_ignore(1);
	}
	$self->die("Error: no templog device with name '".$cj_name."' returned from rig ".$self->rig->name) if (!$dev && $cj_name);
	$self->{'_cj_channel_device'} = $dev;	
    }
    else
    {
	push @hide_tags,'cold_junction_device';
	unless ($self->type =~ /pt100|therm|MCP/i || $self->{'_internal_compensation'} =~ /yes/i)
	{
	    if ($self->{'_cj_type'} =~ /fixed/i)
	    {
		push @hide_tags,'lead_res_name','lead_res_input_type','lead_res_tty','lead_res_address','cold_junction_name','lead_res';
	    }
	    else
	    {
		push @hide_tags,'cj_temp';
		my $cj_name = $self->get_conf('cold_junction_name');
		push @hide_tags,'cj_channel_input_type','cj_channel_tty','cj_channel_address' if ($cj_name);
		### Use explicit device name if possible ###
		my $dev = undef;
		$dev = $self->rig->get_device('simplechannel',$cj_name) if ($cj_name);
		unless ($dev || !$cj_name)
		{
		    $dev = $self->rig->init_device('simplechannel',$cj_name);
		    $dev->readstring_ignore(1);
		}
		$self->die("Error: no simplechannel with name '".$cj_name."' returned from rig ".$self->rig->name) if (!$dev && $cj_name);
		my $devname = 'CJ_channel_'.$self->name;
		$dev = $self->rig->get_device('simplechannel',$devname) unless ($dev);
		unless ($dev)
		{
		    if ($self->{'_internal_compensation'} !~ /yes/i)
                    {
			if ($self->{'_cj_channel_input_type'} !~ /Keithley/i)
			{
			    my $tty = $self->{'_cj_channel_tty'};
			my $addr = $self->{'_cj_channel_address'};
			    $dev = RFC::Device::new_SimpleChannel($self->rig,$devname,$self->{'_channel_input_type'},$tty,$addr,$self->{'_cj_channel'});
			}
			else
			{
			    push @hide_tags,'cj_channel_tty';
			    $dev = RFC::Device::new_SimpleChannel($self->rig,$devname,$self->{'_channel_input_type'},$self->{'_cj_channel'});
			}
			$dev->readstring_ignore(1);
			$self->rig->register_device('simplechannel',$dev);
		    }
		}
		$self->{'_cj_channel_device'} = $dev;
	    }
	}
	if (($self->{'_lead_res_input_type'} !~ /fixed_value/i && $self->{'_cj_type'} !~ /templog/i) || $self->get_conf('lead_res_name'))
	{
	    my $lead_name = $self->get_conf('lead_res_name');
	    push @hide_tags,'lead_res_input_type','lead_res_tty','lead_res_address' if ($lead_name);
	    ### Use explicit device name if possible ###
	    my $dev = undef;
	    $dev = $self->rig->get_device('simplechannel',$lead_name) if ($lead_name);
	    unless ($dev || !$lead_name)
	    {
		$dev = $self->rig->init_device('simplechannel',$lead_name);
		$dev->readstring_ignore(1);
	    }
	    $self->die("Error: no simplechannel with name '".$lead_name."' returned from rig ".$self->rig->name) if (!$dev && $lead_name);
	    my $devname = 'Lead_res_'.$name;
	    $dev = $self->rig->get_device('simplechannel',$devname) unless ($dev);
	    unless ($dev)
	    {
		if ($self->{'_internal_compensation'} !~ /yes/i)
		{
		    if ($self->{'_lead_res_input_type'} !~ /Keithley/i)
		    {
			my $tty = $self->{'_lead_res_tty'};
			my $addr = $self->{'_lead_res_address'};
			$dev = RFC::Device::new_SimpleChannel($self->rig,$devname,$self->{'_lead_res_input_type'},$tty,$addr,$self->{'_lead_res'});
		    }
		    else
		    {
			push @hide_tags,'lead_res_tty';
			$dev = RFC::Device::new_SimpleChannel($self->rig,$devname,$self->{'_lead_res_input_type'},$self->{'_lead_res'});
		    }
		    $dev->readstring_ignore(1);
		    $self->rig->register_device('simplechannel',$dev);
		}
	    }
	    $self->{'_lead_res_device'} = $dev;
	    push @hide_tags,'lead_res';
	}
	push @hide_tags,'type','internal_compensation' if ($self->{'_callibration_file'} && $self->{'_callibration_file'} !~ /default/i);
	if ($self->type =~ /MCP/i)
	{
	    $self->{'_setup_tags'} = ['mode','channel_name','type','internal_compensation','callibration_file','offset','title','show_plot','use_cache','unit'];
	    foreach my $tag ('offset')
	    {
		$self->{'_'.$tag} = $self->get_default($tag);
		my $conf = $self->get_conf($tag);
		$self->{'_'.$tag} = $conf if (defined($conf) && $conf =~ /\w/);
	    }
	}
	if ($self->type =~ /pt100|Thermis/i)
	{
	    $self->{'_setup_tags'} = ['mode','channel_name','type','internal_compensation','callibration_file','lead_res_name','lead_res','lead_res_input_type','title','show_plot','use_cache'];	
	}  
    }  
    $self->{'_hide_tags'} = \@hide_tags;
    return $self;
}

sub test()
{
    my $self = shift;
    return 0 unless ($self->{'_channel_device'});
    return $self->{'_channel_device'}->test();
}

sub test_full()
{
    my $self = shift;
    return 0 unless ($self->{'_channel_device'});
    my $ok = $self->{'_channel_device'}->test;
    return $ok unless ($ok);
    my $tmp = $self->read();
    if ($self->{'_unit'} eq 'K')
    {
	$tmp -= 273.15;
    }
    return 0 if ($tmp < -300 || $tmp > 100000);
    return 1;
}


sub Accept
{
    my $self = shift;
    my $visitor = shift;
    return undef if ($self->{'_seen_visitors'}{$visitor});
    $self->{'_channel_device'}->Accept($visitor);
    $self->{'_cj_channel_device'}->Accept($visitor) if ($self->{'_cj_channel_device'});
    $self->{'_lead_res_device'}->Accept($visitor) if ($self->{'_lead_res_device'});
    $visitor->VisitComplex($self);
    $self->{'_seen_visitors'}{$visitor} = 1;
    return undef;
}

sub test_string()
{
    my $self = shift;
    my $data = RFC::Cache->new();
    my $string = 'Temperature '.$self->name.' is '.$self->read($data);
    if ($self->{'_unit'} eq 'K')
    {
	$string .= "K\n";
    }
    else
    {
	$string .= "C\n";
    }
    $string .= 'Analog voltage: '.$self->{'_channel_device'}->test_string($data);
    $string .= 'Cold junction: '.$self->{'_cj_channel_device'}->test_string($data) if ($self->{'_cj_channel_device'});
    $string .= 'Lead resistance: '.$self->{'_lead_res_device'}->test_string($data) if ($self->{'_lead_res_device'});
    return $string."\n";
}

sub readstring()
{
    my $self = shift;
    return undef if ($self->readstring_ignore);
    my $data = undef;
    if (@_)
    {
        $data = $_[0];
    }
    else
    {
        $data = RFC::Cache->new();
        $data->debug($self->debug()) if ($self->debug);
    }
    $self->check_cache($data);
    my $val = $self->read($data);
    my $ignore = $self->{'_channel_device'}->readstring_ignore;
    $self->{'_channel_device'}->readstring_ignore(0);
    my $str = $self->{'_channel_device'}->readstring($data);
    $self->{'_channel_device'}->readstring_ignore($ignore);
    if (defined($str))
    {
	my @l = split(/\s+/,$str);
	my $res = join(' ',$self->name,$l[1],$l[2],sprintf("%.5g",$val));
	$self->writedebug($res) if ($self->debug > 1);
	my $str = time .' '.$self->name.' '.sprintf("%.5g",$val);
	$self->rig->kanaldata($str) unless ($self->readstring_ignore);
	return $res;
    }
    else
    {
	my @t = $self->get_time();
	my $t = join(':',@t);
	my $res = join(' ',$self->name,$t,time,-32768);
	$self->writedebug("No data was recieved from device '".$self->{'_channel_device'}->name."' using dummy value!") if ($self->debug);
	my $str = time .' '.$self->name.' '.sprintf("%.5g",-32768);
	$self->rig->kanaldata($str) unless ($self->readstring_ignore);
	return $res;
    }
}

sub read_nocache()
{
    my $self = shift;
    my $temp = -32768;
    if ($self->type =~ /pt100|therm/i)
    {
	my $mv = $self->{'_channel_device'}->read(@_);
	my  $lead_res = $self->{'_lead_res'};
	$lead_res = $self->{'_lead_res_device'}->read(@_) if ($self->{'_lead_res_device'});
	my $res = $mv - $lead_res;
	$res = $res / 10.0 if ($self->type eq 'pt1000');
	my $test = undef;
	if ($self->type =~ /pt100/)
	{
	    $test = RFC::Main::spline('pt100-res-to-temp',$res);
	}
	else
	{
	    $test = RFC::Main::spline($self->type.'-res-to-temp',$res);
	}
	$temp = $test if (defined($test));
    }
    else
    {
	my $mv = $self->{'_channel_device'}->read(@_);
	if ($self->{'_internal_compensation'} =~ /yes/i)
	{
	    $temp = $mv;
	}
	elsif ($self->type =~ /MCP/)
	{
	    $self->writedebug("Thermovoltage for ".$self->type.": $mv mV") if ($self->debug);
	    my $test = RFC::Main::spline($self->type.'_mV_to_temp',$mv + $self->{'_offset'});
	    return $temp unless (defined($test) && $test =~ /\d/);
	    $temp = $test;		
	}
	else
	{
	    my  $lead_res = $self->{'_lead_res'};
	    $lead_res = $self->{'_lead_res_device'}->read(@_) if ($self->{'_lead_res_input_type'} !~ /fixed_value/);
	    my $deltaohm = 0;
	    unless ($self->{'_cj_type'} =~ /fixed|templog/i)
	    {
		my $cjv = $self->{'_cj_channel_device'}->read(@_);
		$lead_res = 0 unless (defined($lead_res));
		$deltaohm = $cjv - $lead_res;
		$deltaohm = $deltaohm / 10.0 if ($self->{'_cj_type'} eq 'pt1000');
	    }
	    if ($self->{'_callibration_file'} !~ /DEFAULT/i)
	    {
		my $dir = $homedir.'convert-tables/';
		my $f1 = $dir.'userfiles/'.$self->{'_callibration_file'};
		unless (-e $f1)
		{
		    $self->writedebug("Callibration file $f1 not found!",1);
		    return $temp;
		}
		my $f2 = $dir.'mv_to_temp/'.$self->{'_callibration_file'};
		my $f3 = $dir.'temp_to_mv/'.$self->{'_callibration_file'};
		unless (-e $f2 && stat($f2)->mtime > stat($f1)->mtime)
		{
		    my $cmd = "/bin/sort -n $f1 > $f2";
		    system($cmd) and die &errorlog("Failed to create $f2 $?");
		}
		unless (-e $f3 && stat($f3)->mtime > stat($f2)->mtime)
		{
		    my $cmd = "/bin/awk '{print \$2,\$1}' $f2 > $f3";
		    system($cmd) and die &errorlog("Failed to create $f3 $?");
		}
		my $cjtemp = $self->{'_cj_temp'};
		if ($self->{'_cj_type'} =~ /templog/i)
		{
		    $cjtemp = $self->{'_cj_channel_device'}->read(@_);
		}
		else
		{
		    $cjtemp = RFC::Main::spline('pt100-res-to-temp',$deltaohm) if ($deltaohm);
		}
		$self->writedebug("Cold junction temperature: $cjtemp C") if ($self->debug);
		return $temp unless (defined($cjtemp) && $cjtemp =~ /\d/);
		my $cjvolt = RFC::Main::spline('temp_to_mv/'.$self->{'_callibration_file'},$cjtemp);
		$self->writedebug("Cold junction voltage for ".$self->type.": $cjvolt mV") if ($self->debug);
		return $temp unless (defined($cjvolt) && $cjvolt =~ /\d/);
		my $samplevolt = $mv + $cjvolt;
		$self->writedebug("Thermovoltage for ".$self->type.": $samplevolt mV") if ($self->debug);
		my $test = RFC::Main::spline('mv_to_temp/'.$self->{'_callibration_file'},$samplevolt);
		return $temp unless (defined($test) && $test =~ /\d/);
		$temp = $test;
	    }
	    else
	    {
                my $cjvolt = 0;
                if ($self->{'_cj_type'} =~ /fixed/i)
		{
                    my $cjtemp = $self->{'_cj_temp'};
                    $cjvolt = RFC::Main::spline('NIST-90-'.$self->type.'-temp-to-mV',$cjtemp);
                }
		elsif ($self->{'_cj_type'} =~ /templog/i)
		{
		    my $cjtemp = $self->{'_cj_channel_device'}->read(@_);
                    $cjvolt = RFC::Main::spline('NIST-90-'.$self->type.'-temp-to-mV',$cjtemp);
		}
                else
                {
                    $cjvolt = RFC::Main::spline('pt100-res-to-type-'.$self->type.'-mV',$deltaohm);
                }
		$self->writedebug("Cold junction voltage for ".$self->type.": $cjvolt mV") if ($self->debug);
		return $temp unless (defined($cjvolt) && $cjvolt =~ /\d/);
		my $samplevolt = $mv + $cjvolt;
		$self->writedebug("Thermovoltage for ".$self->type.": $samplevolt mV") if ($self->debug);
		my $test = RFC::Main::spline('NIST-90-'.$self->type.'-mV-to-temp',$samplevolt);
		return $temp unless (defined($test) && $test =~ /\d/);
		$temp = $test;
	    }
	}
    }
    if ($self->{'_unit'} eq 'K')
    {
	$temp += 273.15;
    }
    $self->writedebug("Temperature for ".$self->name." was $temp") if ($self->debug > 1);
    my $str = time .' '.$self->name.' '.sprintf("%.5g",$temp);
    $self->rig->kanaldata($str) unless ($self->readstring_ignore);
    $self->set_cache($temp);
    $self->{'_last_read'} = Time::HiRes::time;
    return $temp;
}

sub print_config()
{
    my $self = shift;
    my @arr = ();
    push @arr,'Name: '.$self->name;
    if ($self->{'_callibration_file'} =~ /default/i)
    {
	push @arr,'Type: '.$self->type;
    }
    else
    {
	push @arr,'Type: File';
	push @arr,'Filename: '.$self->{'_callibration_file'};
    }
    push @arr,$self->{'_channel_device'}->print_config if ($self->{'_channel_device'});
    push @arr,'Cold junction type: '.$self->{'_cj_type'};
    if ($self->{'_cj_channel_device'})
    {
	push @arr,$self->{'_cj_channel_device'}->print_config;
    }
    else
    {
	push @arr,'Cold junction temperature: '.$self->{'_cj_temp'};
    }
    if ($self->{'_lead_res_device'})
    {
        push @arr,$self->{'_lead_res_device'}->print_config;
    }
    else
    {
        push @arr,'Lead resistance value: '.$self->{'_lead_res'};
    }
    return join(', ',@arr);
}




package RFC::EuroLog;
use strict;
use warnings;
#use RFC::Main qw();
use RFC::BaseDevice;
use RFC::Header;
use Eurotherm;
our @ISA = qw(RFC::BaseDevice);

sub new()
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_setup_tags'} = ['type','channel','tty','controller_mode','factor','communication','title','show_plot','use_cache','unit'];
    $self->{'_desc'} = {
	'unit' => 'Temperuature scale (Celcius of Kelvin)',
	'type' => 'Temperature sensor model/mode',
        'channel' => 'Controler address',
	'tty' => 'Communication device (ex. ttyS0)',
	'factor' => 'Multiplication factor',
	'controller_mode' => 'Number format',
	'communication' => 'Communication type',
	'title' => 'Optional device title',
        'show_plot'=>'Determines if the current device data is to be shown in the daily data plots',
        'use_cache'=>'Determines if persisten caching of read values is allowed',
    };
    $self->{'_default'} = {
	'type' => 'C',
	'type' => 'E2216',
        'channel' => 0,
	'tty' => 'ttyS0',
	'factor' => 1,
	'controller_mode' => 'integer',
	'communication' => 'modbus',
        'show_plot'=>'Yes',
        'use_cache'=>'No',
    };
    $self->{'_section'} = 'temp_'.$self->name;
    bless $self,$class;
    $self->{'_readstring_furnace'} = 1;
    $self->{'_html_template'} = 'Templog.tt';
    $self->{'_title'} = $self->get_conf('title');
    $self->{'_device'} = undef;
    $self->{'_values_type'} = [(RFC::Device::list_Templog())];
    $self->{'_values_unit'} = ['C','K'];
    $self->{'_values_controller_mode'} = ['integer','decimal'];
    $self->{'_values_communication'} = ['modbus','bisynch'];
    foreach my $tag ($self->setup_tags)
    {
	$self->{'_'.$tag} = $self->get_default($tag);
        my $conf = $self->get_conf($tag);
        $self->{'_'.$tag} = $conf if (defined($conf) && $conf =~ /\w/);
    }
    $self->{'_type'} = shift if (@_);
    my $dev = Eurotherm::new_controler($self->type,$self->{'_tty'},$self->{'_channel'},$self->{'_communication'},$self->{'_controller_mode'});
    $self->{'_device'} = $dev;
    $self->die("No device returned") unless $dev;
    $self->{'_type'} = $dev->name;
    $self->{'_setup_tags'} = ['type','channel','tty','factor','title'] unless ($dev->name =~ /^\d+e/i);
    return $self;
}

sub test()
{
    my $self = shift;
    return 0 unless ($self->{'_device'});
    return $self->{'_device'}->get_temp();
}

sub test_full()
{
    my $self = shift;
    return 0 unless ($self->{'_device'});
    my $res = $self->{'_device'}->get_temp();
    my $tmp = $self->read();
    if ($self->{'_unit'} eq 'K')
    {
	$tmp -= 273.15;
    }
    return 0 unless defined($res);
    return 0 if ($res < -300 || $res > 100000);
    return 1;
}



sub test_string()
{
    my $self = shift;
    my $temp = $self->{'_device'}->get_temp();
    chomp $temp;
    my $ramp = $self->{'_device'}->get_ramp();
    chomp $ramp;
    return "Temperature controler $self, Setpoint: $temp C, ramprate $ramp C/hour";
}

sub print_config()
{
    my $self = shift;
    my @arr = ();
    push @arr,'Name: '.$self->name;
    push @arr,'Type: '.$self->type;
    push @arr,'TTY: '.$self->{'_tty'};
    push @arr,'Address: '.$self->{'_channel'};
    push @arr,'Communication: '.$self->{'_communication'};
    push @arr,'Mode: '.$self->{'_mode'};
    return join(', ',@arr);
}

sub readstring()
{
    my $self = shift;
    return undef if ($self->readstring_ignore);
    my @t = $self->get_time();
    my $t = join(':',@t);
    my $res = join(' ',$self->name,$t,time,sprintf("%.2f",$self->read(@_)));
    $self->writedebug($res) if ($self->debug > 1);
    return $res;
}

sub read_nocache()
{
    my $self = shift;
    my $data = undef;
    if (@_)
    {
        $data = $_[0];
    }
    else
    {
        $data = RFC::Cache->new();
        $data->debug($self->debug()) if ($self->debug);
    }
    $self->check_cache($data);
    my $cached = $data->get('templog_Eurotherm',$self->name);
    return $cached if (defined($cached));
    my $val = $self->{'_device'}->get_active_temp();
    my $temp = $val / $self->{'_factor'};
    if ($self->{'_unit'} eq 'K')
    {
	$temp += 273.15;
	$val += 273.15;
    }
    $self->writedebug("Temperature for $self was $temp") if ($self->debug > 1);
    my $str = time .' '.$self->name.' '.$temp;
    my $str2 = time .' '.$self->name.'_raw '.$val;
    $self->rig->kanaldata($str,$str2) unless ($self->readstring_ignore);
    $data->set('templog_Eurotherm',$self->name,$temp);
    return $temp;
}


return 1;
