michael-simons/pv
1
0
Fork
You've already forked pv
0
Some scripts to work with PV measurements and tooling to record measurements. https://simons.ac/pv/
  • Jupyter Notebook 45.5%
  • SQL 27.8%
  • Shell 16%
  • Java 9.9%
  • JavaScript 0.6%
  • Other 0.2%
2026年07月05日 08:45:37 +02:00
attic Do some cleanup. 2024年06月13日 14:26:15 +02:00
bin Store local weather (temperature) data. 2026年06月24日 10:21:44 +02:00
docs docs: Cleanup readme. 2023年06月01日 12:04:32 +02:00
etc feat: Add a script to invoke the importer regularly. 2025年05月02日 20:48:47 +02:00
media feat: Show amortization, internal consumption and more. 2023年05月31日 14:02:15 +02:00
notebooks Polish wording, add 5 hottest days. 2026年07月05日 08:45:37 +02:00
schema Add temperature chart, remove rendered file. 2026年07月04日 12:36:19 +02:00
utils Add scripts for creating AppCDS archives and AOT Caches. 2026年06月24日 18:26:47 +02:00
.gitattributes Add gitattributes, making SQL visible. 2023年08月27日 23:20:42 +02:00
.gitignore refactor: Use venv, update to DuckDB 1.1.0 proper, and also do several months of Python libs update. 2024年09月29日 22:20:41 +02:00
LICENSE.txt Add logger, sql scripts and readme. 2023年05月09日 21:24:50 +02:00
README.md Clean up project structure. 2026年06月23日 23:30:57 +02:00

pv

⚠️ Programs and scripts in this repository are not meant to be used and may damage your equipment (Of course I use them myself but you never know with expensive equiptment).

Requirements

For the power logger

The logger is based on the Energy systems reading toolkit. Thanks a ton for your work, Niels Basjes.

Build the power logger with

mvn -f utils/logger/pom.xml clean package

For the database

DuckDB >= 1.0.0.

The schema is split into base tables, shared views and eventually, the API, consisting of several views. It can be applied as follows:

./bin/create_or_update_database.sh pv.db

Measurements are stored per quarterly hour, as local date times (local timezone is assumed). For dealing with specifics to your area, i.e. changes during summer / winter time observations, scripts needs adjustment. All views - think of them as public API to this database - start with an v_.

For the Jupyter notebook

I have added a requirements.txt usable with pip like this:

pip install -r notebooks/requirements.txt

Usage

Logger

Run the power logger with:

./logger/target/assembly/bin/log-power-output

Again, this might damage your inverter, burn down the house and what not. Use at your own risk. The logger puts out 1 minute measurements in watt (W) by default which can be imported after creating a database file as described above like this:

more logger.csv | duckdb pv.db -c ".read attic/import_logger.sql"

Jupyter Notebook

Run the notebook with:

jupyter notebook notebooks/Photovoltaik\ \|\ Familie\ Simons,\ Aachen.ipynb

Produce HTML without input boxes and code:

jupyter nbconvert --execute --to html --output index.html --no-input notebooks/Photovoltaik\ \|\ Familie\ Simons,\ Aachen.ipynb

Clear existing output with:

jupyter nbconvert --ClearOutputPreprocessor.enabled=True --inplace notebooks/Photovoltaik\ \|\ Familie\ Simons,\ Aachen.ipynb

I have a rendered version with my current dataset at simons.ac/pv.

Database

Examples

You can get a list of all views to explorer directly from the information schema like this:

duckdb --readonly pv.db "SELECT table_name FROM information_schema.tables WHERE table_type = 'VIEW' ORDER BY table_name ASC"

Their titles should hopefully be self-explanatory, and I only want to show two highlights here. The bar function and the pivot support. The following adds a bit to the view named v_average_production_per_month and produces a quick chart in the terminal, showing the average energy produced per hour:

duckdb --readonly notebooks/pv.db <<-SQL
WITH max_kWh AS (SELECT max(production) AS value FROM v_average_production_per_hour)
SELECT hour AS Hour, bar(production, 0, max_kWh.value) AS 'Average energy produced (kWh)'
FROM v_average_production_per_hour, max_kWH
ORDER BY hour ASC;
SQL

Should look something like this, which I totally love:

stats_avg_per_month_example

Of course this is also possible per month:

duckdb --readonly notebooks/pv.db <<-SQL
WITH max_kWH AS (SELECT max(production) AS value FROM v_average_production_per_month)
SELECT month AS Month, 
 bar(production, 0, max_kWH.value) AS 'Average energy produced (kWh)'
FROM v_average_production_per_month, max_kWH
ORDER BY month ASC;
SQL

Then there is the PIVOT statement being used in v_average_production_per_month_and_hour view to compute the average per hour and month. Originally I displayed the month names as headers, but that is not that useful as an API for the database when you want todo the translation later:

duckdb --readonly notebooks/pv.db "SELECT * FROM v_average_production_per_month_and_hour"

stats_avg_per_hour_and_month

Creating backups

The whole database can be exported either as CSV files like this

EXPORTDATABASE'target_folder';

Or if you prefer Parquet, use the following:

EXPORTDATABASE'target_folder'(FORMATPARQUET,COMPRESSIONZSTD);