Power Plant
- E-total
\
Inverter (three phase)
- Pac
- Iac1
- Uac1
- Freq1
- Iac2
- Uac2
- Freq2
- Iac3
- Uac3
- Freq3
- Temperature
- Iac - sum
- Uac - sum
- Idc - sum
- Udc - sum
- Pdc - sum
- Freq - avg
- Performance ratio
- Estimate Wh
- Estimate rel. - kWh/kWp
- Health
- E-total - kWh
\
String 1
- Pdc - sum
- Idc - sum
- Udc - sum
- Energy today - sum
\
powerbox 1
- Pdc
- Idc
- Udc1 (panel)
- Udc2 (optimizer)
- Energy today
\
...
\
String 2
...
- Wunderground
... template
I am planning to use PVLng, but I am figuring out what the channel hierarchy should be.
I have one three phase inverter with two strings. Additional to that I have powerbox on each panel with (MPPT).
Standard sensors on inverter are: power, current, voltage, frequency, temperature
Besides this standard data inverter API supports (lifetime energy, this year energy, this month energy, today energy, current power, power 15 min resolution).
I receive export energy reading once per month from electricity company, how could I include this data (previous, new kWh - incrementing)?
So I can calculate internal consumption based on difference between inverter and reading energy.
Is there a resettable meter? for example: daily produced energy.
How do you get Mode and Error states?
Here is my current idea of channels hierarchy.
...
Also I would appreciate if you could share your hierarchy and charts definitions.
{
lastUpdateTime: "2014-09-07 11:41:11",
lifeTimeData: {
energy: 12300,
revenue: 100
},
lastYearData: {
energy: 1230
},
lastMonthData: {
energy: 530
},
lastDayData: {
energy: 312
},
currentPower: {
power: 3000
}
}
{
timeUnit: "DAY",
unit: "Wh",
values: [{
date: "2012-12-01 00:00:00",
value: null
}, {
date: "2012-12-02 00:00:00",
value: null
}...]
}
{
power: {
timeUnit: "QUARTER_OF_AN_HOUR",
unit: "W",
values: [{
date: "2012-12-02 00:00:00",
value: null
}, {
date: "2012-12-02 00:15:00",
value: null
}, {
date: "2012-12-02 00:30:00",
value: null
}...]
}
}
{
count: 1222,
telemetries: [{
date: "2014-09-01 05:01:15",
totalActivePower: 0,
dcVoltage: 12,
temperature: 20.2801,
L1Data: {
acCurrent: 0,
acVoltage: 241,
acFrequency: 50
},
L2Data: {
acCurrent: 0,
acVoltage: 237,
acFrequency: 49.99
},
L3Data: {
acCurrent: 0,
acVoltage: 242,
acFrequency: 50
}
}]
}
I have SolarEdge inverter and power optimisers. API docs are accessible here http://www.solaredge.com/files/pdfs/se_monitoring_api.pdf
In general these are data I am interested in API:
1.Current overview
2. Daily energy:
3. 15 min resolution power-plant power
4.Inverter telemetries (for specified time frame) at 5 min resolution.
These is some data accessible through API, but monitoring portal also supports some additional data. For examplePowerbox telemetries (every measurement recorded), data includes (time (per minute), Pdc, Idc, Udc1 (panel), Udc2 (optimizer), energy (from previous measurement)).So in nutshell additional to data available from API, these are raw sensors/meters available:Inverter
- Pac
- Iac1
- Uac1
- Freq1
- Iac2
- Uac2
- Freq2
- Iac3
- Uac3
- Freq3
- Temperature
power optimizer
- Pdc
- Idc
- Udc1 (panel)
- Udc2 (optimizer)
- Energy today
I have over 50 power optimisers, 2 strings & 1 inverter. That's roughly 280 sensors/meters.
Without any calculated channels.
I don't have inverter consumption data.
I only have difference between inverter energy and electricity company energy meter (available for previous month). I have this data from start, when meter was installed.
If you see anything I have missed, please let me know.
Thank you for all you effort for building PVLng & help. I would like to make a small donation so please let me know your Paypal account.
I have over 50 power optimisers, 2 strings & 1 inverter. That's roughly 280 sensors/meters.Ok, lest put it together:- Inverter (generic group)- ... (13 channels from above)- String 1 (generic group)- Whats about RAW string specific data, any?
- Optimizer 1- ... 5 channels from above...- Optimizer n- String 2 (generic group)...Without any calculated channels.Next question, do you need an channel from all optimizers summarized on a higher level (string), e.g. Pdc?!
Then, below string we will have also- String
- ∑ Pdc (Accumulator)- Pdc (optimizer 1)...- Pdc (optimizer n)I don't have inverter consumption data.No, I have consumption also not from the inverter, one house consumption comes from electricity meter via S0... and the other one via D0 (IEC 62056-21).
I only have difference between inverter energy and electricity company energy meter (available for previous month). I have this data from start, when meter was installed.Fine, lifetime data are ok.Problem with a value "only" each (last day of?) month will be, that all charts using this meter channel with aggregation period lower 1 month are not so good...
If you see anything I have missed, please let me know.I'll build some templates and test the logic in the demo installation, give me a day ;-) ...Thank you for all you effort for building PVLng & help. I would like to make a small donation so please let me know your Paypal account.Wow, sounds good, thank you very much! Link is now here: http://pvlng.com/Main_Page#Contribute :-)Knut
Optimzer dataWith which API call can you fetch the optimizer data?
What is the exact JSON return?
Knut
With which API call can you fetch the optimizer data?
There is no API call for optimizer data. I can download multiple CSV files, where rows are time, and columns are optimizer's data (power or panel voltage or optimizer voltage or current or energy).
What is the exact JSON return?csv can be transformed to any format that would best fit import.
I have attached those CSV example files (numbers are not real).NOTEs:- energy is calculated every full hour (for previous hours)- csv has in general rows for every minute.
Inverter
==========
E-Total /site/{siteId}/overview overview->lifeTimeData->energy
Pac /site/{siteId}/overview overview->currentPower
Pdc /equipment/{siteId}/{serialNumber}/data data->telemetries->totalActivePower
Idc /equipment/{siteId}/{serialNumber}/data data->telemetries->dcVoltage
Iac1 /equipment/{siteId}/{serialNumber}/data data->telemetries->L1Data->acCurrent
Iac2 /equipment/{siteId}/{serialNumber}/data data->telemetries->L2Data->acCurrent
Iac3 /equipment/{siteId}/{serialNumber}/data data->telemetries->L3Data->acCurrent
Uac1 /equipment/{siteId}/{serialNumber}/data data->telemetries->L1Data->acVoltage
Uac2 /equipment/{siteId}/{serialNumber}/data data->telemetries->L2Data->acVoltage
Uac3 /equipment/{siteId}/{serialNumber}/data data->telemetries->L3Data->acVoltage
Freq1 /equipment/{siteId}/{serialNumber}/data data->telemetries->L1Data->acFrequency
Freq2 /equipment/{siteId}/{serialNumber}/data data->telemetries->L2Data->acFrequency
Freq3 /equipment/{siteId}/{serialNumber}/data data->telemetries->L3Data->acFrequency
Temperature /equipment/{siteId}/{serialNumber}/data data->telemetries->temperature
Powerbox (same as optimizer???)
==========
Pdc ID in file?
Idc ID in file?
Udc1 (panel) ID in file?
Udc2 (optimizer) ID in file?
Energy today ID in file?
Optimizer
===========
???
Hi,With which API call can you fetch the optimizer data?There is no API call for optimizer data. I can download multiple CSV files, where rows are time, and columns are optimizer's data (power or panel voltage or optimizer voltage or current or energy).Ok, then we need a kind of "CSV-Importer" model like then JSON based one.
What is the exact JSON return?csv can be transformed to any format that would best fit import.Not really necessary, the model will handle this.
I have attached those CSV example files (numbers are not real).NOTEs:- energy is calculated every full hour (for previous hours)- csv has in general rows for every minute.What does"P1.0.1 I (A)","P1.0.2 I (A)","P1.0.1 V (V)","P1.0.2 V (V)","OP1.0.1 V (V)","OP1.0.2 V (V)"resp."P1.0.1 E (Wh)","P1.0.2 E (Wh)","P1.0.1 P (W)","P1.0.2 P (W)"really mean? Something like P<Optimizer>.0.<String> ?
(O?)P<Inverter>.<String>.<Optimizer> (I|V|U) (unit)
Have all of these files such "holes", it looks a bit like randomized data :-)
Here the channels and their sources as I understood so far:
Inverter
==========
E-Total /site/{siteId}/overview.json overview->lifeTimeData->energyPac /site/{siteId}/overview.json overview->currentPower->power
Pdc /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->totalActivePower
Udc /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->dcVoltage
Iac1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L1Data->acCurrentIac2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L2Data->acCurrentIac3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L3Data->acCurrent
Uac1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L1Data->acVoltageUac2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L2Data->acVoltageUac3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L3Data->acVoltage
Freq1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L1Data->acFrequencyFreq2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L2Data->acFrequencyFreq3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->L3Data->acFrequency
Temperature /equipment/{siteId}/{serialNumber}/data.json data->telemetries[x]->temperature
Optimizer
==========
Pdc P1.0.1 P (W)
Idc P1.0.1 I (A)
Udc1 (panel) P1.0.1 V (V)
Udc2 (optimizer) OP1.0.1 V (V)
Energy last hour P1.0.1 E (Wh)
Can you please review, I would take this for the templates...KnutBTW, thanks for donation
Inverter
==========
E-Total /site/{siteId}/overview.json overview->lifeTimeData->energy
Pac /site/{siteId}/overview.json overview->currentPower->power
Pdc /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->totalActivePower
Udc /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->dcVoltage
Iac1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L1Data->acCurrent
Iac2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L2Data->acCurrent
Iac3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L3Data->acCurrent
Uac1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L1Data->acVoltage
Uac2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L2Data->acVoltage
Uac3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L3Data->acVoltage
Freq1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L1Data->acFrequency
Freq2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L2Data->acFrequency
Freq3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L3Data->acFrequency
Temperature /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->temperature
Optimizer
===========
Pdc P1.0.1 P (W)
Idc P1.0.1 I (A)
Udc1 (panel) P1.0.1 V (V)
Udc2 (optimizer) OP1.0.1 V (V)
Energy last hour P1.0.1 E (Wh)
"P1.0.1 I (A)","P1.0.2 I (A)","P1.0.1 V (V)","P1.0.2 V (V)","OP1.0.1 V (V)","OP1.0.2 V (V)"resp."P1.0.1 E (Wh)","P1.0.2 E (Wh)","P1.0.1 P (W)","P1.0.2 P (W)"
P = panel
OP = optimizer
(O?)P<Inverter>.<String>.<Optimizer> (I|V|U) (unit)
I have updated structure. current power is an object. telemetries is an array of data/time points.
data->telemetries[]->totalActivePower||data->telemetries[]->date
I have sent you an email (to pv at kk de) with full responses.
So, I receive:from grid operator (via email - so it could be automated) readings for two meters:1. meter - total produced energy by plant (kWh) (two readings, VT, MT - tariffs)2. meter - total energy sent to electrical grid (kWh) (same)from electricity company (PX3 scheme)3. meter - total energy received from electrical grid (kWH) (VT, MT tariffs) (mostly at night)so basically this are 6 values per month.
Nevertheless, for later live loading I suggest a cron job each 5 min and an API request with startTime=<now - 5min>This should respond the "latest one" metrics only (data->count = 1)...
For the Optimizers we have to decide
- Split the CSV before upload into value and its timestamp
- Upload the whole CSV
Disadvantage of 2. is the definition, how the model should find the data, when it should be universal as possible.
Have the CSV all the same structure with header line?!
I have sent you an email (to pv at kk de) with full responses.Got it, will test with that.So, I receive:from grid operator (via email - so it could be automated) readings for two meters:1. meter - total produced energy by plant (kWh) (two readings, VT, MT - tariffs)2. meter - total energy sent to electrical grid (kWh) (same)from electricity company (PX3 scheme)3. meter - total energy received from electrical grid (kWH) (VT, MT tariffs) (mostly at night)so basically this are 6 values per month.Ok, this could be in simplest case sources for batch update.Next I'll make an extra installation which we can use for test.Knut
Definition for such a (sub) channel then must be:
data->telemetries[]->totalActivePower||data->telemetries[]->date
Part before double pipe is "location" of measuring value in JSON structure, the other part for the location of timestamp to be used.(Without timestamp, the server timestamp would be used for all arrays!)
I was thinking that JSON model should accept "list" property (in this example: data->telemetries), which is expected to be array. and then all sub-channels should be relative from list. (example: totalActivePower, L1Data->acCurrent). Similar for time. sub channel would have value of "date". but if date is outside of list it should be possible to absolutely addressed (from root) (for example: "->data->date").
So maybe it's less to type for channel definition, but it's more complicated to understand.
Nevertheless, for later live loading I suggest a cron job each 5 min and an API request with startTime=<now - 5min>This should respond the "latest one" metrics only (data->count = 1)...yeah. but if a request fails I should handle this.Does PVLng detect duplicates (same time, value in one channel)?
For the Optimizers we have to decide
- Split the CSV before upload into value and its timestamp
That is simpler approach and it will work pretty well.
- Upload the whole CSV
Disadvantage of 2. is the definition, how the model should find the data, when it should be universal as possible.Here, before importing, a mapper from column to channel would do the trick (simple php array in config?)But in one CSV I can have 150 columns with just 10 rows.Have the CSV all the same structure with header line?!yes, first row cells are always (O?)P<Inverter>.<String>.<Optimizer> (I|V|U) (unit)For exampleA1 is always TimeB1 is P1.0.1 E (Wh)A2 is date time (local timezone - CEST): 06/30/2014 17:01B2 is value: 15.4124...
Hi,
Definition for such a (sub) channel then must be:
data->telemetries[]->totalActivePower||data->telemetries[]->date
Part before double pipe is "location" of measuring value in JSON structure, the other part for the location of timestamp to be used.(Without timestamp, the server timestamp would be used for all arrays!)
I was thinking that JSON model should accept "list" property (in this example: data->telemetries), which is expected to be array. and then all sub-channels should be relative from list. (example: totalActivePower, L1Data->acCurrent). Similar for time. sub channel would have value of "date". but if date is outside of list it should be possible to absolutely addressed (from root) (for example: "->data->date").
Sounds more difficult...
So maybe it's less to type for channel definition, but it's more complicated to understand.
That's the point: You have to type it only once (or never when you use a template :-)I would prefer the more "general" logic, this makes integration of new sources easier.
Nevertheless, for later live loading I suggest a cron job each 5 min and an API request with startTime=<now - 5min>This should respond the "latest one" metrics only (data->count = 1)...yeah. but if a request fails I should handle this.Does PVLng detect duplicates (same time, value in one channel)?
Yes, by default new reading must have timestamp min. 5 seconds after last reeading. (Entry in database: pvlng_config -> DoubleRead)
For the Optimizers we have to decide
- Split the CSV before upload into value and its timestamp
That is simpler approach and it will work pretty well.
- Upload the whole CSV
Disadvantage of 2. is the definition, how the model should find the data, when it should be universal as possible.Here, before importing, a mapper from column to channel would do the trick (simple php array in config?)But in one CSV I can have 150 columns with just 10 rows.Have the CSV all the same structure with header line?!yes, first row cells are always (O?)P<Inverter>.<String>.<Optimizer> (I|V|U) (unit)For exampleA1 is always TimeB1 is P1.0.1 E (Wh)A2 is date time (local timezone - CEST): 06/30/2014 17:01B2 is value: 15.4124...
Ok, I think the handling of such a "CSV with header line" is much easier in PHP.
But if you define a number of optimizers (with sub channels) and a file contains data for more than 1 optimizer, you must push the file to all optimizers and they will extract the data for their sub channels...
Definition for such a (sub) channel then must be:
data->telemetries[]->totalActivePower||data->telemetries[]->date
Part before double pipe is "location" of measuring value in JSON structure, the other part for the location of timestamp to be used.(Without timestamp, the server timestamp would be used for all arrays!)
Inverter
==========
Frontend name API call JPath in response Channel attribute
E-Total /site/{siteId}/overview.json overview->lifeTimeData->energy lifeTimeData->energy
Pac /site/{siteId}/overview.json overview->currentPower->power currentPower->power
As timestamp for the next channels will be used: data->telemetries[]->date
Pdc /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->totalActivePower totalActivePower
Udc /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->dcVoltage dcVoltage
Iac1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L1Data->acCurrent L1Data->acCurrent
Iac2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L2Data->acCurrent L2Data->acCurrent
Iac3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L3Data->acCurrent L3Data->acCurrent
Uac1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L1Data->acVoltage L1Data->acVoltage
Uac2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L2Data->acVoltage L2Data->acVoltage
Uac3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L3Data->acVoltage L3Data->acVoltage
Freq1 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L1Data->acFrequency L1Data->acFrequency
Freq2 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L2Data->acFrequency L2Data->acFrequency
Freq3 /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->L3Data->acFrequency L3Data->acFrequency
Temperature /equipment/{siteId}/{serialNumber}/data.json data->telemetries[]->temperature temperature
Optimizer
===========
Pdc P1.0.1 P (W)
Idc P1.0.1 I (A)
Udc1 (panel) P1.0.1 V (V)
Udc2 (optimizer) OP1.0.1 V (V)
Energy last hour P1.0.1 E (Wh)
I can split csvs to contain only 1 optimiser each.