PLCHome / growatt

39 stars 9 forks source link

How to implement #1

Closed pradoeagle closed 3 years ago

pradoeagle commented 3 years ago

Hi I have being trying to use python for an API interface to server.growatt.com to transfer data to pvoutput.org. The data I get from the API using python is very limited. The .js code you have appears to capture a much larger dataset but I don't know how to use it. I am currently using Visual Studio with a small .js file calling growatt.js. I have the user name and password entered correctly but I don't get any data back. Any ideas? Thanks David

PLCHome commented 3 years ago

This has to work:

"use strict"
const growatt = require('growatt')

const user="xxx"
const passwort="xx"
const options={}

async function test() {
  let login = await growatt.login(user,passwort).catch(e => {console.log(e)})
  console.log('login:',login)
  let getAllPlantData = await growatt.getAllPlantData(options).catch(e => {console.log(e)})
  console.log('getAllPlatData:',JSON.stringify(getAllPlantData,null,' '));
  let logout = await growatt.logout().catch(e => {console.log(e)})
  console.log('logout:',logout)
}

test()

I don't know your implementation, but I think you made a beginner's mistake. Node JS is a mutitasking interpreter. If you call the commands without await or after .then then the login has not run before you call logout.

PLCHome commented 3 years ago

I have revised the readme.md

pradoeagle commented 3 years ago

Thanks for the response. I have used your exact code as above. I have user and passwort correct. I have just changed them to XXX and YYY for this message.

app.js is below

"use strict" const growatt = require('growatt')

const user = "XXX" const passwort = "YYY" const options = {}

async function test() { let login = await growatt.login(user, passwort).catch(e => { console.log(e) }) console.log('login:', login) let getAllPlantData = await growatt.getAllPlantData().catch(e => { console.log(e) }) console.log('getAllPlatData:', JSON.stringify(getAllPlantData, null, ' ')); let logout = await growatt.logout().catch(e => { console.log(e) }) console.log('logout:', logout) }

test()

When I run it I get

Verbose logs are written to: C:\Users\david\AppData\Local\Temp\visualstudio-js-debugger.txt The program 'app.js' has exited with code -1 (0xffffffff).

I am obviously doing something wrong.

PLCHome commented 3 years ago

I am obviously doing something wrong.

short: yes

It doesn't seem right for your purposes. There are currently 80 installations in the ioBroker. It works. Maybe you look for a Python implementation.

Is the API complicated? Maybe I can build an ioBroker adapter?

e:\node_test>npm install growatt
npm WARN saveError ENOENT: no such file or directory, open 'e:\node_test\package.json'
npm WARN enoent ENOENT: no such file or directory, open 'e:\node_test\package.json'
npm WARN node_test No description
npm WARN node_test No repository field.
npm WARN node_test No README data
npm WARN node_test No license field.

+ growatt@0.1.1
added 13 packages from 19 contributors and audited 21 packages in 2.192s
found 0 vulnerabilities

e:\node_test>type test_from_page.js
"use strict"
const growatt = require('growatt')

const user="<my is here so yours here>"
const passwort="<my is here so yours here>"
const options={}

async function test() {
  let login = await growatt.login(user,passwort).catch(e => {console.log(e)})
  console.log('login:',login)
  let getAllPlantData = await growatt.getAllPlantData(options).catch(e => {console.log(e)})
  console.log('getAllPlatData:',JSON.stringify(getAllPlantData,null,' '));
  let logout = await growatt.logout().catch(e => {console.log(e)})
  console.log('logout:',logout)
}

test()
e:\node_test>node test_from_page.js
login: { result: 1 }
getAllPlatData: {
 "****": {
  "id": "*****",
  "timezone": "1",
  "plantName": "*****",
  "plantData": {
   "valleyPeriodPrice": "0.0",
   "formulaTree": "0.0",
   "flatPeriodPrice": "0.0",
   "co2": "396.9",
   "lng": "6.27977",
   "designCompany": "0",
   "moneyUnit": "euro",
   "peakPeriodPrice": "0.0",
   "formulaCoal": "0.146",
   "city": "****",
   "nominalPower": "****",
   "id": "*****",
   "timezone": "1",
   "tree": "0",
   "coal": "144.5",
   "fixedPowerPrice": "0.0",
   "moneyUnitText": "€",
   "lat": "****",
   "plantImg": "*****",
   "plantName": "****",
   "creatDate": "****",
   "eTotal": "989.9",
   "formulaCo2": "0.401",
   "plantType": "0",
   "country": "****",
   "accountName": "****",
   "formulaMoney": "0.26",
   "isShare": "true"
  },
  "weather": {
   "dataStr": "{\"HeWeather6\":[{\"status\":\"no more requests\"}]}",
   "data": {
    "HeWeather6": [
     {
      "status": "no more requests"
     }
    ]
   },
   "radiant": "--"
  },
  "devices": {
   "****": {
    "totalData": {
     "etogridTotal": "0",
     "elocalLoadToday": "3.8",
     "photovoltaicRevenueTotal": "257.4",
     "edischarge1Today": "0.5",
     "gridPowerToday": "3.9",
     "edischarge1Total": "460.1",
     "eselfTotal": "0",
     "elocalLoadTotal": "7325.9",
     "etoGridToday": "0",
     "epvToday": "0",
     "unit": "€",
     "photovoltaicRevenueToday": "0",
     "eselfToday": "0",
     "epvTotal": "989.9",
     "gridPowerTotal": "7326"
    },
    "statusData": {
     "pPv2": "29.6",
     "pdisCharge1": 0,
     "vac1": "232.6",
     "lost": "mix.status.normal",
     "status": "5",
     "upsFac": "0",
     "pPv1": "101.2",
     "SOC": "17",
     "pactogrid": 0,
     "fAc": "50",
     "ppv": 0.13,
     "pLocalLoad": 0.48,
     "priorityChoose": "0",
     "vBat": "48.9",
     "upsVac1": "0",
     "wBatteryType": "1",
     "deviceType": "2",
     "vAc1": "232.6",
     "vPv2": "347.3",
     "chargePower": 0,
     "pactouser": 0.35,
     "vPv1": "346.7",
     "uwSysWorkMode": "5"
    },
    "historyLast": {
     "serialNum": "****",
     "address": 0,
     "calendar": "2021-03-01T07:24:24.000Z",
     "withTime": false,
     "status": 5,
     "isAgain": false,
     "lost": true,
     "ppv": 130.8,
     "vpv1": 346.7,
     "ppv1": 101.2,
     "vpv2": 347.3,
     "ppv2": 29.6,
     "pac": 178.6,
     "fac": 50,
     "vac1": 232.6,
     "pac1": 175.3,
     "eacToday": 0.7,
     "eacTotal": 1111.8,
     "timeTotal": 17953473,
     "epv1Today": 0,
     "epv1Total": 733.2,
     "epv2Today": 0,
     "epv2Total": 256.7,
     "epvTotal": 989.9000000000001,
     "faultCode": 0,
     "faultBitCode": 0,
     "warnCode": 0,
     "errorCode": 0,
     "priorityChoose": 0,
     "batteryType": 1,
     "uwSysWorkMode": 5,
     "sysFaultWord": 0,
     "sysFaultWord1": 0,
     "sysFaultWord2": 0,
     "sysFaultWord3": 0,
     "sysFaultWord4": 0,
     "sysFaultWord5": 0,
     "sysFaultWord6": 0,
     "sysFaultWord7": 2048,
     "pdischarge1": 0,
     "pcharge1": 0,
     "vbat": 48.9,
     "soc": 17,
     "pacToUserR": 350,
     "pacToUserTotal": 350,
     "pacToGridR": 0,
     "pacToGridTotal": 0,
     "plocalLoadR": 460,
     "plocalLoadTotal": 460,
     "batteryTemperature": 2,
     "etoUserToday": 3.5,
     "etoUserTotal": 3541.2,
     "etoGridToday": 0,
     "etogridTotal": 24.6,
     "edischarge1Today": 0.5,
     "edischarge1Total": 460.1,
     "echarge1Today": 0.3,
     "echarge1Total": 321.5,
     "elocalLoadToday": 3.8,
     "elocalLoadTotal": 7325.9,
     "upsFac": 0,
     "upsVac1": 0,
     "upsPac1": 0,
     "upsLoadpercent": 0,
     "upsPF": 1000,
     "bmsStatusOld": 0,
     "bmsStatus": 97,
     "bmsErrorOld": 0,
     "bmsError": 0,
     "bmsSOC": 17,
     "bmsBatteryVolt": 48.92,
     "bmsBatteryCurr": 1.1,
     "bmsBatteryTemp": 2,
     "bmsMaxCurr": 75,
     "bmsMaxDischgCurr": 75,
     "bmsGaugeRM": 0,
     "bmsGaugeFCC": 0,
     "bmsFW": 0,
     "bmsDeltaVolt": 0,
     "bmsCycleCnt": 0,
     "bmsSOH": 100,
     "bmsConstantVolt": 53.2,
     "bmsWarnInfoOld": 0,
     "bmsWarnInfo": 0,
     "bmsMCUVersion": 0,
     "bmsInfo": 22864,
     "bmsPackInfo": 22864,
     "bmsUsingCap": 0,
     "bmsCell1Volt": 0,
     "bmsCell2Volt": 0,
     "bmsCell3Volt": 0.001,
     "bmsCell4Volt": 0,
     "bmsCell5Volt": 0,
     "bmsCell6Volt": 0,
     "bmsCell7Volt": 0,
     "bmsCell8Volt": 0,
     "bmsCell9Volt": 0,
     "bmsCell10Volt": 0,
     "bmsCell11Volt": 0,
     "bmsCell12Volt": 0,
     "bmsCell13Volt": 0,
     "bmsCell14Volt": 0,
     "bmsCell15Volt": 0,
     "bmsCell16Volt": 0,
     "acChargeEnergyToday": 0.800000011920929,
     "acChargeEnergyTotal": 272.3999938964844,
     "acChargePower": 0,
     "vBus1": 368,
     "vBus2": 279,
     "temp1": 30,
     "temp2": 28,
     "temp3": 29,
     "vBatDsp": 49.3,
     "sysEn": 16544,
     "vac2": 0,
     "pac2": 0,
     "vac3": 0,
     "pac3": 0,
     "epsVac2": 0,
     "epsVac3": 0,
     "upsPac2": 0,
     "upsPac3": 0,
     "bmsProtection": 0,
     "bmsErrorExpansion": 0,
     "maxSingleCellVoltNo": 0,
     "minSingleCellVoltNo": 0,
     "maxSingleCellTemNo": 0,
     "minSingleCellTemNo": 0,
     "moduleQty": 0,
     "moduleSeriesQty": 0,
     "chargeForbiddenMark": 0,
     "dischargeForbiddenMark": 0,
     "softwareMajorVersion": 0,
     "softwareMinorVersion": 0,
     "softwareDevelopMajorVersion": 0,
     "softwareDevelopMinorVersion": 0,
     "chargeCutoffVolt": 0,
     "dischargeCutoffVolt": 0,
     "maxSingleCellVolt": 0,
     "minSingleCellVolt": 0,
     "maxSingleCellTem": 0,
     "minSingleCellTem": 0,
     "iac1": 0,
     "iac2": 0,
     "iac3": 0,
     "capacityADD": 0,
     "backupWarning": 0,
     "sgipCyclCnt": 0,
     "uwBatCycleCntPre": 0,
     "sgipStartCyclCnt": 0,
     "dsgipStartDateTime": "null",
     "batErrorUnion": 0,
     "esystemtoday": -0.10000000149011612,
     "esystemtotal": -0.10000000149011612,
     "eselftoday": -0.10000000149011612,
     "eselftotal": -0.10000000149011612,
     "psystem": -0.10000000149011612,
     "pself": -0.10000000149011612,
     "epvtoday": 0,
     "uwMaxCellVol": -0.0010000000474974513,
     "uwMinCellVol": -0.0010000000474974513,
     "bModuleNum": -1,
     "bTotalCellNum": -1,
     "uwMaxVoltCellNo": -1,
     "uwMinVoltCellNo": -1,
     "uwMaxTemprCell": -0.10000000149011612,
     "uwMinTemprCell": -0.10000000149011612,
     "uwMaxTemprCellNo": -1,
     "uwMinTemprCellNo": -1,
     "protectPackId": -1,
     "maxSOC": -1,
     "minSOC": -1,
     "bmsError2": -1,
     "bmsError3": -1,
     "bmsWarnInfo2": -1,
     "bmsHighestSoftVersion": -1,
     "bmsHardwareVersion": -1,
     "bmsRequestType": -1,
     "accDischargePackSn": -1,
     "accdischargePower": -0.1,
     "accChargePackSn": -1,
     "accChargePower": -0.1,
     "firstBattFaultSn": -1,
     "secondBattFaultSn": -1,
     "thirdBattFaultSn": -1,
     "fourthBattFaultSn": -1,
     "battHistoryFaultCode1": -1,
     "battHistoryFaultCode2": -1,
     "battHistoryFaultCode3": -1,
     "battHistoryFaultCode4": -1,
     "battHistoryFaultCode5": -1,
     "battHistoryFaultCode6": -1,
     "battHistoryFaultCode7": -1,
     "battHistoryFaultCode8": -1,
     "numberOfBattCodes": -1
    },
    "deviceData": {
     "pac": "178.6",
     "sn": "****",
     "plantName": "****",
     "location": "",
     "alias": "****",
     "status": "5",
     "eToday": "0",
     "lastUpdateTime": "2021-03-01 08:24:24",
     "datalogSn": "****",
     "datalogTypeTest": "****",
     "deviceModel": "****",
     "bdcStatus": "0",
     "deviceTypeName": "mix",
     "eTotal": "989.9",
     "eMonth": "0",
     "nominalPower": "*****",
     "accountName": "****",
     "timezone": "1",
     "timeServer": "2021-03-01 15:24:24",
     "plantId": "******",
     "deviceType": "0"
    }
   }
  }
 }
}
logout: { result: 1, msg: 'OK' }

e:\node_test>
pradoeagle commented 3 years ago

Hi I have tried exactly as above. I have copied your file and called it app.js. when I run (node app.js)

I installed everything via npm

PS C:\WINDOWS\system32> npm install growatt npm WARN saveError ENOENT: no such file or directory, open 'C:\WINDOWS\system32\package.json' npm notice created a lockfile as package-lock.json. You should commit this file. npm WARN enoent ENOENT: no such file or directory, open 'C:\WINDOWS\system32\package.json' npm WARN system32 No description npm WARN system32 No repository field. npm WARN system32 No README data npm WARN system32 No license field.

1 package is looking for funding run npm fund for details

found 0 vulnerabilities

I get the follow error when I run app.js

internal/modules/cjs/loader.js:883 throw err; ^

Error: Cannot find module 'growatt' Require stack:

This tells me that the growatt.js file is not found. I have growatt.js saved in the same directory.

I am using MS Studio to edit the app.js file. The username and password fields have been changed.

image

Thanks in advance

PLCHome commented 3 years ago

cd C:\Users\david\GrowattAPI\ npm install growatt node app.js

pradoeagle commented 3 years ago

Thanks. I get data back now. I would be interested in discussing some coding to suit what I am trying to do. Not sure now to contact directly.

PLCHome commented 3 years ago

Yes, fine, you can use gitHub thanx

pradoeagle commented 3 years ago

Hi I am trying to upload 5 minute data to PVOutput. PVOutput is a site for solar data that is very popular in Australia and even across the world that logs generation and usage data for solar systems. My system is https://pvoutput.org/intraday.jsp?id=54920&sid=49926 The API specification for PVOutput is detailed here https://pvoutput.org/help/api_specification.html The Add Status Service is used to upload 5 minute data https://pvoutput.org/service/r2/addstatus.jsp Date (d), Time (t), PV (v2), Usage (v4), Voltage (v6), Battery (v7), Charge (v8), Discharge (v9) From your Growatt API the following data is required Date is today Time is every 5 minutes starting at 0:05 and ending at 24:00 PV is “ppv” Usage is “plocalLoadR” Voltage is “vac1” Battery is “pcharge1” – “pdischarge1” Charge is “pcharge1” Discharge is “pdischarge1”

The following function is required to correct for battery storage supplying the load. At the end of everyday the following is required to be uploaded to PVOutput The Add Output Service is used to upload the daily data https://pvoutput.org/service/r2/addoutput.jsp Date (d), Generation (g), Export (e), Consumption (c) Date is the date for the previous day Generation is Sum of the 5 minute data of “ppv” / 12 Export is Sum of the 5 minute data of IF((“ppv”-“plocalLoadR”-“pdischarge1”)<0,0,IF(“pcharge1”<0,0,”ppv”-“plocalLoadR”-“pdischarge1”)) / 12 Consumption is the Sum of the 5 minute data of “pac1” / 12 This may be easy to implement by just downloading the previous day data rather than storing the data.

I started to develop the code in python on my raspberry pi. The writing of data to the PVOutput is quite easy but I could never get the growatt API to work in python. I need it to run automatically on the raspberry pi. I am currently doing manual end of day download from the growatt site as a CSV file and then using excel to batch the data in the format required by PVOutput then manual upload.

Is this something you would be able to help with setting up?

PLCHome commented 3 years ago
"use strict"
const growatt = require('growatt')
const fs = require('fs');

const user="<my is here so yours here>"
const passwort="<my is here so yours here>"
const options={}

const processFile='./plantData.json'

async function processFileOut() {
  let login = await growatt.login(user,passwort).catch(e => {console.log(e)})
  let getAllPlantData = await growatt.getAllPlantData(options).catch(e => {console.log(e)})
  fs.writeFileSync(processFile, JSON.stringify(allPlantData,null,' '));
  let logout = await growatt.logout().catch(e => {console.log(e)})
}

processFileOut()

Actually I wrote this API to process the data in ioBroker on an RPI. The API is currently used by ioBroker.growatt. I had already thought about writing an ioBroker.pvoutput to send data there. But don't see the reason for me.

https://www.iobroker.net/

sidequest-tomas commented 1 year ago

Hi, nice work, but i can not get any data from my device. I have a hybrid inverter and only get this, any suggestions on how to get statusData and historyLast to work for me? :

"devices": { "MFK0CDVxxx": { "deviceData": { "deviceType": "1", "ptoStatus": "0", "timeServer": "2022-12-02 20:32:10", "accountName": "xxxxxxx", "timezone": "1", "plantId": "146xxxx", "deviceTypeName": "tlx", "nominalPower": "8000", "bdcStatus": "1", "eToday": "4.9", "eMonth": "14.8", "datalogTypeTest": "ShineWiFi-X", "eTotal": "768.0", "pac": "459.5", "datalogSn": "XGD5BJxxxx", "alias": "MFK0CDxxxx", "location": "", "deviceModel": "MOD 8000TL3-XH", "sn": "MFK0CDxxxx", "plantName": "xxxxxx", "status": "1", "lastUpdateTime": "2022-12-02 13:32:10" } } } } }

PLCHome commented 1 year ago

switch on debugging with "set DEBUG=growatt:verbose" and post it in the output.

sidequest-tomas commented 1 year ago

ok, then i get a result like this ( identifiers removed with xxxx):

login: { result: 1 } getAllPlantData: { "14699xx": { "timezone": "1", "id": "14699xx", "plantName": "xxxx", "plantData": { "country": "Sweden", "formulaCo2": "0.4", "accountName": "xxxx", "city": "Sundsvall", "timezone": "1", "co2": "321.4", "creatDate": "2022-09-12", "formulaCoal": "0.4", "designCompany": "0", "fixedPowerPrice": "1.2", "id": "14699xx", "lat": "62.39129", "valleyPeriodPrice": "1.0", "lng": "17.3063", "locationImg": "null", "tree": "44", "peakPeriodPrice": "1.3", "plantType": "0", "nominalPower": "10700", "formulaMoney": "0.0", "formulaTree": "0.0", "flatPeriodPrice": "1.1", "eTotal": "803.4", "plantImg": "1469927_1images1664003118913.jpg", "isShare": "false", "coal": "321.4", "moneyUnit": "sek", "plantName": "xxxx", "moneyUnitText": "Kr" }, "weather": { "city": "Sundsvall", "Week": "Monday", "dataStr": "{\"HeWeather6\":[{\"now\":{\"hum\":\"90\",\"vis\":\"16\",\"pres\":\"1028\",\"pcpn\":\"0.0\",\"fl\":\"-14\",\"wind_sc\":\"2\",\"wind_dir\":\"NW\",\"wind_spd\":\"7\",\"cloud\":\"80\",\"wind_deg\":\"338\",\"tmp\":\"-10\",\"cond_txt\":\"Cloudy\",\"cond_code\":\"101\"},\"update\":{\"loc\":\"2022-12-05 07:55\",\"utc\":\"2022-12-05 06:55\"},\"basic\":{\"ss\":\"14:27\",\"admin_area\":\"Västernorrland County\",\"tz\":\"+1.00\",\"toDay\":\"2022-12-05\",\"location\":\"Sundsvall\",\"lon\":\"17.285994\",\"parent_city\":\"Sundsvall Municipality\",\"cnty\":\"Sweden\",\"lat\":\"62.395508\",\"cid\":\"SE2670781\",\"sr\":\"08:57\"},\"status\":\"ok\"}]}", "data": { "HeWeather6": [ { "now": { "hum": "90", "vis": "16", "pres": "1028", "pcpn": "0.0", "fl": "-14", "wind_sc": "2", "wind_dir": "NW", "wind_spd": "7", "cloud": "80", "wind_deg": "338", "tmp": "-10", "cond_txt": "Cloudy", "cond_code": "101" }, "update": { "loc": "2022-12-05 07:55", "utc": "2022-12-05 06:55" }, "basic": { "ss": "14:27", "admin_area": "Västernorrland County", "tz": "+1.00", "toDay": "2022-12-05", "location": "Sundsvall", "lon": "17.285994", "parent_city": "Sundsvall Municipality", "cnty": "Sweden", "lat": "62.395508", "cid": "SE2670781", "sr": "08:57" }, "status": "ok" } ] }, "radiant": "--" }, "devices": { "MFK0CDV0xx": { "deviceData": { "deviceType": "1", "ptoStatus": "0", "timeServer": "2022-12-05 22:51:40", "accountName": "xxxx", "timezone": "1", "plantId": "14699xx", "deviceTypeName": "tlx", "nominalPower": "8000", "bdcStatus": "1", "eToday": "9.3", "eMonth": "50.2", "datalogTypeTest": "ShineWiFi-X", "eTotal": "803.4", "pac": "71.9", "datalogSn": "XGD5BJHAxx", "alias": "MFK0CDV0xx", "location": "", "deviceModel": "MOD 8000TL3-XH", "sn": "MFK0CDV057", "plantName": "xxxx", "status": "1", "lastUpdateTime": "2022-12-05 15:51:40" } } } } } logout: { result: 1, msg: 'OK' }