Copyright©2018InClime SolutionsPage 1
Table of Contents
Description of API to Transfer PV Applications to PennAEPS
Audience
Prerequisites
API Requirements
Flow of Transfer Process
Client Programming Steps of Transfer Process
InClime Transfer Data Format
Required Documents
Config Settings
For Development (Testing)
For Production
Sample PHP Code
Display of Sample Transfer Array
Sample Success/Error Messages
Reviewing Transfer Status of Applications
Description of API to Transfer PV Applications to PennAEPS
This InClime Solutions transfer Application Program Interface (API) allows organizations to take data from their current Photovoltaic (PV) application system and transfer the information to create an application in the Pennsylvania Alternative Energy Portfolio Standard (PennAEPS) program.
Described in this document are the requirements for use of the API, the format of the transfer data, as well as sample PHP code that will enable a developer to programmatically initiate the transfer.
Audience
This document is written for developers who have a working knowledge of PHP or other similar programming languages.
Prerequisites
API Requirements
- Before you begin, you will need to obtain an API key from InClime Solutions in order to initiate the handshake between your website and the InClime’s Transfer API. Contact InClime Solutions for this information.
- Make the necessary changes to your development config file (See Config For Development) so that you can use this for testing until you and InClime have agreed that your process is valid, where your production code will use the settings it the production config file (See ConfigFor Production.)
- It’s best if you allow users to have a page that lists applications that are ready for transfer and allows them to select applications for which they want data transferred.
- Review InClime Transfer Data Format and determine what fields are required from your database and in which tables they are located. This includes locating where the application documents are located on your server (e.g. System Photo.)
- Use the Sample PHP Code as a guide to write your program to transfer the data.
Flow of Transfer Process
Client Programming Steps of Transfer Process
(Copy the Sample PHP Code and adjust it for your company’s specific data formats, website name, document locations, and InClime supplied API credentials.)
- Allow user to select applications that need to be submitted to PennAEPS.
- Application data is obtained by querying client tables.
- An array is filled, formatted, and with the exact names listed in InClime Transfer Data Format. Note that the array is not position based, but rather key name based.
- The client program passes its company credentials to the InClime API.
- InClime verifies the credentials and returns a success or fail acknowledgement.
- If the client program receives a success acknowledgement from InClime, the array, which contains the applications’ data, including properly formatted document contents, is passed to the API.
- InClime validates the applications’ data.
- InClime returns errors codes on invalid applications.
- InClime processes applications with no validation errors, and returns success codes for applications that have been submitted into the PennAEPS program.
InClime Transfer Data Format
Note: The transfer data is based on field name and not field position.
Inclime Field Name / Format(max length) / Reqd? / Descriptionuser_email / String (255)
email / Y / Your admin’s email address
aggregator_email / String (255)
email / Y / Aggregator’s email address
facilities_name / String (80) / Y / Name of the facility
Property Information
property_owner / String
(80) / Y / Name of property owner (or Attention)
address1 / String
(80) / Y / Street or address
address2 / String
(80) / N / Suite or apartment
city / String
(80) / Y / City
state / String
(2)
ST abbrev / Y / State
zip / String
(10)
nnnnn[-nnnn] / Y / Zip
email / String
(40)
email / N / Email address
eia_plant_name / String (100) / N / Energy Information Agency facility name
interconnecting_utility / String
(50) / Y / Utility facility is connected to
“Citizens Electric Company“
“Duquesne Light Company“
“Metropolitan Edison Company“
“PECO Energy“
“Pennsylvania Electric Company“
“Pennsylvania Power Company“
“Pike County Light and Power“
“PPL Electric Utilities“
“UGI Utilites, Inc. “
“Wellsboro Electric Company“
“West Penn Power Company“
“Other“
other_utility_name / String
(80) / N / If interconnecting_utility = ‘Other’, this is required
facility_leased / String
(10) / Y / If facility is leased
“Leased” or “Not Leased”
customer_sited / String
(3) / Y / Majority of facility serves an on-site load
“yes” or “no”
energize_date / String
(10)
mm/dd/yyyy / Y / Date system was turned on and began operating (must be prior to current date)
online_date / String
(10)
mm/dd/yyyy / Y / Date interconnection was approved (must be prior to current date)
RTO / String
(5) / Y / Regional Transmission Organization
“PJM“ “MISO” or “Other”
GATS_NON / String
(10) / N / GATS Unit ID, eg NON12345
first_state / String
(3) / Y / Is this the first state where facility is registered?
“yes” or “no”
other_states / String
(2)
ST abbrev / N / State where facility is also registered. If first_state is “no”, this is required.
pv_system_type / String
(80) / Y / System type
“Utility Interconnected” or
“Utility Interconnected w/ battery”
pv_installation_location / String
(80) / Y / Mounting location of installation
“Ground” or “Rooftop”
pv_tracking_axis / Integer / Y / If there is no tracking axis, or single or double tracking axis
0, 1 or 2
pv_total_array_output / Integer
watts (kw*1000) / Y / Total output (number of modules * power rating) of all arrays
pv_multiple_tilt / Integer / Y / Number of arrays
1 through 5
First Array
pv_number_of_modules / Integer / Y / Number of solar modules
pv_power_rating / Integer / Y / Power rating (DC watts at Standard Test Conditions)
pv_derate / Floating / Y / Derate factor for this array
From 0 to less than 1, typically 0.14
pv_system_tilt / Integer
degrees / Y / The tilt of this array
Between 0 and 90
pv_system_azimuth / Integer
degrees / Y / The azimuth of this array
Between 0 and 360, where 18- is south facing
Second Array
*2=Required if pv_multiple_tilt > 1
pv_number_of_modules2 / Integer / *2 / Number of solar modules
pv_power_rating2 / Integer / *2 / Power rating (DC watts at Standard Test Conditions)
pv_derate2 / Floating / *2 / Derate factor for this array
From 0 to less than 1, typically 0.14
pv_system_tilt_2 / Integer
degrees / *2 / The tilt of this array
Between 0 and 90
pv_system_azimuth_2 / Integer
degrees / *2 / The azimuth of this array
Between 0 and 360, where 18- is south facing
Third Array
*3=Required if pv_multiple_tilt > 2
pv_number_of_modules3 / Integer / *3 / Number of solar modules
pv_power_rating3 / Integer / *3 / Power rating (DC watts at Standard Test Conditions)
pv_derate3 / Floating / *3 / Derate factor for this array
From 0 to less than 1, typically 0.14
pv_system_tilt_3 / Integer
degrees / *3 / The tilt of this array
Between 0 and 90
pv_system_azimuth_3 / Integer
degrees / *3 / The azimuth of this array
Between 0 and 360, where 18- is south facing
Fourth Array
*4=Required if pv_multiple_tilt > 3
pv_number_of_modules4 / Integer / *4 / Number of solar modules
pv_power_rating4 / Integer / *4 / Power rating (DC watts at Standard Test Conditions)
pv_derate4 / Floating / *4 / Derate factor for this array
From 0 to less than 1, typically 0.14
pv_system_tilt_4 / Integer
degrees / *4 / The tilt of this array
Between 0 and 90
pv_system_azimuth_4 / Integer
degrees / *4 / The azimuth of this array
Between 0 and 360, where 18- is south facing
Fifth Array
*5=Required if pv_multiple_tilt > 4
pv_number_of_modules5 / Integer / *5 / Number of solar modules
pv_power_rating5 / Integer / *5 / Power rating (DC watts at Standard Test Conditions)
pv_derate5 / Floating / *5 / Derate factor for this array
From 0 to less than 1, typically 0.14
pv_system_tilt_5 / Integer
degrees / *5 / The tilt of this array
Between 0 and 90
pv_system_azimuth_5 / Integer
degrees / *5 / The azimuth of this array
Between 0 and 360, where 18- is south facing
Owner Information
owner_name / String (80)
firstname + “ “ + lastname / Y / The first and last name of the owner.
owner_company_name / String
(80) / N / Company name
owner_address1 / String
(80) / Y / Street address
owner_address2 / String
(80) / N / Suite or apartment
owner_city / String
(80) / Y / City
owner_state / String
(2) / Y / State
owner_zip / String
(10) / Y / Zip
owner_phone / String
(20)
nnn-nnn-nnnn / Y / Phone
owner_email / String
(80)
email / Y / Email address
pv_meter_reading / Integer / N / Last meter reading
api_application_id / String / Y / Your application id for reference in reporting back any errors on transfer
attest_name / String (100)
firstname + “ “ + lastname / Y / The name of the person who signed the form provided by InClime that attests to the Customer Sited Generation.
Application Documents
(SeeRequired Documents)
Maximum length of full transfer array contents depends
on memory settings in php.ini
doc_panels_file_ext / String
jpg|pdf|jpeg / N / File extension for the System Photo
doc_panels_file / String / N / Base 64 encoded file contents of System Photo
doc_meter_file_ext / String
jpg|pdf|jpeg / N / File extension for the Meter Photo
doc_meter_file / String / N / Base 64 encoded file contents of Meter Photo
doc_schedulea_file_ext / String
jpg|pdf|jpeg / N / File extension for the Schedule A
doc_schedulea_file / String / N / Base 64 encoded file contents of the Schedule A
doc_roa_file_ext / String
jpg|pdf|jpeg / N / File extension for the Recognition of Assignment (for Leased Facilities)
doc_roa_file / String / N / Base 64 encoded file contents of ROA
doc_interconnection_file_ext / String
jpg|pdf|jpeg / N / File extension for the Interconnection Approval
doc_interconnection_file / String / N / Base 64 encoded file contents of the Interconnection Approval
doc_multiplephoto_file_ext / String
jpg|pdf|jpeg / N / File extension for a Multiple System Photo
doc_multiplephoto_file / String / N / Base 64 encoded file contents of a Multiple System Photo
doc_optionalupload_file_ext / String
jpg|pdf|jpeg / N / File extension for an Optional Upload file
doc_optionalupload_file / String / N / Base 64 encoded file contents of an Optional Upload file
Required Documents
Document / When RequiredSystem Photo / All applications
Interconnection Approval / All applications
Recognition of Assignment / Applications for facilities that are ‘Leased’
Schedule A / Applications for facilities that are ‘Not Leased’
Meter Photo / Applications that are being submitted more than 30 days after the date interconnection was approved (online_date)
Config Settings
In order to keep your code separate and not hard-code the URL target for the PennAEPS API, place this setting in a config file (e.g. config\application.php).
For Development (Testing)
/*
|------
| PennAEPS Development export
|------
|
| Sets API URL target
|
*/
$config['pennaeps_api_url']= "
/*
For Production
/*
|------
| PennAEPS Production export
|------
|
| Sets API URL target
|
*/
$config['pennaeps_api_url']= "
/*
Sample PHP Code
function sample($app_ids){
// Get your application data
$SQL="SELECT * FROM tblApplication WHERE application_id in $app_ids";
$query=$this->db->query($SQL));
$data=array();
/*****************************************************
Fill the $data array
Note to client developer – you will fill the array
by keeping the exact names of the keys, on the
left (eg "user_email")
******************************************************/
foreach($query->result_array()as$row){
$data[]=array(
"user_email"=>'',
"aggregator_email"=>null,
"facilities_name"=>trim($row['facilities_name']),
"property_owner"=>trim($row['attention']),
"address1"=>trim($row['address1']),
"address2"=>trim($row['address2']),
"city"=>trim($row['city']),
"state"=>trim($row['state']),
"zip"=>trim($row['zip']),
"email"=>trim($row['email']),
"eia_plant_name"=>trim($row['eia_plant_name']),,
"interconnecting_utility"=>"Other",
"other_utility_name"=>trim($row['interconnecting_utility']),
"facility_leased"=>$row['own_lease'],
"customer_sited"=>$row['customer_sited '],
"energize_date"=>trim($row['date_turned_on']),
"online_date"=>trim($row['date_of_interconnection']),
"RTO"=>trim($row['RTO']),
"GATS_NON"=>trim($row['gats_non_number']),
"first_state"=>(empty($row['registered_state']) || $row['registered_state'])==’PA’
? "yes” : "no"),
"other_states"=>$row['registered_state'],
"pv_system_type"=>$row['system_type],
"pv_installation_location"=>$row['installation_location'],
"pv_tracking_axis"=>$row['tracking_axis'],
"pv_total_array_output"=>trim($row['total_array_output']),
"pv_multiple_tilt"=>trim($row['multiple_tilt']),
"pv_number_of_modules"=>trim($row['number_of_modules']),
"pv_power_rating"=>trim($row['module_power_rating']),
"pv_derate"=>trim($row['derate']),
"pv_system_tilt"=>trim($row['system_tilt']),
"pv_system_azimuth"=>trim($row['system_azimuth']),
"pv_number_of_modules2"=>$row["number_of_modules_2"],
"pv_power_rating2"=>$row["power_rating_2"],
"pv_derate2"=>$row["derate_2"],
"pv_system_tilt_2"=>$row["system_tilt_2"],
"pv_system_azimuth_2"=>$row["system_azimuth_2"],
"pv_number_of_modules3"=>$row["number_of_modules_3"],
"pv_power_rating3"=>$row["power_rating_3"],
"pv_derate3"=>$row["derate_3"],
"pv_system_tilt_3"=>$row["system_tilt_3"],
"pv_system_azimuth_3"=>$row["system_azimuth_3"],
"pv_number_of_modules4"=>$row["number_of_modules_4"],
"pv_power_rating4"=>$row["power_rating_4"],
"pv_derate4"=>$row["derate_4"],
"pv_system_tilt_4"=>$row["system_tilt_4"],
"pv_system_azimuth_4"=>$row["system_azimuth_4"],
"pv_number_of_module5"=>$row["number_of_modules_5"],
"pv_power_rating5"=>$row["power_rating_5"],
"pv_derate5"=>$row["derate_5"],
"pv_system_tilt_5"=>$row["system_tilt_5"],
"pv_system_azimuth_5"=>$row["system_azimuth_5"],
"owner_name"=>trim($row['owner_name']),
"owner_company_name"=>trim($row['owner_company_name']),
"owner_address1"=>trim($row['owner_address1']),
"owner_address2"=>trim($row['owner_address2']),
"owner_city"=>trim($row['owner_city']),
"owner_state"=>trim($row['owner_state']),
"owner_zip"=>trim($row['owner_zip']),
"owner_phone"=>trim($row['owner_phone']),
"owner_email"=>trim($row['owner_email']),
"pv_meter_reading"=>trim($row['meter_reading']),
"api_application_id"=>$row['application_id'],
"attest_name"=>$current_user_name,
// panels => System Photo
"doc_panels_file_ext"=>preg_replace("#^.*\.#","",$row['doc_system_photo']),
"doc_panels_file"=>base64_encode(file_get_contents($row['doc_system_photo']),
// meter_file => Meter Photo
"doc_meter_file_ext"=>preg_replace("#^.*\.#","",$row['doc_meter_photo']),
"doc_meter_file"=>base64_encode(file_get_contents($row['doc_meter_photo'])),
// schedulea => Schedule A (application)
"doc_schedulea_file_ext"=>preg_replace("#^.*\.#","",$row['doc_schedule_A']),
"doc_schedulea_file"=>base64_encode(file_get_contents($row['doc_schedule_A'])),
// roa => ROA (application)
"doc_roa_file_ext"=>preg_replace("#^.*\.#","",$row['doc_roa']),
"doc_roa_file"=>base64_encode(file_get_contents($row['doc_roa'])),
// interconnection => Interconnection Approval
"doc_interconnection_file_ext"=>preg_replace("#^.*\.#","",
$row['doc_interconnection_approval]),
"doc_interconnection_file"=>base64_encode(file_get_contents(
$row['doc_interconnection_approval])),
// multiplephoto => Multiple System Photo
"doc_multiplephoto_file_ext"=>preg_replace("#^.*\.#","",
$row['doc_system_photo_2']),
"doc_multiplephoto_file"=>base64_encode(file_get_contents(
$row['doc_system_photo_2'])),
// optionalupload => Optional Upload
"doc_optionalupload_file_ext"=>preg_replace("#^.*\.#","",
$row['doc_optional_upload']),
"doc_optionalupload_file"=>base64_encode(file_get_contents(
$row['doc_optional_upload'])),
);
}
// Now send data to PennAEPS via API using a setting in config file(See Config Settings)
)
$url=$this->config->item('pennaeps_api_url');
$curl_handle=curl_init();
// Credentials below should be obtained from InClime Solutions
$args=array('id'=>nnn,'domain'=>'YourCompany.com','key'=>'…. your company key……….');
$arg_string=http_build_query($args);
curl_setopt($curl_handle,CURLOPT_URL,$url."?".$arg_string);
curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,true);
if($output=curl_exec($curl_handle)){
$return=json_decode($output);
if(!($token=$return->token)){
// Send an error message on authentication
echo"<pre>",print_r($return),"</pre>";
return;
}
}
// Determine if the $data array is too large to xfer
$data_serialized=serialize($data);
if(function_exists('mb_strlen')){
$size=mb_strlen($data_serialized,'8bit');
}else{
$size=strlen($data_serialized);
}
if($size22000000){
$message='Size of selected application(s) is too large to transfer';
returnArray("message"=>$message,"data"=>$data,"alert_type"=>$alert);
}
$encoded_data=json_encode($data);
$payload=json_encode(array('token'=>$token,'data'=>$encoded_data));
$curl_handle=curl_init();
curl_setopt($curl_handle,CURLOPT_URL,$url);
curl_setopt($curl_handle,CURLOPT_RETURNTRANSFER,true);
curl_setopt($curl_handle,CURLOPT_CONNECTTIMEOUT,60);
curl_setopt($curl_handle,CURLOPT_TIMEOUT,60);
curl_setopt($curl_handle,CURLOPT_POST,1);
curl_setopt($curl_handle,CURLOPT_POSTFIELDS,$payload);
curl_setopt($curl_handle,CURLOPT_HTTPHEADER,array(
"Content-Type: application/json",
"Content-Length: ".strlen($payload)
));
// Code to Display Successful and Unsuccessful Transfers
$output=curl_exec($curl_handle);
curl_close($curl_handle);
$results=json_decode($output);
$message="";
$alert="success";
foreach($resultsas$index=>$result){
$message.="Export ".$result->result ." for Application ID:<strong>".
get_object_vars($result->data)['api_application_id']."</strong<br/>\n";
if($result->result =="Error"){
$alert="error";
foreach($result->error_messages as$key=>$msg){
$message.="<li<strong>[$key]</strong> $msg</li>";
}
}
}
if($alert=="error"){
$message.="Please contact company IT administrator for assistance.\n";
}
returnArray("message"=>$message,"data"=>$data,"alert_type"=>$alert);
}
Display of Sample Transfer Array
Array ( [0] => Array (
[user_email] =>
[aggregator_email] =>
[facilities_name] => Some Facility
[property_owner] => Sam Jones
[property_name] =>
[address1] => 3 Main Street
[address2] =>
[city] => Middletown
[state] => DE
[zip] => 19709
[email] =>
[eia_plant_name] =>
[interconnecting_utility] => Other
[other_utility_name] => Delmarva Power
[facility_leased] => Not Leased
[customer_sited] => yes
[energize_date] => 2016-08-20
[online_date] => 2016-09-23
[RTO] => PJM
[GATS_NON] =>
[first_state] => no
[other_states] => DE
[pv_system_type] => Utility Interconnected
[pv_installation_location] => Rooftop
[pv_tracking_axis] => 0
[pv_total_array_output] => 5000
[pv_multiple_tilt] => 1
[pv_number_of_modules] => 20
[pv_power_rating] => 250
[pv_derate] => 0.14
[pv_system_tilt] => 34
[pv_system_azimuth] => 196
[pv_number_of_modules2] =>
[pv_power_rating2] =>
[pv_derate2] =>
[pv_system_tilt_2] =>
[pv_system_azimuth_2] =>
[pv_number_of_modules3] =>
[pv_power_rating3] =>
[pv_derate3] =>
[pv_system_tilt_3] =>
[pv_system_azimuth_3] =>
[pv_number_of_modules4] =>
[pv_power_rating4] =>
[pv_derate4] =>
[pv_system_tilt_4] =>
[pv_system_azimuth_4] =>
[pv_number_of_modules5] =>
[pv_power_rating5] =>
[pv_derate5] =>
[pv_system_tilt_5] =>
[pv_system_azimuth_5] =>
[owner_name] => Sam Jones
[owner_company_name] =>
[owner_address1] => 3 Main Street
[owner_address2] =>
[owner_city] => Middletown
[owner_state] => DE
[owner_zip] => 19709
[owner_phone] => 302-266-7666
[owner_email] =>
[pv_meter_reading] => 4367
[api_application_id] => 9234
[attest_name] => Sam Jones
[doc_panels_file_ext] => pdf
[doc_panels_file] => (contains base64 encoded file contents of the System Photo)
[doc_meter_file_ext] => JPG
[doc_meter_file] => (contains base64 encoded file contents of the Meter Photo)
[doc_schedulea_file_ext] => pdf
[doc_schedulea_file] => (contains base64 encoded file contents of the Schedule A)
[doc_roa_file_ext] =>
[doc_roa_file] => (contains base64 encoded file contents of the ROA)
[doc_interconnection_file_ext] => pdf
[doc_interconnection_file] => (contains base64 encoded file contents of Interconnect Approval)
[doc_multiplephoto_file_ext] => JPG
[doc_multiplephoto_file] => (contains base64 encoded file contents of Multiple Photo)
[doc_optionalupload_file_ext] =>
[doc_optionalupload_file] => (contains base64 encoded file contents of Optional Upload)
) )
Sample Success/Error Messages
The API will return a JSON encoded string that you can decode using json_decode() to create an array (See the end of Sample PHP Code) which will contain both the successful transfers and the unsuccessful transfers and error messages, along with your supplied Application ID (‘api_application_id’.) Below is an example of the output from the Sample PHP Code:
Reviewing Transfer Status of Applications
You will receive information back from the API indicating whether the transfer of applications were successful or not successful. If not successful, specific error messages will also be sent back.
If at some later date, you would like to view all successful transfers, as well as unsuccessful attempts along with the corresponding errors, you can do that through the PennAEPS website. After logging into the PennAEPS, you will see your Aggregator Dashboard. Under option #5 – “Upload New Applications”, click “View Uploaded Applications”:
After you select “View Uploaded Applications”, you will be taken to a page that displays successful uploads and upload errors:
Copyright©2018InClime SolutionsPage 1