I have installed a very nice solar power plant with 600Wp feed-in capacity on my balcony, properly installed and registered, of course. The power plant produces more energy during the day than is required for the base load and in the evening less than is required, so the energy should be stored. A sophisticated control is in the process of being implemented using a RaspberryPi + SQL Server. However, actually the´re data from the inverter still missing.
There are some code snippets on the Internet, from which I have assembled a curl query using PHP. My code consists of 3 query blocks, all of which are answered by the target server. The relevant detailed information can be found in the 3rd building block, but unfortunately all the variables show 0 here.
error_reporting(E_ALL);
ini_set("display_errors","on");
date_default_timezone_set('Europe/Berlin');
define('time',$_SERVER['REQUEST_TIME']);
// The username or email address of the account.
define('USERNAME', '*******');
// The Password of the account
define('PASSWORD', '*******');
$pw = md5(PASSWORD);
// replace leading 0 by c for Growatt
for ($i = 0; $i < strlen($pw); $i=$i+2){
if ($pw[$i]=='0'){
$pw=substr_replace($pw,'c',$i,1);
}
}
// Where our cookie information will be stored (need to be writable!)
define('COOKIE_FILE','/home/sites/site100009302/web/SmartHome/Hoppe2a/Solar/growatt.cookie');
define('HEADER',array('Content-Type: application/x-www-form-urlencoded;charset=UTF-8'));
// URL of the login form.
define('LOGIN_FORM_URL', 'https://server-api.growatt.com/newTwoLoginAPI.do');
// Login action URL. Sometimes, this is the same URL as the login form.
define('LOGIN_ACTION_URL', 'https://server-api.growatt.com/newTwoLoginAPI.do');
// Start with 1st query block (Login)
$curl = curl_init();
// Set the URL that we want to send our POST request to. In this case, it's the action URL of the login form.
curl_setopt($curl, CURLOPT_URL, LOGIN_ACTION_URL);
// Tell cURL that we want to carry out a POST request.
curl_setopt($curl, CURLOPT_POST, true);
// Set POST-Data.
$postValues = array(
'userName' => USERNAME,
'password' => $pw
);
curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($postValues));
// We don't want any HTTPS errors.
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
// Where our cookie details are saved.
curl_setopt($curl, CURLOPT_COOKIEJAR, COOKIE_FILE);
// This is typically required for authentication, as the session ID is usually saved in the cookie file.
curl_setopt($curl, CURLOPT_HTTPHEADER, HEADER);
curl_setopt($curl, CURLOPT_COOKIEFILE, COOKIE_FILE);
// Tells cURL to return the output once the request has been executed.
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
// Allows us to set the referer header. In this particular case, we are fooling the server into thinking that we were referred by the login form.
curl_setopt($curl, CURLOPT_REFERER, LOGIN_FORM_URL);
curl_setopt ($curl, CURLOPT_SSLVERSION, 1);
// Do we want to follow any redirects?
curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
// Get data from JSON from the server
$responseDecoded_a = json_decode(curl_exec($curl), true);
$plantName = $responseDecoded_a['back']['data'][0]['plantName'];
$plantId = $responseDecoded_a['back']['data'][0]['plantId'];
$Inbetriebnahme = $responseDecoded_a['back']['user']['createDate'];
// Check if retrieval was successful
$http_code_login = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($http_code_login == 200 xor $http_code_login == 302){
echo "Login was successful, Status ".$http_code_login." <br>\n";
}else{
echo "Login was not successful, Status ".$http_code_login.", program is terminated <br>\n";
exit;
}
The server gives the following satisfactory answer to this query (personal data rendered unrecognizable):
Array ( [back] => Array ( [deviceCount] => 1 [data] => Array ( [0] => Array ( [plantName] => Hoppe 2a [plantId] => 1222064 ) ) [isOpenSmartFamily] => 0 [isCheckUserAuth] => 1 [msg] => [isEicUserAddSmartDevice] => 1 [isOpenDeviceList] => 1 [isOpenDeviceParams] => 0 [quality] => 0 [service] => 1 [totalData] => Array ( ) [user] => Array ( [uid] => [dataAcqList] => Array ( ) [type] => 0 [password] => *******[isValiPhone] => 0 [distributorEnable] => 1 [approved] => [phoneNum] => ******* [registerType] => 0 [userDeviceType] => -1 [userIconPath] => [nickName] => [customerCode] => [counrty] => Germany [appType] => c [roleId] => 0 [enabled] => 1 [agentCode] => APBWE [isValiEmail] => 0 [installerEnable] => 1 [email] => ******* [company] => [codeIndex] => 1 [noticeType] => [userLanguage] => gm [inverterGroup] => Array ( ) [lng] => [timeZone] => 8 [kind] => 0 [mailNotice] => 1 [id] => 1494787 [lastLoginIp] => 127.0.0.1 [area] => Europe [isAgent] => 0 [smsNotice] => [token] => [parentUserId] => 0 [isPhoneNumReg] => 0 [createDate] => 2022-05-21 22:50:20 [rightlevel] => 1 [lastLoginTime] => 2022-08-01 19:14:32 [lat] => [serverUrl] => [cpowerToken] => ******* [inverterList] => Array ( ) [vipPoints] => 10 [accountName] => ******* [accountNameOss] => ******* [activeName] => ******* [appAlias] => ******* [isBigCustomer] => 0 ) [success] => 1 [app_code] => 1 [isViewDeviceInfo] => ) )
In the following second block I call up general data on the power plant output. The code used for this is:
$curl = curl_init();
$url = 'http://server-api.growatt.com/newPlantAPI.do?action=getUserCenterEnertyData';
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($curl, CURLOPT_COOKIEFILE, COOKIE_FILE);
curl_setopt($curl, CURLOPT_POSTFIELDS, "language=1" );
curl_setopt($curl, CURLOPT_HTTPHEADER, HEADER);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt ($curl, CURLOPT_SSLVERSION, 1);
$responseDecoded_b = json_decode(curl_exec($curl), true);
// Accept data from JSON from the server, remove unit characters after the values
$nominalPowerStr = str_replace("kWp", "", $responseDecoded_b['nominalPowerStr']);
$Ausgangsleistung = $responseDecoded_b['powerValue'];
$Tagesleistung = str_replace("kWh", "", $responseDecoded_b['todayStr']);
// Check if retrieval was successful
$http_code_PlantAPI = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($http_code_PlantAPI == 200 xor $http_code_PlantAPI == 302){
echo "Retrieval of the power plant data was successful, Status ".$http_code_PlantAPI." <br>\n";
}else{
echo "Retrieval of the power plant data was not successful, Status ".$http_code_PlantAPI.", program is terminated <br>\n";
exit;
}
The server gives the following satisfactory answer to this 2nd query:
Array ( [monthProfitStr] => €0.4 [todayProfitStr] => €0.4 [plantNumber] => 1 [treeValue] => 8.4 [treeStr] => 8 [nominalPowerStr] => 0.6kWp [eventMessBeanList] => Array ( ) [yearValue] => 0.0 [formulaCo2Vlue] => 60.9 [formulaCo2Str] => 60.9kg [todayValue] => 1.1 [totalStr] => 152.3kWh [powerValue] => 608.2 [totalValue] => 152.3 [nominalPowerValue] => 600.0 [powerValueStr] => 0.6kW [monthValue] => 1.1 [todayStr] => 1.1kWh [monthStr] => 1.1kWh [formulaCoalStr] => 60.9kg [alarmValue] => 0 [totalProfitStr] => €48.7 [yearStr] => 0kWh [formulaCoalValue] => 60.9 )
I need some more data like Voltage (V) and Current (A) on the primary and secondary side. This data is made available by the Growatt portal and should almost certainly also be retrievable. Here is a screenshot of the web interface of the manufacturer portal Growatt: Growatt Server Dashboard
So my code for 3rd query is:
$curl = curl_init();
$url = 'http://server-api.growatt.com/newInverterAPI.do?inverterId=FRJ2BGP002&op=getInverterDetailData_two';
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_COOKIEJAR, COOKIE_FILE);
curl_setopt($curl, CURLOPT_COOKIEFILE, COOKIE_FILE);
curl_setopt($curl, CURLOPT_HTTPHEADER, HEADER);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt ($curl, CURLOPT_SSLVERSION, 1);
// Accept data from JSON from the server
$responseDecoded_c = json_decode(curl_exec($curl), true);
// Check if retrieval was successful
$http_code_PlantAPI = curl_getinfo($curl, CURLINFO_HTTP_CODE);
curl_close($curl);
if ($http_code_PlantAPI == 200 xor $http_code_PlantAPI == 302){
echo "Retrieval of the power plant data was successful, Status ".$http_code_PlantAPI." <br>\n";
}else{
echo "Retrieval of the power plant data was not successful, Status ".$http_code_PlantAPI.", program is terminated <br>\n";
exit;
}
There is a server response under status 200 in which all variables are unfortunately displayed with 0. There should actually be data on the power plant here.
Array ( [data] => Array ( [e_today] => 0 [e_total] => 0 [vpv1] => 0 [ipv1] => 0 [ppv1] => 0 [vpv2] => 0 [ipv2] => 0 [ppv2] => 0 [vpv3] => 0 [ipv3] => 0 [ppv3] => 0 [ppv] => 0 [vacr] => 0 [vacs] => 0 [vact] => 0 [iacr] => 0 [iacs] => 0 [iact] => 0 [fac] => 0 [pac] => 0 [pacr] => 0 [pacs] => 0 [pact] => 0 [rac] => 0 [e_rac_today] => 0 [e_rac_total] => 0 [t_total] => 0 [vstring1] => 0 [istring1] => 0 [vstring2] => 0 [istring2] => 0 [vstring3] => 0 [istring3] => 0 [vstring4] => 0 [istring4] => 0 [vstring5] => 0 [istring5] => 0 [vstring6] => 0 [istring6] => 0 [vstring7] => 0 [istring7] => 0 [vstring8] => 0 [istring8] => 0 [strfault] => 0 [strwarning] => 0 [strbreak] => 0 [pidwarning] => 0 ) [parameterName] => Fac(Hz),Pac(W),E_Today(kWh),E_Total(kWh),Vpv1(V),Ipv1(A),Ppv1(W),Vpv2(V),Ipv2(A),Ppv2(W),Vpv3(V),Ipv3(A),Ppv3(W),Ppv(W),VacR(V),VacS(V),VacT(V),IacR(A),IacS(A),IacT(A),PacR(W),PacS(W),PacT(W),Rac(W),E_Rac_Today(W),E_Rac_Total(W),T_Total(H),Vstring1(V),Istring1(A),Vstring2(V),Istring2(A),Vstring3(V),Istring3(A),Vstring4(V),Istring4(A),Vstring5(V),Istring5(A),Vstring6(V),Istring6(A),Vstring7(V),Istring7(A),Vstring8(V),Istring8(A),StrFault,StrWarning,StrBreak,PIDWarning )
I'm not professionally involved in IT or software and I program as a hobby because it's fun to find solutions and get machines running. Maybe you have experience with this problem and a tip for me how I can retrieve the data or what I can do better.
best regards