package RFC::PSU_B2N;
#$Id: PSU_B2N.pm,v 1.48 2025/03/31 10:35:06 sqko Exp $

#######################################################################
#
#
#      RFC::PSU_B2N
#
# The RFC::PSU_B2N module defines a wrapper class which makes it possible to 
# use bipolar power supplies with the RFC control system.
# It works by vivifying a virtual relay which from the system and UI is 
# indistinguishable from the normal physical relays.
#
# The only difference is that when switching polarity by using the virtual 
# relay, the current is switched by using callback through the the observer pattern.
# By using this, the device behaves as a normal relay system.
# Thus this module overrides the observe() function and attaches this device to the
# virtual relay instance created during device initialization (bootstrapping).
#
# A PSU_B2N instance behaves exactly as a normal PSU instance in combination 
# with a normal electrolysis relay device. However, 
# the minvoltage and mincurrent values are defined by the device acting as
# the PSU, thus the mincurrent would likely be negative as opposed to a normal
# unipolar PSU which would be unable to give negative current.
#
# The benefit of using the container class is that it makes it possible to
# use a bipolar power supply instead of a normal power supply fitted with
# electrolysis switching relays.
#
# The RFC::PSU_B2N module also defines the reverse wrapper (called RFC::PSU_N2B)
# which can be used to convert a normal unipolar PSU with a switching relay for
# polarization control into a pseudo bipolar PSU (it will behave as a bipolar 
# PSU as far as RFCcontrol is concerned).
#
# Although RFCcontrol assumes a normal PSU and a switching relay for control, in
# some cases this is a disadvantage. Especially in the case where PID devices are
# used to control the current of a PSU, then the inability of the normal PSU
# device to natively set a negative current is a problem. This will be alleviated
# by using a RFC::PSU_N2B wrapper between the PID controller and the normal PSU.
#
#
# The RFC::PSU_B2N module also defines the RFC::PSU_N2B device which works like
# the inverse of the RFC::PSU_B2N device.
# The RFC::PSU_N2B device allows a normal PSU to emulate a bipolar power supply
# by incorporating the electrolyser module and allowing setting and reading the
# current also for electrolysis if the current is negative.
#
# In order to aquire one of the devices call the constructor:
#
# $id = RFC::PSU_B2N->new($name,$rig)
#
# $id = RFC::PSU_N2B->new($name,$rig)
#
#######################################################################

use strict;
use warnings;
use RFC::Header;
use RFC::BaseDevice;
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 $self = $class->SUPER::new(@_);
    $self->{'_setup_tags'} = ['mode','PSU_device','control_mode','show_plot'];
    $self->{'_desc'} = {
        'mode' =>'Device control mode',
        'PSU_device' => 'Bipolar power supply device',
        'title' => 'Optional device title',
        'show_plot'=>'Determines if the current device data is to be shown in the daily data plots',
	'control_mode' => 'determines if the set() function should control voltage or current',
    };
    $self->{'_set_fn_names'} = ['current','voltage','RSD']; # List of function names which can trigger a notify event
    $self->{'_type'} = 'PSU_B2N';
    $self->{'_default'} = {
        'mode' =>'Automatic',
        'show_plot'=>'Yes',
	'control_mode'=>'Current',
    };
    $self->{'_psu'} = undef;
    $self->{'_relay'} = undef;
    $self->{'_U'} = undef;
    $self->{'_I'} = undef;
    $self->{'_mode'} = 'Automatic';
    $self->{'_values_mode'} = ['Automatic'];
    $self->{'_values_control_mode'} = ['Voltage','Current'];
    $self->{'_set_names'} = ['current','voltage','set','RSD'];
    $self->{'_read_names'} = ['read','measure_I','measure_U','get_I','get_U'];
    $self->{'_file'} = SemaforeFile->new($userdir.'rig'.$self->rig->name.'/PSU_'.$self->name,'/home/celltest/Gas_rig'.$self->rig->name.'.lock');
    $self->{'_values_PSU_device'} = ['',($self->rig->avaliable_devices('PSU'))];
    $self->{'_section'} = 'PSU_'.$self->name;
    $self->{'_info_string'} = 'Wrapper device which converts a true bipolar PSU to behave like a unipolar PSU fitted with a switching relay';
    bless $self,$class;
    return $self->init;
}

sub DESTROY
{
    my $self = shift;
    $self->{'_file'}->DESTROY() if ($self->{'_file'});
    return undef;
}

sub set
{
    my $self = shift;
    if ($self->{'_control_mode'} && $self->{'_control_mode'} =~ /current/i)
    {
        return $self->current(@_);
    }
    else
    {
        return $self->voltage(@_);
    }
}

sub maxcurrent()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->maxcurrent;
}

sub mincurrent()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->mincurrent;
}

sub maxvoltage()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->maxvoltage;
}

sub minvoltage()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->minvoltage;
}

sub get_version()
{
    my $self = shift;
    ### get the serial-server version ###
    return SocketClient::serial_client($self->{'_tty'},'version');
}

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


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


sub test_string()
{
    my $self = shift;
    my $string = 'PSU '.$self->name."\n";
    if ($self->{'_psu'})
    {
        $string .= $self->{'_psu'}->test_string(@_);
    }
    else
    {
        $string .= "Warning: No PSU device found!\n";
    }
    return $string;
}

sub print_config()
{
    my $self = shift;
    my @arr = ();
    push @arr,'Name: '.$self->name;
    push @arr,'PSU type: '.$self->type;
    push @arr,$self->{'_psu'}->print_config if ($self->{'_psu'});
    return join (', ',@arr);
}

sub RSD()
{
    my $self = shift;
    my $status = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    $self->{'_psu'}->RSD($status);
    $self->notify('RSD',$status,@_);
}

sub voltage
{
    my $self = shift;
    if (@_)
    {
        my $v = shift;
        $self->{'_U'} = $v;
        $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
        if ($v =~ /\d/ )
        {
	    if (ref($self->{'_psu'}) eq 'RFC::PSU_Bipolar')
	    {
		if ($self->{'_relay'}->read)
		{
		    $self->{'_psu'}->voltage($v,'psu',@_);
		}
		else
		{
		    $self->{'_psu'}->voltage($v,'eload',@_);
		}		
	    }
	    else
	    {
		$self->{'_psu'}->voltage($v,@_);
	    }
            $self->writedebug('Setting voltage to '.$self->{'_U'}.' V') if ($self->debug > 1);
        }
        else
        {
            $self->writedebug('Setting voltage to OCV') if ($self->debug > 1);
            $self->{'_psu'}->voltage('ocv',@_);
        }
	$self->notify('voltage',$v,@_);
    }
    return $self->{'_U'};
}

sub current
{
    my $self = shift;
    if (@_)
    {
        my $c = shift;
	if ($c =~ /\d+/)
	{
	    $self->{'_file'}->writeline(sprintf("%.4f",$c));
	}
	else
	{
	    $self->{'_file'}->writeline('ocv');
	}
        $self->{'_I'} = $c;
        $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
	$self->writedebug("Setting current for $self to $c");
        if ($c =~ /\d/ )
        {
            if ($c > 0)
            {
		if ($self->{'_relay'}->read)
		{
		    $self->writedebug("Electrolysis mode, setting negative curent $c");
		    $self->{'_psu'}->current(-$c,@_);
		}
		else
		{
		    $self->writedebug("Fuel cell mode, setting positive curent $c");
		    $self->{'_psu'}->current($c,@_);
		}
            }
            else
            {
                $self->{'_psu'}->current(0,@_);
            }
            $self->writedebug('Setting current to '.$self->{'_I'}.' A') if ($self->debug > 1);
        }
        else
        {
            $self->writedebug('Setting current to OCV') if ($self->debug > 1);
            $self->{'_psu'}->current('ocv',@_);
        }
	$self->notify('current',$c,@_);
    }
    return $self->{'_I'};
}

sub measure_U()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    if (ref($self->{'_psu'}) eq 'RFC::PSU_Bipolar')
    {
	if ($self->{'_relay'}->read)
	{
	    return $self->{'_psu'}->read_volt_psu(@_);
	}
	else
	{
	    return $self->{'_psu'}->read_volt_eload(@_);
	}
    }
    return $self->{'_psu'}->measure_U(@_)
}

sub measure_I()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    if (ref($self->{'_psu'}) eq 'RFC::PSU_Bipolar')
    {
	if ($self->{'_relay'}->read)
	{
	    return $self->{'_psu'}->read_curr_psu(@_);
	}
	else
	{
	    return $self->{'_psu'}->read_curr_eload(@_);
	}
    }
    my $pi = $self->{'_psu'}->measure_I(@_);
    return abs($pi);
}

sub get_U()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    if (ref($self->{'_psu'}) eq 'RFC::PSU_Bipolar')
    {
	if ($self->{'_relay'}->read)
	{
	    return $self->{'_psu'}->get_volt_psu(@_);
	}
	else
	{
	    return $self->{'_psu'}->get_volt_eload(@_);
	}
    }
    return $self->{'_psu'}->get_U(@_)
}

sub get_I()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    if (ref($self->{'_psu'}) eq 'RFC::PSU_Bipolar')
    {
	if ($self->{'_relay'}->read)
	{
	    return $self->{'_psu'}->get_curr_psu(@_);
	}
	else
	{
	    return $self->{'_psu'}->get_curr_eload(@_);
	}
    }
    my $pi = $self->{'_psu'}->get_I(@_);
    return abs($pi);
}

sub idn()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    return $self->{'_psu'}->idn;
}


sub read()
{
    my $self = shift;
    return $self->measure_I(@_);
}

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

sub init
{
    my $self = shift;
    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/);
    }
    ## Init devices in container ###
    $self->{'_psu'} = $self->rig->get_device('PSU',$self->{'_PSU_device'});
    unless ($self->{'_psu'})
    {
        ### Implicitly initilaise device ###
        $self->{'_psu'} = $self->rig->init_device('PSU',$self->{'_PSU_device'});
        $self->{'_psu'}->readstring_ignore(1) if ($self->{'_psu'});
    }
    my $relay_name = $self->name.'_electrolysis_mode';
    ### Use existing relay if it exists (which should not be the case! ) ####
    $self->{'_relay'} = $self->rig->get_device('relay',$relay_name);
    unless ($self->{'_relay'})
    {
	### Implicitly create a new virtual relay which is enbled by default ###
        my $type = 'ManualRelay';
        my $dev = RFC::Device::new_RELAY($self->rig,$relay_name,$type);
        $self->rig->register_device('relay',$dev);
	$self->{'_relay'} = $dev;
    }
    $self->{'_relay'}->attatch_observer(\$self);
    return $self;
}


sub observe
{
    my $self = shift;
    my $action = shift;
    if ($action eq 'set')
    {
	my $status = shift;
        my @lines = $self->{'_file'}->readlines;
	my $current = 'ocv';
        $current = $lines[0] if (@lines);
	$self->current($current,$self->{'_relay'});
	sleep(1);
	my $c = $self->get_I();
	$self->proglog("Changing current polarisation due to notify from relay device, new current: $c A",$self->{'_relay'});
	return;
    }
    if ($action eq 'set_noinfo')
    {
	my $status = shift;
        my @lines = $self->{'_file'}->readlines;
	my $current = 'ocv';
        $current = $lines[0] if (@lines);
	$self->current($current,$self->{'_relay'},'noinfo');
	sleep(1);
	my $c = $self->measure_I();
	return;
    }
}

package RFC::PSU_N2B;
use RFC::Header;
use RFC::BaseDevice;
use RFC::Cache;
our @ISA = qw(RFC::BaseDevice);

sub new()
{
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->{'_setup_tags'} = ['mode','PSU_device','relay_device','control_mode','show_plot'];
    $self->{'_desc'} = {
        'mode' =>'Device control mode',
        'PSU_device' => 'Power supply device',
        'title' => 'Optional device title',
        'show_plot'=>'Determines if the current device data is to be shown in the daily data plots',
	'control_mode' => 'determines if the set() function should control voltage or current',
	'relay_device' => 'Relay device controling the direction of curent for the underlying PSU device',
    };
    $self->{'_set_fn_names'} = ['current','voltage','RSD']; # List of function names which can trigger a notify event
    $self->{'_type'} = 'PSU_B2N';
    $self->{'_default'} = {
        'mode' =>'Automatic',
        'show_plot'=>'Yes',
	'control_mode'=>'Current',
    };
    $self->{'_type'} = 'PSU_N2B';
    $self->{'_psu'} = undef;
    $self->{'_relay'} = undef;
    $self->{'_U'} = undef;
    $self->{'_I'} = undef;
    $self->{'_mode'} = 'Automatic';
    $self->{'_values_mode'} = ['Automatic'];
    $self->{'_values_control_mode'} = ['Voltage','Current'];
    $self->{'_file'} = SemaforeFile->new($userdir.'rig'.$self->rig->name.'/PSU_'.$self->name,'/home/celltest/Gas_rig'.$self->rig->name.'.lock');
    $self->{'_values_PSU_device'} = ['',($self->rig->avaliable_devices('PSU'))];
    $self->{'_values_relay_device'} = ['',($self->rig->avaliable_devices('relay'))];
    $self->{'_section'} = 'PSU_'.$self->name;
    $self->{'_info_string'} = 'Wrapper device which converts a normal unipolar PSU and a switching relay to behave like a bipolar PSU';
    bless $self,$class;
    return $self->init;
}

sub DESTROY
{
    my $self = shift;
    $self->{'_file'}->DESTROY() if ($self->{'_file'});
    return undef;
}

sub set
{
    my $self = shift;
    if ($self->{'_control_mode'} && $self->{'_control_mode'} =~ /current/i)
    {
	return $self->current(@_);
    }
    else
    {
        return $self->voltage(@_);
    }
}

sub maxcurrent()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->maxcurrent;
}

sub mincurrent()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->mincurrent;
}

sub maxvoltage()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->maxvoltage;
}

sub minvoltage()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    return $self->{'_psu'}->minvoltage;
}

sub get_version()
{
    my $self = shift;
    ### get the serial-server version ###
    return SocketClient::serial_client($self->{'_tty'},'version');
}

sub test()
{
    my $self = shift;
    return 0 unless ($self->{'_psu'} && $self->{'_psu'}->test); 
    return 0 unless ($self->{'_relay'} && $self->{'_relay'}->test); 
    return 1;
}


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


sub test_string()
{
    my $self = shift;
    my $string = 'PSU '.$self->name."\n";
    if ($self->{'_psu'})
    {
        $string .= $self->{'_psu'}->test_string(@_)."\n";
    }
    else
    {
        $string .= "Warning: No PSU device found!\n";
    }
    if ($self->{'_relay'})
    {
        $string .= $self->{'_relay'}->test_string(@_)."\n";
    }
    else
    {
        $string .= "Warning: No relay device found!\n";
    }
    return $string;
}

sub print_config()
{
    my $self = shift;
    my @arr = ();
    push @arr,'Name: '.$self->name;
    push @arr,'PSU type: '.$self->type;
    push @arr,$self->{'_psu'}->print_config if ($self->{'_psu'});
    push @arr,$self->{'_relay'}->print_config if ($self->{'_relay'});
    return join (', ',@arr);
}

sub RSD()
{
    my $self = shift;
    my $status = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
    $self->{'_psu'}->RSD($status);
    $self->notify('RSD',$status,@_);
}

sub voltage
{
    my $self = shift;
    if (@_)
    {
        my $v = shift;
        $self->{'_U'} = $v;
        $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
        if ($v =~ /\d/ )
        {
            $self->writedebug('Setting voltage to '.$self->{'_U'}.' V') if ($self->debug > 1);
	    $self->{'_psu'}->voltage($v,@_);
        }
        else
        {
            $self->writedebug('Setting voltage to OCV') if ($self->debug > 1);
            $self->{'_psu'}->voltage('ocv',@_);
        }
	$self->notify('voltage',$v,@_);
    }
    return $self->{'_U'};
}


sub set_relay
{
    my $self = shift;
    my $state = shift;
    my $cstate = $self->{'_relay'}->bool();
    return $state if ($cstate == $state);
    return $self->{'_relay'}->set($state,@_);
}

sub current
{
    my $self = shift;
    if (@_)
    {
        my $c = shift;
	if ($c =~ /\d+/)
	{
	    $self->{'_file'}->writeline(sprintf("%.4f",$c));
	}
	else
	{
	    $self->{'_file'}->writeline('ocv');
	}
        $self->{'_I'} = $c;
        $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'}  && $self->{'_relay'});
	$self->writedebug("Setting current for $self to $c");
        if ($c =~ /\d/ )
        {
            if ($c < 0)
            {
		$self->writedebug("Electrolysis mode, setting relay on and changing sign");
		$self->set_relay(1,@_);
		$self->{'_psu'}->current(-$c,@_);
            }
            else
            {
		$self->writedebug("FC mode, setting relay off and maintaining sign");
		$self->set_relay(0,@_);
                $self->{'_psu'}->current($c,@_);
            }
            $self->writedebug('Setting current to '.$self->{'_I'}.' A') if ($self->debug > 1);
        }
        else
        {
            $self->writedebug('Setting current to OCV') if ($self->debug > 1);
            $self->{'_psu'}->current('ocv',@_);
        }
	$self->notify('current',$c,@_);
    }
    return $self->{'_I'};
}

sub measure_U()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    return $self->{'_psu'}->measure_U(@_)
}

sub measure_I()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    my $pi = $self->{'_psu'}->measure_I(@_);
    $pi = -$pi if ($self->{'_relay'}->bool(@_));
    return $pi;
}

sub get_U()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    return $self->{'_psu'}->get_U(@_)
}

sub get_I()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    my $pi = $self->{'_psu'}->get_I(@_);
    $pi = -$pi if ($self->{'_relay'}->bool(@_));
    return $pi;
}

sub idn()
{
    my $self = shift;
    $self->die("Error: Device '".$self->name."', not properly initialised: one or more of the devices in container could not be initialised!") unless ($self->{'_psu'} && $self->{'_relay'});
    return $self->{'_psu'}->idn;
}


sub read()
{
    my $self = shift;
    return $self->measure_I(@_);
}

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

sub init
{
    my $self = shift;
    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/);
    }
    ## Init devices in container ###
    $self->{'_psu'} = $self->rig->get_device('PSU',$self->{'_PSU_device'});
    unless ($self->{'_psu'})
    {
        ### Implicitly initilaise device ###
        $self->{'_psu'} = $self->rig->init_device('PSU',$self->{'_PSU_device'});
        $self->{'_psu'}->readstring_ignore(1) if ($self->{'_psu'});
    }
    ### Use existing relay if it exists (which should not be the case! ) ####
    $self->{'_relay'} = $self->rig->get_device('relay',$self->{'_relay_device'});
    unless ($self->{'_relay'})
    {
        ### Implicitly initilaise device ###
        $self->{'_relay'} = $self->rig->init_device('relay',$self->{'_relay_device'});
        $self->{'_relay'}->readstring_ignore(1) if ($self->{'_relay'});
    }
    return $self;
}

return 1;
