package RFC::Elektro;

#####################################################################
#
# Package RFC::Elektro
#
#
# This module implements RFC::PSU for electronic loads.
#
# To obtain an instance call one of the constructors as shown below:
#
# $id = RFC::EL_9080_200_HP->new($name,$rig);
#
# $id = RFC::EL_9160_100_HP->new($name,$rig);
#
# $id = RFC::EL_9400_50_HP->new($name,$rig);
#
# $id = RFC::EL_9750_50_HP->new($name,$rig);
#
# $id = RFC::EL_9080_200_HP->new($name,$rig);
#
# $id = RFC::EL_9160_100_HP->new($name,$rig);
#
# $id = RFC::EL_9400_50->new($name,$rig);
#
# $id = RFC::EL_9750_50->new($name,$rig);
#
# $id = RFC::EL_9080_600_HP->new($name,$rig);
#
# $id = RFC::EL_9160_300_HP->new($name,$rig);
#
# $id = RFC::EL_9400_150_HP->new($name,$rig);
#
# $id = RFC::EL_9080_600_HP->new($name,$rig);
#
# $id = RFC::EL_9160_300_HP->new($name,$rig);
#
# $id = RFC::EL_9400_150_HP->new($name,$rig);
#
# $id = RFC::EL_9750_75->new($name,$rig);
#
# $id = RFC::EL_9750_75_HP->new($name,$rig);
#
# $id = RFC::EL_3160_60A->new($name,$rig);
#
# $id = RFC::EL_3400_25A->new($name,$rig);
#
# $id = RFC::EL_9080_200->new($name,$rig);
#
# $id = RFC::EL_9160_100->new($name,$rig);
#
# $id = RFC::EL_9400_50_S01->new($name,$rig);
#
# $id = RFC::EL_9750_25->new($name,$rig);
#
# $id = RFC::EL_9080_400->new($name,$rig);
#
# $id = RFC::EL_9400_100->new($name,$rig);
#
# $id = RFC::EL_9160_200->new($name,$rig);
#
# $id = RFC::EL_9400_100_S01->new($name,$rig);
#
# $id = RFC::EL_9750_50->new($name,$rig);
#
# $id = RFC::Hocherl_ZS->new($name,$rig);
#
#####################################################################

use strict;
use warnings;
use RFC::PSU;
use RFC::Cache;
our @ISA = qw(RFC::PSU);

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->{'_type'} = 'Default_Elektro';
    $self->{'_mode'} = 'Automatic';
    $self->{'_default'}{'mode'} ='Automatic';
    $self->{'_maxI'} = 100;
    $self->{'_maxU'} = 100;
    $self->{'_maxP'} = 100;
    bless $self,$class;
    $self->{'_section'} = 'PSU_'.$self->name;
    ### Specproc for backwards compatibility ###
    $self->{'_section'} = 'current' if (!$self->rig->config_section_exists($self->sectionname) && $self->name eq 'current');
    return $self;
}

sub read()
{
    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 $var = $data->get('PSU',$self->name,'I');
    return $var if (defined($var));
    $var =  $self->measure_I();
    $data->set('PSU',$self->name,'I',$var);
    return $var;
}

sub test()
{
    my $self = shift;
    my $res = $self->test_string();
    return 1 if ($res =~ /el/i);
    return 0;
}

sub test_string()
{
    my $self = shift;
    return SocketClient::serial_client($self->{'_tty'},'elektro','idn',$self->{'_address'});    
}

sub remote_on()
{
    my $self = shift;
    return SocketClient::serial_client($self->{'_tty'},'elektro','remote',$self->{'_address'},'on');
}

sub remote_off()
{
    my $self = shift;
    return SocketClient::serial_client($self->{'_tty'},'elektro','remote',$self->{'_address'},'off');
}

sub current()
{
    my $self = shift;
    if (@_)
    {
	$self->{'_I'} = 'ocv';
	my $c = shift;
	if ($c =~ /([\d\.]+)/)
	{
	    $self->{'_I'} = $1 / $self->{'_parallel'};
	    $self->{'_I'} = $self->{'_minI'} if ($self->{'_I'} < $self->{'_minI'});
	    $self->{'_I'} = $self->{'_maxI'} if ($self->{'_I'} > $self->{'_maxI'});
	}
	if ($self->{'_I'} =~ /ocv/i)
	{
	    $self->writedebug('Setting current to OCV') if ($self->debug > 1);
	    $self->RSD(0);

	}
	else
	{
	    $self->writedebug('Setting current to '.$self->{'_I'}.' A') if ($self->debug > 1);
	    $self->RSD(1);
	}
	my $res = $self->send_current;
	$self->proglog("Current for PSU ".$self->name." set to ".$self->{'_I'}." A",@_);
	$self->notify('current',$res,@_);
	return $res;
    }
    else
    {
	return $self->get_I();
    }
}


sub voltage()
{
    my $self = shift;
    if (@_)
    {
	$self->{'_U'} = 'ocv';
	my $c = shift;
	if ($c =~ /([\d\.]+)/)
	{
	    $self->{'_U'} = $1 / $self->{'_serial'};
	    $self->{'_U'} = $self->{'_minU'} if ($self->{'_U'} < $self->{'_minU'});
	    $self->{'_U'} = $self->{'_maxU'} if ($self->{'_U'} > $self->{'_maxU'});
	}
	if ($self->{'_U'} =~ /ocv/i)
	{
	    $self->writedebug('Setting voltage to OCV') if ($self->debug > 1);
	    $self->RSD(0);

	}
	else
	{
	    $self->writedebug('Setting voltage to '.$self->{'_U'}.' V') if ($self->debug > 1);
	    $self->RSD(1);
	}
	my $res = $self->send_voltage; 
	$self->proglog("Voltage for PSU ".$self->name." set to ".$self->{'_U'}." V",@_);
	$self->notify('voltage',$res,@_);
	return $res;
    }
    else
    {
	return $self->get_U();
    }
}


sub send_voltage()
{
    my $self = shift;
    my $volt = 'ocv';
    $volt = $self->{'_U'} * 100 / $self->{'_maxU'} if (defined($self->{'_U'}) && $self->{'_U'} =~ /\d+/);
    $self->writedebug("Setting voltage '$volt' on ".$self->type) if ($self->debug > 3);
    my $res = undef;
    $self->remote_on();
    if ($volt !~ /\d+/i)
    {
	$res = SocketClient::serial_client($self->{'_tty'},'elektro','ocv',$self->{'_address'});
    }
    else
    {
	$res = SocketClient::serial_client($self->{'_tty'},'elektro','on',$self->{'_address'});
    }
    $self->writedebug("Setting RSD status on ".$self->type.", result: $res") if ($self->debug > 3);
    $res = SocketClient::serial_client($self->{'_tty'},'elektro','write',$self->{'_address'},2,50,$volt);
    $self->writedebug("Result of send volt '$res'") if ($self->debug > 3);
    $self->remote_off();
    return $res;
}

sub send_current()
{
    my $self = shift;
    my $current = 'ocv';
    $current = $self->{'_I'} * 100 / $self->{'_maxI'} if (defined($self->{'_I'}) && $self->{'_I'} =~ /\d+/);
    $self->writedebug("Setting current '$current' on ".$self->type) if ($self->debug > 3);
    my $res = undef;
    $self->remote_on();
    if ($current !~ /\d+/)
    {
	$res = SocketClient::serial_client($self->{'_tty'},'elektro','ocv',$self->{'_address'});
    }
    else
    {
	$res = SocketClient::serial_client($self->{'_tty'},'elektro','on',$self->{'_address'});
    }
    $self->writedebug("Setting RSD status on ".$self->type.", result: $res") if ($self->debug > 3);
    $res = SocketClient::serial_client($self->{'_tty'},'elektro','write',$self->{'_address'},2,51,$current);
    $self->writedebug("Result of send current '$res'") if ($self->debug > 3);
    $self->remote_off();
    return $res;
}

sub read_values()
{
    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 $volt = $data->get('PSU',$self->name,'U');
    my $curr = $data->get('PSU',$self->name,'I');
    my $pow = $data->get('PSU',$self->name,'P');
    return ($volt,$curr,$pow) if (defined($volt) && defined($curr) && defined($pow));
    my $res = SocketClient::serial_client($self->{'_tty'},'elektro','read_values',$self->{'_address'});
    if ($res)
    {
	my $volt = undef;
	my $curr = undef;
	my $pow = undef;
	if ($res =~ /Voltage:\s+([\d\.\+\-eE]+)/)
	{
	    $volt = $1;
	}
	if ($res =~ /Current:\s+([\d\.\+\-eE]+)/)
	{
	    $curr = $1;
	}
	if ($res =~ /Power:\s+([\d\.\+\-eE]+)/)
	{
	    $pow = $1;
	}
	$data->set('PSU',$self->name,'U',$volt);
	$data->set('PSU',$self->name,'I',$curr);
	$data->set('PSU',$self->name,'P',$pow);
	return ($volt,$curr,$pow);
    }
    return (undef,undef,undef);
}

sub get_U()
{
    my $self = shift;
    return SocketClient::serial_client($self->{'_tty'},'elektro','read',$self->{'_address'},2,50) * $self->{'_maxU'} * $self->{'_serial'} / 100;
}

sub get_I()
{
    my $self = shift;
    return SocketClient::serial_client($self->{'_tty'},'elektro','read',$self->{'_address'},2,51) * $self->{'_maxI'} * $self->{'_parallel'} / 100;
}

sub get_P()
{
    my $self = shift;
    return SocketClient::serial_client($self->{'_tty'},'elektro','read',$self->{'_address'},2,52) * $self->{'_maxP'} * $self->{'_parallel'} * $self->{'_serial'} / 100;
}

sub measure_U()
{
    my $self = shift;
    return ($self->read_values)[0] * $self->{'_maxU'} * $self->{'_serial'} / 100;
}

sub measure_I()
{
    my $self = shift;
    return ($self->read_values)[1] * $self->{'_maxI'} * $self->{'_parallel'} / 100;
}

sub measure_P()
{
    my $self = shift;
    return ($self->read_values)[2] * $self->{'_maxP'} * $self->{'_parallel'} * $self->{'_serial'} / 100;
}


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 @t = $self->get_time();
    my $t = join(':',@t);
    my $res = join(' ',$self->name.'_current',$t,time,$self->measure_I(),$self->name.'_voltage',$t,time,$self->measure_U());
    $self->writedebug($res) if ($self->debug > 1);
    return $res;
}

sub monitor()
{
    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 $u = $self->measure_U($data);
    $u = -32768 unless defined($u);
    my $i = $self->measure_I($data);
    $i = -32768 unless defined($i);
    return join(' ','Current',$i,'Voltage',$u);
}



### Instance classes  ###

package RFC::EL_9080_200_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9080-200_HP';
    $self->{'_maxI'} = 200;
    $self->{'_maxU'} = 80;
    bless $self,$class;
    return $self;
}

package RFC::EL_9160_100_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9160-100_HP';
    $self->{'_maxI'} = 100;
    $self->{'_maxU'} = 160;
    bless $self,$class;
    return $self;
}

package RFC::EL_9400_50_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9400-50_HP';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 400;
    bless $self,$class;
    return $self;
}


package RFC::EL_9080_600_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9080-600_HP';
    $self->{'_maxI'} = 600;
    $self->{'_maxU'} = 80;
    bless $self,$class;
    return $self;
}


package RFC::EL_9160_300_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9160-300_HP';
    $self->{'_maxI'} = 300;
    $self->{'_maxU'} = 160;
    bless $self,$class;
    return $self;
}

package RFC::EL_9400_150_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9400-150_HP';
    $self->{'_maxI'} = 150;
    $self->{'_maxU'} = 400;
    bless $self,$class;
    return $self;
}

package RFC::EL_3160_60A;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_3160-60A';
    $self->{'_maxI'} = 60;
    $self->{'_maxU'} = 160;
    bless $self,$class;
    return $self;
}

package RFC::EL_3400_25A;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_3400-25A';
    $self->{'_maxI'} = 25;
    $self->{'_maxU'} = 400;
    bless $self,$class;
    return $self;
}

package RFC::EL_9080_200;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9080-200';
    $self->{'_maxI'} = 200;
    $self->{'_maxU'} = 80;
    bless $self,$class;
    return $self;
}

package RFC::EL_9160_100;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9160-100';
    $self->{'_maxI'} = 100;
    $self->{'_maxU'} = 160;
    bless $self,$class;
    return $self;
}

package RFC::EL_9400_50;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9400-50';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 400;
    bless $self,$class;
    return $self;
}

package RFC::EL_9400_50_S01;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9400-50 S01';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 450;
    bless $self,$class;
    return $self;
}

package RFC::EL_9750_25;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9750_25';
    $self->{'_maxI'} = 25;
    $self->{'_maxU'} = 750;
    bless $self,$class;
    return $self;
}

package RFC::EL_9080_400;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9080-400';
    $self->{'_maxI'} = 400;
    $self->{'_maxU'} = 80;
    bless $self,$class;
    return $self;
}

package RFC::EL_9160_200;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9160-100';
    $self->{'_maxI'} = 200;
    $self->{'_maxU'} = 160;
    bless $self,$class;
    return $self;
}

package RFC::EL_9400_100;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9400-100';
    $self->{'_maxI'} = 100;
    $self->{'_maxU'} = 400;
    bless $self,$class;
    return $self;
}

package RFC::EL_9400_100_S01;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9400-100 S01';
    $self->{'_maxI'} = 100;
    $self->{'_maxU'} = 460;
    bless $self,$class;
    return $self;
}

package RFC::EL_9750_50;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9750-50';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 750;
    bless $self,$class;
    return $self;
}

package RFC::EL_9750_50_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9750-50-HP';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 750;
    bless $self,$class;
    return $self;
}

package RFC::EL_9750_75_HP;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9750-75_HP';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 750;
    bless $self,$class;
    return $self;
}

package RFC::EL_9750_75;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'EL_9750-75';
    $self->{'_maxI'} = 50;
    $self->{'_maxU'} = 750;
    bless $self,$class;
    return $self;
}

package RFC::Hocherl_ZS;
our @ISA = qw(RFC::Elektro);

sub new
{
    my $class = shift;
    my $name = shift;
    my $rig = shift;
    my $self = $class->SUPER::new($name,$rig);
    $self->{'_type'} = 'Hocherl and hackl ZS Eloads';
    $self->{'_maxI'} = undef;
    $self->{'_maxU'} = undef;
    $self->{'_setup_tags_readonly'} = ['communication','control_mode'];
    $self->{'_setup_tags'} = ['mode','communication','tty','baudrate','parity','databits','stopbits','serial','parallel','external_RSD','RSD_name','control_mode','master_device','slave_current','slave_voltage','show_plot'];
    $self->{'_default'}{'baudrate'} = 9600;
    $self->{'_default'}{'parity'} = 'even';
    $self->{'_default'}{'databits'} = 8;
    $self->{'_default'}{'stopbits'} = 2;
    $self->{'_desc'}{'baudrate'} = 'Baud rate';
    $self->{'_desc'}{'parity'} = 'Parity check scheme';
    $self->{'_desc'}{'databits'} = 'Data bits';
    $self->{'_desc'}{'stopbits'} = 'Stop bits';
    $self->{'_communication'} = 'Serial RS232';
    $self->{'_values_baudrate'} = [4800,9600,14400,19200,28800,38400,57600];
    $self->{'_values_parity'} = ['even','odd'];
    $self->{'_values_databits'} = [7,8];
    $self->{'_values_stopbits'} = [1,2];
    $self->{'_values_control_mode'} = ['Current'];
    $self->{'_control_mode'} = 'Current';
    $self->{'_section'} = 'PSU_'.$self->name;
    $self->{'_ui_fn_args'} = {'reset' => 0};
    $self->{'_ui_fn_names'} = ['reset'];
    $self->{'_ui_fn_desc'} = {'reset' => 'Resets electronic load to default setup'};
    bless $self,$class;
    $self->load_conf();
    return $self;
}


sub reset
{
    my $self = shift;
    my @conn = $self->get_conn();
    SocketClient::serial_client($self->{'_tty'},'raw',@conn,'*rst');
    sleep(1);
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'*idn?');
}

sub readonly_value($)
{
    my $self = shift;
    my $tag = shift;
    return undef unless ($tag);
    return $self->{'_communication'} if ($tag eq 'communication');
    return $self->{'_control_mode'} if ($tag eq 'control_mode');
    return undef;
}

sub get_conn()
{
    my $self = shift;
    my @arr = ();
    push @arr,$self->{'_baudrate'};
    push @arr,$self->{'_parity'};
    push @arr,$self->{'_databits'};
    push @arr,$self->{'_stopbits'};
    return @arr;
}

sub read()
{
    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 $var = $data->get('PSU',$self->name,'I');
    return $var if (defined($var));
    $var =  $self->measure_I();
    $data->set('PSU',$self->name,'I',$var);
    return $var;
}

sub test()
{
    my $self = shift;
    my $res = $self->test_string();
    return 1 if ($res =~ /hoe/i);
    return 0;
}

sub test_string()
{
    my $self = shift;
    my @conn = $self->get_conn();
    my @res = ();
    push @res,SocketClient::serial_client($self->{'_tty'},'raw',@conn,'*idn?');
    push @res,'Min voltage: '. (SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT? MIN')+0).' V';    
    push @res,'Max voltage: '. (SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT? MAX')+0).' V';    
    push @res,'Min current: '. (SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR? MIN')+0).' A';    
    push @res,'Max current: '. (SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR? MAX')+0).' A';    
    return join("\n",@res);
}

sub current()
{
    my $self = shift;
    if (@_)
    {
	my @conn = $self->get_conn();
	unless (defined($self->{'_maxI'}))
	{
	    $self->{'_maxI'}= SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR? MAX')
	}
	unless (defined($self->{'_minI'}))
	{
	    $self->{'_minI'}= SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR? MIN')
	}
	$self->{'_I'} = 'ocv';
	my $c = shift;
	if ($c =~ /([\d\.]+)/)
	{
	    $self->{'_I'} = $1 / $self->{'_parallel'};
	    $self->{'_I'} = $self->{'_minI'} if ($self->{'_I'} < $self->{'_minI'});
	    $self->{'_I'} = $self->{'_maxI'} if ($self->{'_I'} > $self->{'_maxI'});
	}
	if ($self->{'_I'} =~ /ocv/i)
	{
	    $self->writedebug('Setting current to OCV') if ($self->debug > 1);
	    $self->RSD(0);

	}
	else
	{
	    $self->writedebug('Setting current to '.$self->{'_I'}.' A') if ($self->debug > 1);
	    $self->RSD(1);
	}
	my $res = $self->send_current;
	$self->proglog("Current for PSU ".$self->name." set to ".$self->{'_I'}." A",@_);
	$self->notify('current',$res,@_);
	return $res;
    }
    else
    {
	return $self->get_I();
    }
}


sub voltage()
{
    my $self = shift;
    if (@_)
    {
	my @conn = $self->get_conn();
	unless (defined($self->{'_maxU'}))
	{
	    $self->{'_maxU'}= SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT? MAX')
	}
	unless (defined($self->{'_minU'}))
	{
	    $self->{'_minU'}= SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT? MIN')
	}
	$self->{'_U'} = 'ocv';
	my $c = shift;
	if ($c =~ /([\d\.]+)/)
	{
	    $self->{'_U'} = $1 / $self->{'_serial'};
	    $self->{'_U'} = $self->{'_minU'} if ($self->{'_U'} < $self->{'_minU'});
	    $self->{'_U'} = $self->{'_maxU'} if ($self->{'_U'} > $self->{'_maxU'});
	}
	if ($self->{'_U'} =~ /ocv/i)
	{
	    $self->writedebug('Setting voltage to OCV') if ($self->debug > 1);
	    $self->RSD(0);

	}
	else
	{
	    $self->writedebug('Setting voltage to '.$self->{'_U'}.' V') if ($self->debug > 1);
	    $self->RSD(1);
	}
	my $res = $self->send_voltage; 
	$self->proglog("Voltage for PSU ".$self->name." set to ".$self->{'_U'}." V",@_);
	$self->notify('voltage',$res,@_);
	return $res;
    }
    else
    {
	return $self->get_U();
    }
}


sub send_voltage()
{
    my $self = shift;
    my $volt = $self->{'_U'};
    $self->writedebug("Setting voltage '$volt' on ".$self->type) if ($self->debug > 3);
    my @conn = $self->get_conn();
    my $status = 0;
    if ($volt !~ /\d+/i)
    {
	SocketClient::serial_client($self->{'_tty'},'raw',@conn,'OUTP 0');
	$status = 0;
    }
    else
    {
	SocketClient::serial_client($self->{'_tty'},'raw',@conn,'OUTP 1');
	$status = 0;
    }
    $self->writedebug("Setting RSD status on ".$self->type." to $status") if ($self->debug > 3);
    SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT:IMM '.$volt) unless ($volt =~ /ocv/);
    my $res = SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT?');
    return $res;
}

sub send_current()
{
    my $self = shift;
    my $current = $self->{'_I'};
    $self->writedebug("Setting current '$current' on ".$self->type) if ($self->debug > 3);
    my @conn = $self->get_conn();
    my $status = 0;
    if ($current !~ /\d+/)
    {
	SocketClient::serial_client($self->{'_tty'},'raw',@conn,'OUTP 0');
	$status = 0;
    }
    else
    {
	SocketClient::serial_client($self->{'_tty'},'raw',@conn,'OUTP 1');
	$status = 1;
    }
    $self->writedebug("Setting RSD status on ".$self->type." to £status") if ($self->debug > 3);
    SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR:IMM '.$current) unless ($current =~ /ocv/);
    my $res = SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR?');
    return $res;
}
sub get_U()
{
    my $self = shift;
    my @conn = $self->get_conn();
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'VOLT?') * $self->{'_serial'};
}

sub get_I()
{
    my $self = shift;
    my @conn = $self->get_conn();
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'CURR?') * $self->{'_parallel'};
}

sub get_P()
{
    my $self = shift;
    my @conn = $self->get_conn();
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'POW?') * $self->{'_parallel'} * $self->{'_serial'};
}

sub measure_U()
{
    my $self = shift;
    my @conn = $self->get_conn();
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'MEAS:VOLT:DC?') * $self->{'_serial'};
}

sub measure_I()
{
    my $self = shift;
    my @conn = $self->get_conn();
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'MEAS:CURR:DC?') * $self->{'_parallel'};
}

sub measure_P()
{
    my $self = shift;
    my @conn = $self->get_conn();
    return SocketClient::serial_client($self->{'_tty'},'raw',@conn,'MEAS:POW:DC?') * $self->{'_parallel'} * $self->{'_serial'};
}


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 @t = $self->get_time();
    my $t = join(':',@t);
    my $res = join(' ',$self->name.'_current',$t,time,$self->measure_I(),$self->name.'_voltage',$t,time,$self->measure_U());
    $self->writedebug($res) if ($self->debug > 1);
    return $res;
}


return 1;
