Пример #1
0
def log_conn_state(inv, data=None):
    try:
        connected = inverter.get_conn_state(inv)
        power = inverter.get_power(inv, data)
        ts.log('Current connection state is %s - power output = %0.3f W' % (inverter.conn_state_str(connected), power))
    except Exception, e:
        ts.log('Error logging connect state: %s' % str(e))
        raise
Пример #2
0
def log_conn_state(inv, data=None):
    try:
        connected = inverter.get_conn_state(inv)
        power = inverter.get_power(inv, data)
        pf = inverter.get_power_factor(inv, data)
        ts.log('Current connection state is %s. Power output = %0.3f W. power factor %0.3f.' %
               (inverter.conn_state_str(connected), power, pf))
    except Exception, e:
        ts.log_error('Error logging connect state: %s' % str(e))
        raise
Пример #3
0
def test_run():

    result = script.RESULT_FAIL
    das = None
    wfmtrigger = None
    gsim = None
    pv = None
    inv = None
    filename = None
    disable = None

    try:
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        time_window = ts.param_value('vrt.settings.time_window')
        timeout_period = ts.param_value('vrt.settings.timeout_period')
        ramp_time = ts.param_value('vrt.settings.ramp_time')

        h_n_points = ts.param_value('vrt.settings.h_n_points')
        h_curve_num = ts.param_value('vrt.settings.h_curve_num')
        h_time = ts.param_value('vrt.h_curve.h_time')
        h_volt = ts.param_value('vrt.h_curve.h_volt')

        l_n_points = ts.param_value('vrt.settings.l_n_points')
        l_curve_num = ts.param_value('vrt.settings.l_curve_num')
        l_time = ts.param_value('vrt.l_curve.l_time')
        l_volt = ts.param_value('vrt.l_curve.l_volt')

        ride_through = ts.param_value('vrt.settings.ride_through')

        hc_n_points = ts.param_value('vrt.settings.hc_n_points')
        hc_curve_num = ts.param_value('vrt.settings.hc_curve_num')
        hc_time = ts.param_value('vrt.hc_curve.hc_time')
        hc_volt = ts.param_value('vrt.hc_curve.hc_volt')

        lc_n_points = ts.param_value('vrt.settings.lc_n_points')
        lc_curve_num = ts.param_value('vrt.settings.lc_curve_num')
        lc_time = ts.param_value('vrt.lc_curve.lc_time')
        lc_volt = ts.param_value('vrt.lc_curve.lc_volt')

        time_msa = ts.param_value('invt.time_msa')
        test_point_offset = ts.param_value('invt.test_point_offset')
        vrt_period = ts.param_value('invt.VRT_period')
        pretest_delay = ts.param_value('invt.pretest_delay')
        failure_count = ts.param_value('invt.failure_count')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        das, wfmtrigger, wfmtrigger_params = das_init()

        # initialize pv simulation
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # initialize grid simulation
        gsim = gridsim.gridsim_init(ts)

        #Inverter scan after grid and PV simulation setup so that Modbus registers can be read.
        ts.log('Scanning inverter')
        inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate, parity=parity,
                                         ipaddr=ipaddr, ipport=ipport)

        ### Find test points ###
        # determine the test points for the HVRT tests (ends near nominal)
        h_v_test_points = [h_volt[h_volt['index_start']]+test_point_offset]
        h_v_test_points.append(h_volt[h_volt['index_start']]-test_point_offset)
        for x in range(h_volt['index_start']+1, h_volt['index_count']):
            h_v_test_points.append(h_volt[x]+test_point_offset)
            h_v_test_points.append(h_volt[x]-test_point_offset)
        h_v_test_points.append(h_volt[h_volt['index_count']]+test_point_offset)
        h_v_test_points.append(h_volt[h_volt['index_count']]-test_point_offset)
        #ts.log_debug(h_v_test_points)

        # determine the test points for the LVRT tests (starts near nominal)
        l_v_test_points = [l_volt[l_volt['index_count']]+test_point_offset]
        l_v_test_points.append(l_volt[l_volt['index_count']]-test_point_offset)
        for x in range(l_volt['index_count']-1, l_volt['index_start'], -1):
            l_v_test_points.append(l_volt[x]+test_point_offset)
            l_v_test_points.append(l_volt[x]-test_point_offset)
        l_v_test_points.append(l_volt[l_volt['index_start']]+test_point_offset)
        l_v_test_points.append(l_volt[l_volt['index_start']]-test_point_offset)
        #ts.log_debug(l_v_test_points)

        v_test_points = h_v_test_points + l_v_test_points
        list(set(v_test_points))  # remove duplicate points
        # ts.log_debug(v_test_points)

        if ride_through == 'Yes':

            # determine the test points for the HVRTC tests (ends near nominal)
            hc_v_test_points = [hc_volt[hc_volt['index_start']]+test_point_offset]
            hc_v_test_points.append(hc_volt[hc_volt['index_start']]-test_point_offset)
            for x in range(hc_volt['index_start']+1, hc_volt['index_count']):
                hc_v_test_points.append(hc_volt[x]+test_point_offset)
                hc_v_test_points.append(hc_volt[x]-test_point_offset)
            hc_v_test_points.append(hc_volt[hc_volt['index_count']]+test_point_offset)
            hc_v_test_points.append(hc_volt[hc_volt['index_count']]-test_point_offset)
            #ts.log_debug(hc_v_test_points)

            # determine the test points for the LVRTC tests (starts near nominal)
            lc_v_test_points = [lc_volt[lc_volt['index_count']]+test_point_offset]
            lc_v_test_points.append(lc_volt[lc_volt['index_count']]-test_point_offset)
            for x in range(lc_volt['index_count']-1, lc_volt['index_start'], -1):
                lc_v_test_points.append(lc_volt[x]+test_point_offset)
                lc_v_test_points.append(lc_volt[x]-test_point_offset)
            lc_v_test_points.append(lc_volt[lc_volt['index_start']]+test_point_offset)
            lc_v_test_points.append(lc_volt[lc_volt['index_start']]-test_point_offset)
            #ts.log_debug(lc_v_test_points)

            v_test_points = v_test_points + hc_v_test_points + lc_v_test_points

        v_test_points = list(set(v_test_points))  # remove duplicate points
        v_test_points.sort()

        # remove negative test points
        for x in range(len(v_test_points)-1, 0, -1):
            if v_test_points[x] < 0:
                del v_test_points[x]
        ts.log('Voltage Test points are %s' % v_test_points)

        ######## Begin Test ########
        #if pretest_delay > 0:
        #    ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
        #    ts.sleep(pretest_delay)

        # note: timing parameters are not tested currently by this script - would need to wrap the assignment into loop
        # below to determine response times and timeout periods

        ts.log('Writing the VRT curves to the EUT')
        '''
        inverter.set_vrt_trip_high(inv, h_time=h_time, h_volt=h_volt, h_n_points=h_n_points, h_curve_num=h_curve_num,
                         time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time,
                         enable=1, wfmtrigger=wfmtrigger)

        inverter.set_vrt_trip_high(inv, l_time=l_time, l_volt=l_volt, l_n_points=l_n_points, l_curve_num=l_curve_num,
                         time_window=time_window, timeout_period=timeout_period, ramp_time=ramp_time,
                         enable=1, wfmtrigger=wfmtrigger)

        if ride_through == 'Yes':
            inverter.set_vrt_stay_connected_high(inv, hc_time=hc_time, hc_volt=hc_volt, hc_n_points=hc_n_points,
                                                 hc_curve_num=hc_curve_num, time_window=time_window,
                                                 timeout_period=timeout_period, ramp_time=ramp_time,
                                                 enable=1, wfmtrigger=wfmtrigger)

            inverter.set_vrt_stay_connected_low(inv, lc_time=lc_time, lc_volt=lc_volt, lc_n_points=lc_n_points,
                                                 lc_curve_num=lc_curve_num, time_window=time_window,
                                                 timeout_period=timeout_period, ramp_time=ramp_time,
                                                 enable=1, wfmtrigger=wfmtrigger)
        '''

        failures = 0  # failure counter
        for i in xrange(0, len(v_test_points)):
            # determine the expected behavior
            c_time, d_time = predict_vrt_response_time(v_test_points[i], ride_through,
                                                       h_time=h_time, h_volt=h_volt, h_n_points=h_n_points,
                                                       l_time=l_time, l_volt=l_volt, l_n_points=l_n_points,
                                                       hc_time=hc_time, hc_volt=hc_volt, hc_n_points=hc_n_points,
                                                       lc_time=lc_time, lc_volt=lc_volt, lc_n_points=lc_n_points)

            ts.log('Test %i, test voltage = %0.3f %%Vref. Expected Ride-Through Time = %0.3f sec. '
                   'Expected Trip Time = %0.3f sec.' % (i+1, v_test_points[i], c_time, d_time))

            if d_time == 0.:  # test doesn't have a trip boundary. Set d_time to max time plus verification time
                max_time = max(l_time, lc_time, h_time, hc_time)
                ts.log_debug('max_time: %s, max(max_time): %s' % (max_time, max(max_time)))
                d_time = max_time + verification_delay

            ### Make sure the EUT is on and operating
            if inverter.get_conn_state(inv) and inverter.get_power_norm(inv) < 0.05:
                ts.log_warning('EUT not operating! Checking grid simulator operations.')

                # if the inverter is off it's probably because the grid simulator is misconfigured.
                if gsim:
                    gsim.profile_stop()  #abort the profile
                    ts.log('grid nominal voltage: %s' % gsim.v_nom())
                    gsim.voltage(gsim.v_nom())  # return simulator to nominal voltage

                ts.log('Waiting up to %d seconds for EUT to begin power export.' % (verification_delay+pretest_delay))
                if verify_initial_conn_state(inv, state=inverter.CONN_CONNECT,
                                             time_period=verification_delay+pretest_delay, das=das) is False:
                        ts.log_error('Inverter unable to be set to connected state.')
                        raise script.ScriptFail()

            ### Arm the data acquisition system for waveform capture
            if das is not None:
                das_time = inverter.get_time(das=das)
                while das_time == inverter.get_time(das=das):
                    ts.log('Monitoring the data stream to ensure the das is prepared for a waveform capture. '
                           'DAS time: %s' % inverter.get_time(das=das))
                    ts.sleep(1)

                ts.log('Configuring the data capture for the following channels: %s' %
                       wfmtrigger_params.get('trigacqchannels'))
                ts.log('Configuring the %s waveform trigger for %s = %0.3f' %
                       (wfmtrigger_params.get('trigcondition'), wfmtrigger_params.get('trigchannel'),
                        float(wfmtrigger_params.get('trigval'))))
                # ts.log_debug('wfmtrigger_params = %s' % wfmtrigger_params)
                wfmtrigger.trigger(wfmtrigger_params=wfmtrigger_params)

                ts.log('Data acquisition preparing for waveform capture. Waiting for pre-test delay of %d seconds'
                       % pretest_delay)
                starttime = time.time()
                while pretest_delay >= (time.time()-starttime):
                    totaltime = time.time()-starttime
                    ts.log('Waiting %0.3f more seconds.' % (pretest_delay-totaltime))
                    ts.sleep(1.0 - totaltime % 1)

            else:  # there is no data acquisition system
                ts.log_warning('No data acquisition system configured.')
                if ts.confirm('Please configure the trigger to capture the ride-through and enable it.') is False:
                    raise script.ScriptFail('Aborted VRT!')

            if v_test_points[i] < 100.:
                vrt_test_voltage = v_test_points[i]+test_point_offset
            else:
                vrt_test_voltage = v_test_points[i]-test_point_offset

            ### Execute the voltage change
            if gsim is not None:
                ### create transient event in grid simulator
                if d_time == 0 and c_time == 0:  # near nominal
                    test_duration = max(h_time, l_time, lc_time, hc_time)
                    # be sure to catch end of transient with at least a 3 cycle window
                    wfmtrigger_params['posttrig'] = test_duration + max(verification_delay, 0.0166*3)
                else:
                    test_duration = max(c_time, d_time)
                    # be sure to catch end of transient with at least a 3 cycle window
                    wfmtrigger_params['posttrig'] = test_duration + max(verification_delay, 0.0166*3)
                ts.log('The post trigger time has been adjusted to %s for this ride through test to capture '
                       'the EUT dynamics' % wfmtrigger_params.get('posttrig'))

                # Use the profile so the timing for the event is accurate and there is a trigger from the simulator
                gsim.profile_load(profile_name='Transient_Step', v_step=vrt_test_voltage, f_step=100,
                                  t_step=test_duration)
                ts.log('Profile is loaded in simulator. Running the grid simulator profile.')
                gsim.profile_start()
            else:
                ts.log('Must set the grid simulator voltage to the ride-through voltage.')
                if ts.confirm('Set the grid simulator to the test voltage: %0.3f %%Vref.' %
                              vrt_test_voltage) is False:
                    raise script.ScriptFail('Aborted VRT!')

            ### Wait for DAS to capture transient event
            start_time = time.time()
            elapsed_time = 0.
            while elapsed_time <= wfmtrigger_params['posttrig']:
                ts.log('Waiting for waveform capture to complete. Total time remaining %0.3f seconds' %
                       (wfmtrigger_params['posttrig']-elapsed_time))
                ts.sleep(0.93)
                elapsed_time = time.time() - start_time

            ### Screen waveform data and save in the results file
            if das is not None:

                ts.log('Waiting post test delay of %0.2f seconds before processing the data file.' % posttest_delay)
                ts.sleep(posttest_delay)

                # get data from waveform saved on the hard drive
                # (this function could use a little help to make it more robust...)
                wfmname = wfmtrigger.getfilename()
                ts.log('Analyzing waveform data in file "%s".' % wfmname)

                if ts.param_value('wfm.trigchannel').count(',') == 3:
                    wfmtime, ac_voltage, ac_current = wfmtrigger.read_file(wfmname)

                    # calculate the time the EUT rode through the voltage event
                    # ride_through_time == 0 means no trip/ceassation
                    ride_through_time = calc_ride_through_duration(wfmtime, ac_current, ac_voltage=ac_voltage)

                else:  # if there are more than 3 channels being collected, assume the first 4 the following:
                    wfmtime, ac_voltage, ac_current, grid_trig = wfmtrigger.read_file(wfmname)

                    # calculate the time the EUT rode through the voltage event
                    # ride_through_time == 0 means no trip/ceassation
                    ride_through_time = calc_ride_through_duration(wfmtime, ac_current, grid_trig=grid_trig)

                if ride_through_time == 0:
                    ts.log('The EUT did not trip or momentarily cease to energize.')
                else:
                    ts.log('The ride-through duration was %0.3f.' % ride_through_time)

                if ride_through_time - time_msa < c_time:
                    ts.log_warning('The ride-through duration of %0.3f minus the manufacturers stated '
                                   'accuracy of %0.3f is less '
                                   'than the ride-through time of %0.3f.' % (ride_through_time, time_msa, c_time))
                    failures += 1
                    ts.log_warning('The number of failures is %i.' % failures)
                elif ride_through_time + time_msa > d_time:
                    ts.log_warning('The ride-through duration of %0.3f plus the manufacturers stated '
                                   'accuracy of %0.3f is more '
                                   'than the must disconnect time of %0.3f.' % (ride_through_time, time_msa, c_time))
                    failures += 1
                    ts.log_warning('The number of failures is %i.' % failures)

                # save file to results
                results_dir = os.path.dirname(__file__)[:-7] + 'Results' + os.path.sep
                ts.log('Moving waveform "%s" to results folder: %s.' % (wfmname, results_dir))
                wfmtrigger.move_file_to_results(wfmname=wfmname, results_dir=results_dir, delete_original='No')

            else:
                ts.log('Ride-through test complete. Please analyze the data to assign pass/fail result.')

            if failures >= failure_count:
                raise script.ScriptFail()

        ts.log('Waiting the post-test duration %i.' % posttest_delay)
        ts.sleep(posttest_delay)

        result = script.RESULT_PASS

    except script.ScriptFail, e:
        reason = str(e)
        if reason:
            ts.log_error(reason)
Пример #4
0
def test_run():

    result = script.RESULT_FAIL
    data = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:

        # UL 1741 Test Protocol
        # a.	Connect the EUT according to the Requirements in Sec. 11.2.4 and specifications provided by the
        #       manufacturer. Set the EUT to maximum power factor.

        # b.	Set all AC source parameters to the nominal operating conditions for the EUT.

        # c.	Set the input power level to provide Ilow from the EUT. Note: for units that do not adjust output
        #       current as a function of their input such as units with energy storage or multimode products the output
        #       power is to be commanded.

        # d.	Turn on the EUT.  Allow the EUT to reach steady state, e.g., maximum power point.

        # e.	Set the EUT ramp rate parameters according to Test 1 in Table SA 11.1.

        # f.	Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.

        # g.	Increase the available input power to provide Irated from the EUT according to the step function
        #       described in SA 11.

        # h.	Stop recording the time domain response after the ramp duration plus a manufacturer-specified dwell
        #       time. Ramp duration is defined by 100/RRnorm_up as appropriate for the test settings.

        # i.	Repeat steps c-h two times for a total of 3 repetitions.

        # j.	Repeat steps c-i for Tests 2-3 in Table SA 11.1.

        # EUT communication parameters
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        # RR parameters
        RRnorm_up_min = ts.param_value('rr.RRnorm_up_min')
        RRnorm_up_max = ts.param_value('rr.RRnorm_up_max')
        Ilow = ts.param_value('rr.Ilow')
        Irated = ts.param_value('rr.Irated')
        MSARR = ts.param_value('rr.MSARR')
        t_dwell = ts.param_value('rr.t_dwell')

        # Script timing and pass/fail criteria
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        power_threshold = ts.param_value('invt.power_threshold')
        disable = ts.param_value('invt.disable')

        # initialize data acquisition system
        daq = das.das_init(ts)
        data = daq.data_init()
        trigger = daq.trigger_init()

        # Step b.	Set all AC source parameters to the nominal operating conditions for the EUT.
        # Initialize pv simulation - This is before step (a) because PV power may be required for communications to EUT
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        # Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % e)

        # Step a.	Connect the EUT according to the Requirements in Sec. 11.2.4 and specifications provided by the
        #       manufacturer. Set the EUT to maximum power factor.
        # It is assumed that the  Grid Simulator (if used) is connected to the EUT and operating properly
        inverter.set_power_factor(inv, power_factor=1., enable=0)

        # UL 1741 Step j.	Repeat steps c-i for Tests 2-3 in Table SA 11.1.
        for ramp in [RRnorm_up_min, (RRnorm_up_min + RRnorm_up_max)/2, RRnorm_up_max]:

            for i in xrange(3):  # UL 1741 Step i. Repeat steps c-h two times for a total of 3 repetitions.

                ts.log('Running test number %d with ramp rate %0.3f %%Irated/sec.' %
                       (i+1, ramp))

                # Step c. Set the input power level to provide Ilow from the EUT. Note: for units that do not adjust
                #       output current as a function of their input such as units with energy storage or multimode
                #       products the output power is to be commanded.
                pv.irradiance_set(irradiance=Ilow*10)

                # Step d.	Turn on the EUT.  Allow the EUT to reach steady state, e.g., maximum power point.
                if pretest_delay > 0:
                    ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
                    ts.sleep(pretest_delay)

                # Verify EUT is in correct state before running the test.
                if inverter.get_conn_state(inv) is False:
                    ts.log('Inverter not in correct state, setting state to connected.')
                    inverter.set_conn_state(inv, state=1)
                    if verify_conn_state_change(inv, orig_state=0, verification_delay=verification_delay,
                                                threshold=power_threshold, data=data) is False:
                        raise script.ScriptFail()

                # Step e.	Set the EUT ramp rate parameters according to Test 1 in Table SA 11.1.
                try:
                    inv.settings.read()
                    if inv.settings.WGra is not None:
                        inv.settings.WGra = ramp
                    else:
                        ts.log_error('Unable to change ramp rate in the EUT.')
                except Exception, e:
                    ts.log_error('Error changing ramp rate in the EUT: %s' % str(e))

                # Step g.	Increase the available input power to provide Irated from the EUT according to the step
                #           function described in SA 11.
                pv.irradiance_set(irradiance=1000)
                start_time = time.time()

                # Step h.	Stop recording the time domain response after the ramp duration plus a
                #           manufacturer-specified dwell time.
                data_update_rate = 1  # Hz
                check_duration = (Irated-Ilow)/ramp
                test_duration = t_dwell + check_duration
                duration = 0
                while duration < test_duration+verification_delay:
                    duration = time.time()-start_time
                    ts.log_debug('duration = %0.2f, check duration = %0.2f' % (duration, check_duration))
                    if duration <= check_duration:  # only check the ramp response during the check_duration
                        ramp_in_bounds = verify_ramp(inv, ramp=ramp, t_since_step=duration, Ilow=Ilow,
                                                     Irated=Irated, MSARR=MSARR, data=data)
                        if ramp_in_bounds is False:
                            ts.log_error('Ramp response was not within limits')
                            # raise script.ScriptFail()
                    else:  # The EUT shall reach at least 95% of Irated at the end of the dwell time.
                        ts.log('EUT completed ramping. Waiting for dwell time to check current output. '
                               'Remaining time: %0.3f' % (test_duration - duration))
                        if duration >= test_duration:
                            current_pct = inverter.get_power_norm(inv=inv, das=data)*100
                            ts.log_error('EUT current is %0.3f%%' % current_pct)
                            if current_pct < 95:
                                ts.log_error('EUT did not reach at least 95% of Irated at the end of the dwell time.')
                                raise script.ScriptFail()
                            break
                    time.sleep(1/data_update_rate)  # todo: should improve the loop timing

                if posttest_delay > 0:
                    ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
                    ts.sleep(posttest_delay)
Пример #5
0
def test_run():

    result = script.RESULT_FAIL
    das = None
    trigger = None
    inv = None
    pv = None
    disable = None

    try:

        # UL 1741 Test Protocol
        # SA 11.3.2 The soft-start test shall be carried out as follows:

        # a)	Connect the EUT according to the instructions and specifications provided by the manufacturer.

        # b)	Set all AC source parameters to the nominal operating conditions for the EUT.

        # c)	Set the input  source power level to provide  Irated from the EUT. Note: for units that do not
        # adjust output current as a function of their input such as units with energy storage or multimode products
        # the output power is to be commanded.

        # d)	Turn on the EUT.  Set the EUT ramp rate parameters according to Test 1 in Table SA 11.2.

        # e)	Adjust the AC voltage or frequency outside the near nominal range for a period exceeding setting the
        # AC voltage to zero for longer than the must-trip duration.

        # f)	Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.

        # g)	Adjust the AC source to the rated nominal operating conditions for the EUT. The EUT shall not
        # commence exporting output current until nominal conditions have been achieved.

        # h)	Stop recording the time domain response after at least the reconnect time of the inverter
        # (e.g. 30 sec. to 5 minutes), plus ramp duration plus a manufacturer-specified dwell time as shown in SA 11.
        # Ramp duration is defined by 100/RRss as appropriate.

        # i)	Repeat steps e-h for a total of 3 repetitions.

        # j)	Repeat steps d-i for Tests 2-3 in Table 11.2.


        # EUT communication parameters
        ifc_type = ts.param_value('comm.ifc_type')
        ifc_name = ts.param_value('comm.ifc_name')
        if ifc_type == client.MAPPED:
            ifc_name = ts.param_value('comm.map_name')
        baudrate = ts.param_value('comm.baudrate')
        parity = ts.param_value('comm.parity')
        ipaddr = ts.param_value('comm.ipaddr')
        ipport = ts.param_value('comm.ipport')
        slave_id = ts.param_value('comm.slave_id')

        # RR parameters
        RRss_min = ts.param_value('ss.RRss_min')
        RRss_max = ts.param_value('ss.RRss_max')
        #Ilow = ts.param_value('ss.Ilow')
        Irated = 100.
        MSARR = ts.param_value('ss.MSARR')
        t_dwell = ts.param_value('ss.t_dwell')

        # Script timing and pass/fail criteria
        pretest_delay = ts.param_value('invt.pretest_delay')
        verification_delay = ts.param_value('invt.verification_delay')
        posttest_delay = ts.param_value('invt.posttest_delay')
        power_threshold = ts.param_value('invt.power_threshold')
        disable = ts.param_value('invt.disable')

        # Data acquisition and triggering methods
        datamethod = ts.param_value('datatrig.dsm_method')
        trigmethod = ts.param_value('datatrig.trigger_method')

        # Step f. Begin recording the time domain response of the EUT AC voltage and current, and DC voltage and current.

        # Step h. Stop recording the time domain response after at least the reconnect time of the inverter
        #         (e.g. 30 sec. to 5 minutes), plus ramp duration plus a manufacturer-specified dwell time as shown in
        #         SA 11. Ramp duration is defined by 100/RRss as appropriate.

        if datamethod == 'Sandia LabView DSM':
            import sandia_dsm as dsm
            das = dsm.Data()
            computer = ts.param_value('datatrig.das_comp')
            if computer == '10 node':
                node = ts.param_value('datatrig.node')

        # Setup trigger if available
        if trigmethod == 'Create Local File for Sandia LabView DSM':
            import sandia_dsm as dsm
            trigger = dsm.Trigger()
            trigger.off()

        # Step b.	Set all AC source parameters to the nominal operating conditions for the EUT.
        # Initialize pv simulation - This is before step (a) because PV power may be required for communications to EUT
        pv = pvsim.pvsim_init(ts)
        pv.power_on()

        grid = gridsim.gridsim_init(ts)

        # Communication is established between the Utility Management System Simulator and EUT
        ts.log('Scanning EUT')
        try:
            inv = client.SunSpecClientDevice(ifc_type, slave_id=slave_id, name=ifc_name, baudrate=baudrate,
                                             parity=parity, ipaddr=ipaddr, ipport=ipport)
        except Exception, e:
            raise script.ScriptFail('Error: %s' % e)

        # Step a.	Connect the EUT according to the instructions and specifications provided by the manufacturer.
        # It is assumed that the  Grid Simulator (if used) is connected to the EUT and operating properly
        inverter.set_power_factor(inv, power_factor=1., enable=0)

        # Step c. Set the input  source power level to provide Irated from the EUT. Note: for units that do not
        # adjust output current as a function of their input such as units with energy storage or multimode
        # products the output power is to be commanded.
        pv.irradiance_set(irradiance=1000)

        # UL 1741 Step j.	Repeat steps d-i for Tests 2-3 in Table 11.2.
        for ramp in [RRss_min, (RRss_min + RRss_max)/2, RRss_max]:

            # Step d.	Turn on the EUT. Set the EUT ramp rate parameters according to Test 1 in Table SA 11.2.
            if pretest_delay > 0:
                ts.log('Waiting for pre-test delay of %d seconds' % pretest_delay)
                ts.sleep(pretest_delay)

            # Verify EUT is in correct state before running the test.
            if inverter.get_conn_state(inv) is False:
                ts.log('Inverter not in correct state, setting state to connected.')
                inverter.set_conn_state(inv, state=1)
                if verify_conn_state_change(inv, orig_state=0, verification_delay=verification_delay,
                                            threshold=power_threshold, das=das) is False:
                    raise script.ScriptFail()

            ''' Revise when SS ramp rate exists in a SunSpec Model
            try:
                inv.settings.read()
                if inv.settings.SSWGra is not None:
                    inv.settings.SSWGra = ramp
                else:
                    ts.log_error('Unable to change ss ramp rate in the EUT.')
            except Exception, e:
                ts.log_error('Error changing ss ramp rate in the EUT: %s' % str(e))
            '''

            for i in xrange(3):  # UL 1741 Step i. Repeat steps e-h two times for a total of 3 repetitions.

                ts.log('Running test number %d with ramp rate %0.3f %%Irated/sec.' % (i+1, ramp))

                # e)	Adjust the AC voltage or frequency outside the near nominal range for a period exceeding
                # setting the AC voltage to zero for longer than the must-trip duration.
                grid.voltage(0)
                time.sleep(1)

                # g)	Adjust the AC source to the rated nominal operating conditions for the EUT. The EUT shall not
                # commence exporting output current until nominal conditions have been achieved.
                grid.voltage(grid.v_nom())
                start_time = time.time()

                # Determine reconnection time
                t_reconnection = 0
                while inverter.get_conn_state(inv) is False:
                    t_reconnection = time.time()-start_time  # Reconnection time updates until the inverter reconnects
                    time.sleep(0.1)

                data_update_rate = 1  # Hz ... parameterize sometime...
                check_duration = 100./ramp
                test_duration = t_dwell + check_duration
                duration = 0
                while duration < test_duration+verification_delay:
                    duration = time.time()-start_time-t_reconnection
                    if duration <= check_duration:  # only check the ramp response during the check_duration
                        ramp_in_bounds = verify_ramp(inv, ramp=ramp, t_since_start=duration, Irated=Irated, MSARR=MSARR,
                                                     das=das)
                        if ramp_in_bounds is False:
                            ts.log_error('Ramp response was not within limits')
                            # raise script.ScriptFail()
                    else:  # The EUT shall reach at least 95% of Irated at the end of the dwell time.
                        ts.log('EUT completed ramping. Waiting for dwell time to check current output. '
                               'Remaining time: %0.3f' % (test_duration - duration))
                        if duration >= test_duration:
                            current_pct = inverter.get_power_norm(inv=inv, das=das)*100
                            ts.log_error('EUT current is %0.3f%%' % current_pct)
                            if current_pct < 95:
                                ts.log_error('EUT did not reach at least 95% of Irated at the end of the dwell time.')
                                raise script.ScriptFail()
                            break
                    time.sleep(1/data_update_rate)  # todo: improve the loop timing

                if posttest_delay > 0:
                    ts.log('Waiting for post-test delay of %d seconds' % posttest_delay)
                    ts.sleep(posttest_delay)

        result = script.RESULT_PASS