From 444e5065a473cc1d405a3bfb9040f70cd4d7f539 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Fri, 26 Jul 2024 22:35:30 +0200 Subject: [PATCH 01/23] Implement proper DB migrations using Goose. Upgrade go packages. --- go.mod | 11 ++- go.sum | 55 ++++++++++- main.go | 147 +++++++---------------------- migrations/00001_log.sql | 14 +++ migrations/00002_inverters.sql | 19 ++++ migrations/00003_inverters_ac.sql | 20 ++++ migrations/00004_inverters_dc.sql | 22 +++++ migrations/00005_inverters_inv.sql | 19 ++++ migrations/00006_events.sql | 17 ++++ migrations/00007_events.sql | 26 +++++ migrations/00008_hints.sql | 16 ++++ migrations/fs.go | 6 ++ 12 files changed, 255 insertions(+), 117 deletions(-) create mode 100644 migrations/00001_log.sql create mode 100644 migrations/00002_inverters.sql create mode 100644 migrations/00003_inverters_ac.sql create mode 100644 migrations/00004_inverters_dc.sql create mode 100644 migrations/00005_inverters_inv.sql create mode 100644 migrations/00006_events.sql create mode 100644 migrations/00007_events.sql create mode 100644 migrations/00008_hints.sql create mode 100644 migrations/fs.go diff --git a/go.mod b/go.mod index 07b4ae4..1d86d89 100644 --- a/go.mod +++ b/go.mod @@ -3,8 +3,15 @@ module git.hollander.online/energy/opendtu-logger go 1.22 require ( - github.com/gorilla/websocket v1.5.1 + github.com/gorilla/websocket v1.5.3 github.com/lib/pq v1.10.9 + github.com/pressly/goose/v3 v3.21.1 ) -require golang.org/x/net v0.17.0 // indirect +require ( + github.com/mfridman/interpolate v0.0.2 // indirect + github.com/sethvargo/go-retry v0.2.4 // indirect + go.uber.org/multierr v1.11.0 // indirect + golang.org/x/net v0.27.0 // indirect + golang.org/x/sync v0.7.0 // indirect +) diff --git a/go.sum b/go.sum index 944767b..f93ce7b 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,57 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= +github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= +github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mfridman/interpolate v0.0.2 h1:pnuTK7MQIxxFz1Gr+rjSIx9u7qVjf5VOoM/u6BbAxPY= +github.com/mfridman/interpolate v0.0.2/go.mod h1:p+7uk6oE07mpE/Ik1b8EckO0O4ZXiGAfshKBWLUM9Xg= +github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= +github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= +github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= +github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= +github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= +go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= +golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= +modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= +modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= +modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= +modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= +modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4= +modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= +modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= +modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= +modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= diff --git a/main.go b/main.go index 4ea5cc7..e6fbfa2 100644 --- a/main.go +++ b/main.go @@ -11,6 +11,7 @@ import ( "database/sql" "encoding/json" "fmt" + "io/fs" "log" "log/slog" "net/http" @@ -19,8 +20,10 @@ import ( "time" _ "time/tzdata" + "git.hollander.online/energy/opendtu-logger/migrations" "github.com/gorilla/websocket" _ "github.com/lib/pq" + "github.com/pressly/goose/v3" ) // VUD contains three variables used for most metrics sent by OpenDTU: @@ -212,7 +215,7 @@ func main() { defer db.Close() // Create tables if they don't exist - createTables(db) + migrateDB(db) // Create WebSocket URL from config variable wsURL := "ws://" + config.OpenDTU + "/livedata" @@ -287,122 +290,14 @@ func handleMessage(message []byte, db *sql.DB) { } } -func createTables(db *sql.DB) { - // Execute SQL statements to create tables if they don't exist - // inverter_serial is TEXT as some non-Hoymiles inverters use non-numeric serial numbers. - // An additional advantage is that it makes plotting in Grafana easier. +func migrateDB(db *sql.DB) { // TODO: Foreign keys commented out as TimescaleDB hypertables don't support them. - createTableSQL := ` - CREATE TABLE IF NOT EXISTS opendtu_log ( - timestamp TIMESTAMPTZ UNIQUE DEFAULT CURRENT_TIMESTAMP, - power NUMERIC, - yieldday NUMERIC, - yieldtotal NUMERIC - ); - - CREATE TABLE IF NOT EXISTS opendtu_inverters ( - timestamp TIMESTAMPTZ, - -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), - inverter_serial TEXT, - name TEXT, - producing BOOL, - limit_relative NUMERIC, - limit_absolute NUMERIC - ); - - CREATE TABLE IF NOT EXISTS opendtu_inverters_ac ( - timestamp TIMESTAMPTZ, - -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), - inverter_serial TEXT, - ac_number INT, - power NUMERIC, - voltage NUMERIC, - current NUMERIC, - frequency NUMERIC, - powerfactor NUMERIC, - reactivepower NUMERIC - ); - - CREATE TABLE IF NOT EXISTS opendtu_inverters_dc ( - -- id SERIAL PRIMARY KEY, - timestamp TIMESTAMPTZ, - -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), - inverter_serial TEXT, - dc_number INT, - name TEXT, - power NUMERIC, - voltage NUMERIC, - current NUMERIC, - yieldday NUMERIC, - yieldtotal NUMERIC, - irradiation NUMERIC - ); - - CREATE TABLE IF NOT EXISTS opendtu_inverters_inv ( - -- id SERIAL PRIMARY KEY, - timestamp TIMESTAMPTZ, - -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), - inverter_serial TEXT, - temperature NUMERIC, - power_dc NUMERIC, - yieldday NUMERIC, - yieldtotal NUMERIC, - efficiency NUMERIC - ); - CREATE TABLE IF NOT EXISTS opendtu_events ( - -- id SERIAL PRIMARY KEY, - timestamp TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, - inverter_serial TEXT, - message_id INT, - message TEXT, - start_time INT, - end_time INT - ); + // Perform DB migrations + err := migrateFS(db, migrations.FS, ".") - DO $$ - BEGIN - -- Check if start_timestamp column exists - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name='opendtu_events' - AND column_name='start_timestamp') THEN - -- Add start_timestamp column - ALTER TABLE opendtu_events - ADD COLUMN start_timestamp TIMESTAMPTZ; - END IF; - - -- Check if end_timestamp column exists - IF NOT EXISTS (SELECT 1 FROM information_schema.columns - WHERE table_name='opendtu_events' - AND column_name='end_timestamp') THEN - -- Add end_timestamp column - ALTER TABLE opendtu_events - ADD COLUMN end_timestamp TIMESTAMPTZ; - END IF; - END $$; - - CREATE TABLE IF NOT EXISTS opendtu_hints ( - -- id SERIAL PRIMARY KEY, - timestamp TIMESTAMPTZ, - -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), - time_sync BOOL, - radio_problem BOOL, - default_password BOOL - ); - - CREATE INDEX IF NOT EXISTS opendtu_log_timestamp_idx ON opendtu_log (timestamp); - CREATE INDEX IF NOT EXISTS opendtu_inverters_timestamp_idx ON opendtu_inverters (timestamp); - CREATE INDEX IF NOT EXISTS opendtu_inverters_ac_timestamp_idx ON opendtu_inverters_ac (timestamp); - CREATE INDEX IF NOT EXISTS opendtu_inverters_dc_timestamp_idx ON opendtu_inverters_dc (timestamp); - CREATE INDEX IF NOT EXISTS opendtu_inverters_inv_timestamp_idx ON opendtu_inverters_inv (timestamp); - CREATE INDEX IF NOT EXISTS opendtu_events_timestamp_idx ON opendtu_events (timestamp); - CREATE INDEX IF NOT EXISTS opendtu_hints_timestamp_idx ON opendtu_hints (timestamp); - - ` - - _, err := db.Exec(createTableSQL) if err != nil { - log.Fatal("Error creating tables: ", err) + log.Fatal("Error performing database migrations: ", err) } timescaleEnabled := config.TimescaleDB @@ -502,6 +397,32 @@ func insertLiveData(db *sql.DB, inverter Inverter, total Total, hints Hints) { } +func migrate(db *sql.DB, dir string) error { + err := goose.SetDialect("postgres") + if err != nil { + return fmt.Errorf("migrate: %w", err) + } + err = goose.Up(db, dir) + if err != nil { + return fmt.Errorf("migrate: %w", err) + } + return nil + +} + +func migrateFS(db *sql.DB, migrationFS fs.FS, dir string) error { + // In case the dir is an empty string, they probably meant the current directory and goose wants a period for that. + if dir == "" { + dir = "." + } + goose.SetBaseFS(migrationFS) + defer func() { + // Ensure that we remove the FS on the off chance some other part of our app uses goose for migrations and doesn't want to use our FS. + goose.SetBaseFS(nil) + }() + return migrate(db, dir) +} + func queryEventsEndpoint(inverterSerial string) (*EventsResponse, error) { remoteURL := config.OpenDTU endpoint := fmt.Sprintf("http://"+remoteURL+"/api/eventlog/status?inv=%s", inverterSerial) diff --git a/migrations/00001_log.sql b/migrations/00001_log.sql new file mode 100644 index 0000000..6a9d6b4 --- /dev/null +++ b/migrations/00001_log.sql @@ -0,0 +1,14 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_log ( + timestamp TIMESTAMPTZ UNIQUE DEFAULT CURRENT_TIMESTAMP, + power NUMERIC, + yieldday NUMERIC, + yieldtotal NUMERIC +); + +CREATE INDEX IF NOT EXISTS opendtu_log_timestamp_idx ON opendtu_log (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/00002_inverters.sql b/migrations/00002_inverters.sql new file mode 100644 index 0000000..935eb63 --- /dev/null +++ b/migrations/00002_inverters.sql @@ -0,0 +1,19 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_inverters ( + timestamp TIMESTAMPTZ, + -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), + -- inverter_serial is TEXT as some non-Hoymiles inverters use non-numeric serial numbers. + -- An additional advantage is that it makes plotting in Grafana easier. + inverter_serial TEXT, + name TEXT, + producing BOOL, + limit_relative NUMERIC, + limit_absolute NUMERIC +); + +CREATE INDEX IF NOT EXISTS opendtu_inverters_timestamp_idx ON opendtu_inverters (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/00003_inverters_ac.sql b/migrations/00003_inverters_ac.sql new file mode 100644 index 0000000..cccfb2d --- /dev/null +++ b/migrations/00003_inverters_ac.sql @@ -0,0 +1,20 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_inverters_ac ( + timestamp TIMESTAMPTZ, + -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), + inverter_serial TEXT, + ac_number INT, + power NUMERIC, + voltage NUMERIC, + current NUMERIC, + frequency NUMERIC, + powerfactor NUMERIC, + reactivepower NUMERIC +); + +CREATE INDEX IF NOT EXISTS opendtu_inverters_ac_timestamp_idx ON opendtu_inverters_ac (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/00004_inverters_dc.sql b/migrations/00004_inverters_dc.sql new file mode 100644 index 0000000..c958fef --- /dev/null +++ b/migrations/00004_inverters_dc.sql @@ -0,0 +1,22 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_inverters_dc ( + -- id SERIAL PRIMARY KEY, + timestamp TIMESTAMPTZ, + -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), + inverter_serial TEXT, + dc_number INT, + name TEXT, + power NUMERIC, + voltage NUMERIC, + current NUMERIC, + yieldday NUMERIC, + yieldtotal NUMERIC, + irradiation NUMERIC +); + +CREATE INDEX IF NOT EXISTS opendtu_inverters_dc_timestamp_idx ON opendtu_inverters_dc (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/00005_inverters_inv.sql b/migrations/00005_inverters_inv.sql new file mode 100644 index 0000000..677248f --- /dev/null +++ b/migrations/00005_inverters_inv.sql @@ -0,0 +1,19 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_inverters_inv ( + -- id SERIAL PRIMARY KEY, + timestamp TIMESTAMPTZ, + -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), + inverter_serial TEXT, + temperature NUMERIC, + power_dc NUMERIC, + yieldday NUMERIC, + yieldtotal NUMERIC, + efficiency NUMERIC +); + +CREATE INDEX IF NOT EXISTS opendtu_inverters_inv_timestamp_idx ON opendtu_inverters_inv (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/00006_events.sql b/migrations/00006_events.sql new file mode 100644 index 0000000..4f56cc7 --- /dev/null +++ b/migrations/00006_events.sql @@ -0,0 +1,17 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_events ( + -- id SERIAL PRIMARY KEY, + timestamp TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP, + inverter_serial TEXT, + message_id INT, + message TEXT, + start_time INT, + end_time INT +); + +CREATE INDEX IF NOT EXISTS opendtu_events_timestamp_idx ON opendtu_events (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd \ No newline at end of file diff --git a/migrations/00007_events.sql b/migrations/00007_events.sql new file mode 100644 index 0000000..d7ad456 --- /dev/null +++ b/migrations/00007_events.sql @@ -0,0 +1,26 @@ +-- +goose Up +-- +goose StatementBegin +DO $$ +BEGIN + -- Check if start_timestamp column exists + IF NOT EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='opendtu_events' + AND column_name='start_timestamp') THEN + -- Add start_timestamp column + ALTER TABLE opendtu_events + ADD COLUMN start_timestamp TIMESTAMPTZ; + END IF; + + -- Check if end_timestamp column exists + IF NOT EXISTS (SELECT 1 FROM information_schema.columns + WHERE table_name='opendtu_events' + AND column_name='end_timestamp') THEN + -- Add end_timestamp column + ALTER TABLE opendtu_events + ADD COLUMN end_timestamp TIMESTAMPTZ; + END IF; +END $$; +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/00008_hints.sql b/migrations/00008_hints.sql new file mode 100644 index 0000000..ed5e87b --- /dev/null +++ b/migrations/00008_hints.sql @@ -0,0 +1,16 @@ +-- +goose Up +-- +goose StatementBegin +CREATE TABLE IF NOT EXISTS opendtu_hints ( + -- id SERIAL PRIMARY KEY, + timestamp TIMESTAMPTZ, + -- FOREIGN KEY (timestamp) REFERENCES opendtu_log(timestamp), + time_sync BOOL, + radio_problem BOOL, + default_password BOOL +); + +CREATE INDEX IF NOT EXISTS opendtu_hints_timestamp_idx ON opendtu_hints (timestamp); +-- +goose StatementEnd +-- +goose Down +-- +goose StatementBegin +-- +goose StatementEnd diff --git a/migrations/fs.go b/migrations/fs.go new file mode 100644 index 0000000..91cca1c --- /dev/null +++ b/migrations/fs.go @@ -0,0 +1,6 @@ +package migrations + +import "embed" + +//go:embed *.sql +var FS embed.FS From 9a0fb6ad1c24c5bc5d29a2ce15b5c5dd47dfa5a0 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Fri, 26 Jul 2024 22:36:50 +0200 Subject: [PATCH 02/23] Remove completed DB migration TODO. --- main.go | 1 - 1 file changed, 1 deletion(-) diff --git a/main.go b/main.go index e6fbfa2..1184b82 100644 --- a/main.go +++ b/main.go @@ -4,7 +4,6 @@ // Idea: Make a full admin / config GUI and only configure through this utility. // Idea: Gather settings only on start-up. // TODO: Only update meter readings such as yieldday, yieldtotal on-change. -// TODO: Implement proper DB migrations. package main import ( From a7576cd0c06b5077dac1250bfeb1d912c4f91e67 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Fri, 26 Jul 2024 22:37:29 +0200 Subject: [PATCH 03/23] Add health check TODO. --- main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/main.go b/main.go index 1184b82..8bd6657 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ // Idea: Make a full admin / config GUI and only configure through this utility. // Idea: Gather settings only on start-up. // TODO: Only update meter readings such as yieldday, yieldtotal on-change. +// TODO: Add a health check endpoint, potentially log to it. package main import ( From bf885fb84ce45ddbfabe4d000db64b400b46e394 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Fri, 26 Jul 2024 22:42:31 +0200 Subject: [PATCH 04/23] Change default version in compose examples from main to latest. --- docker/compose.with-database-grafana.yml | 2 +- docker/compose.with-database.yml | 2 +- docker/compose.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/compose.with-database-grafana.yml b/docker/compose.with-database-grafana.yml index b7fa9d4..2a63282 100644 --- a/docker/compose.with-database-grafana.yml +++ b/docker/compose.with-database-grafana.yml @@ -22,7 +22,7 @@ services: retries: 20 opendtu-logger: - image: git.hollander.online/energy/opendtu-logger:main + image: git.hollander.online/energy/opendtu-logger:latest restart: always environment: DB_URL: ${DB_URL} diff --git a/docker/compose.with-database.yml b/docker/compose.with-database.yml index b0a9004..867bbd9 100644 --- a/docker/compose.with-database.yml +++ b/docker/compose.with-database.yml @@ -23,7 +23,7 @@ services: opendtu-logger: restart: always - image: git.hollander.online/energy/opendtu-logger:main + image: git.hollander.online/energy/opendtu-logger:latest environment: DB_URL: ${DB_URL} REMOTE_URL: ${REMOTE_URL} diff --git a/docker/compose.yml b/docker/compose.yml index d25a958..dc0fbe3 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -2,7 +2,7 @@ version: '3.8' services: opendtu-logger: restart: always - image: git.hollander.online/energy/opendtu-logger:main + image: git.hollander.online/energy/opendtu-logger:latest environment: DB_URL: ${DB_URL} REMOTE_URL: ${REMOTE_URL} From 48d0382b0e15e9fbef12ebc54e0f10ea314fd8a1 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Fri, 26 Jul 2024 23:46:19 +0200 Subject: [PATCH 05/23] BREAKING: Migrate REMOTE_URL to OPENDTU_ADDRESS. BREAKING: Migrate opendtu to opendtu_address Add authentication capability for locked-down opendtu's. Updated setup examples with new variables. --- docker/compose.with-database-grafana.yml | 5 +- docker/compose.with-database.yml | 5 +- docker/compose.yml | 5 +- docker/example.with-database.env | 8 +- main.go | 102 +++++++++++++++++++---- systemd/opendtu-logger.service | 5 +- 6 files changed, 109 insertions(+), 21 deletions(-) diff --git a/docker/compose.with-database-grafana.yml b/docker/compose.with-database-grafana.yml index 2a63282..d72d7e7 100644 --- a/docker/compose.with-database-grafana.yml +++ b/docker/compose.with-database-grafana.yml @@ -26,7 +26,10 @@ services: restart: always environment: DB_URL: ${DB_URL} - REMOTE_URL: ${REMOTE_URL} + OPENDTU_ADDRESS: ${OPENDTU_ADDRESS} + OPENDTU_AUTH: ${OPENDTU_AUTH} + OPENDTU_USERNAME: ${OPENDTU_USERNAME} + OPENDTU_PASSWORD: ${OPENDTU_PASSWORD} TIMESCALEDB_ENABLED: ${TIMESCALEDB_ENABLED} TZ: ${TZ} depends_on: diff --git a/docker/compose.with-database.yml b/docker/compose.with-database.yml index 867bbd9..277ee63 100644 --- a/docker/compose.with-database.yml +++ b/docker/compose.with-database.yml @@ -26,7 +26,10 @@ services: image: git.hollander.online/energy/opendtu-logger:latest environment: DB_URL: ${DB_URL} - REMOTE_URL: ${REMOTE_URL} + OPENDTU_ADDRESS: ${OPENDTU_ADDRESS} + OPENDTU_AUTH: ${OPENDTU_AUTH} + OPENDTU_USERNAME: ${OPENDTU_USERNAME} + OPENDTU_PASSWORD: ${OPENDTU_PASSWORD} TIMESCALEDB_ENABLED: ${TIMESCALEDB_ENABLED} TZ: ${TZ} depends_on: diff --git a/docker/compose.yml b/docker/compose.yml index dc0fbe3..2c29835 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -5,7 +5,10 @@ services: image: git.hollander.online/energy/opendtu-logger:latest environment: DB_URL: ${DB_URL} - REMOTE_URL: ${REMOTE_URL} + OPENDTU_ADDRESS: ${OPENDTU_ADDRESS} + OPENDTU_AUTH: ${OPENDTU_AUTH} + OPENDTU_USERNAME: ${OPENDTU_USERNAME} + OPENDTU_PASSWORD: ${OPENDTU_PASSWORD} TIMESCALEDB_ENABLED: ${TIMESCALEDB_ENABLED} TZ: ${TZ} depends_on: diff --git a/docker/example.with-database.env b/docker/example.with-database.env index a283d89..5131f51 100644 --- a/docker/example.with-database.env +++ b/docker/example.with-database.env @@ -1,9 +1,13 @@ +# OpenDTU +OPENDTU_ADDRESS="192.168.1.89:80" +OPENDTU_AUTH=false +OPENDTU_USERNAME= +OPENDTU_PASSWORD= # OpenDTU Logger -REMOTE_URL="192.168.1.89:80" DB_URL="host=timescaledb port=5432 user=postgres password=secret dbname=opendtu_logger sslmode=disable" TIMESCALEDB_ENABLED=true TZ="Europe/Amsterdam" # Database configuration PG_USER=postgres PG_PASSWORD= -PG_DB=opendtu_logger \ No newline at end of file +PG_DB=opendtu_logger diff --git a/main.go b/main.go index 8bd6657..2d3921f 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,4 @@ // TODO: Storage optimisation: Map inverter serial to shorter serial. Use that for referring. -// TODO: Use username and password provided using Basic Authentication. // TODO: Record Inverter struct data only on-change. // Idea: Make a full admin / config GUI and only configure through this utility. // Idea: Gather settings only on start-up. @@ -9,6 +8,7 @@ package main import ( "database/sql" + "encoding/base64" "encoding/json" "fmt" "io/fs" @@ -149,10 +149,13 @@ type InverterSettingsData struct { // Config settings struct type Config struct { - DB string `json:"db"` - OpenDTU string `json:"opendtu"` - TimescaleDB bool `json:"timescaledb"` - TZ string `json:"tz"` + DB string `json:"db"` + OpenDTUAddress string `json:"opendtu_address"` + OpenDTUAuth bool `json:"opendtu_auth"` + OpenDTUUser string `json:"opendtu_username"` + OpenDTUPassword string `json:"opendtu_password"` + TimescaleDB bool `json:"timescaledb"` + TZ string `json:"tz"` } var logger = slog.New(slog.NewJSONHandler(os.Stdout, nil)) @@ -173,15 +176,50 @@ func loadConfig() Config { if err != nil { log.Fatalf("Error parsing config file: %v", err) } + if config.DB == "" { + log.Fatal("db connection settings are not set") + } + if config.OpenDTUAddress == "" { + log.Fatal("opendtu_address is not set") + } + if config.OpenDTUAuth { + if config.OpenDTUUser == "" { + log.Fatal("opendtu_username is not set, while opendtu_auth is set to enabled. Set opendtu_auth to false or set username") + } + if config.OpenDTUPassword == "" { + log.Fatal("opendtu_password is not set, while opendtu_auth is set to enabled. Set opendtu_auth to false or set password") + } + } } else { + logger.Info("JSON config file not found. Falling back to environment variables.") // Fallback to environment variables config.DB = os.Getenv("DB_URL") if config.DB == "" { log.Fatal("DB_URL environment variable is not set.") } - config.OpenDTU = os.Getenv("REMOTE_URL") - if config.OpenDTU == "" { - log.Fatal("REMOTE_URL environment variable is not set.") + config.OpenDTUAddress = os.Getenv("OPENDTU_ADDRESS") + if config.OpenDTUAddress == "" { + log.Fatal("OPENDTU_ADDRESS environment variable is not set.") + } + + openDTUAuthStr := os.Getenv("OPENDTU_AUTH") + if openDTUAuthStr != "" { + openDTUAuth, err := strconv.ParseBool(openDTUAuthStr) + if err != nil { + log.Fatalf("Error parsing OPENDTU_AUTH: %v", err) + } + config.OpenDTUAuth = openDTUAuth + } + if config.OpenDTUAuth { + config.OpenDTUUser = os.Getenv("OPENDTU_USERNAME") + if config.OpenDTUUser == "" { + log.Fatal("OPENDTU_USERNAME environment variable is not set.") + } + config.OpenDTUPassword = os.Getenv("OPENDTU_PASSWORD") + if config.OpenDTUPassword == "" { + log.Fatal("OPENDTU_PASSWORD environment variable is not set.") + } + } timescaleDBStr := os.Getenv("TIMESCALEDB_ENABLED") @@ -194,6 +232,10 @@ func loadConfig() Config { } config.TZ = os.Getenv("TZ") } + _, err = time.LoadLocation(config.TZ) + if err != nil { + logger.Warn("invalid timezone") + } return config } @@ -218,10 +260,16 @@ func main() { migrateDB(db) // Create WebSocket URL from config variable - wsURL := "ws://" + config.OpenDTU + "/livedata" + wsURL := "ws://" + config.OpenDTUAddress + "/livedata" + + // Create headers with optional Basic Auth + headers := http.Header{} + if config.OpenDTUAuth { + headers.Set("Authorization", basicAuth(config.OpenDTUUser, config.OpenDTUPassword)) + } // Establish WebSocket connection - c, _, err := websocket.DefaultDialer.Dial(wsURL, nil) + c, _, err := websocket.DefaultDialer.Dial(wsURL, headers) if err != nil { log.Fatal(err) } @@ -424,15 +472,33 @@ func migrateFS(db *sql.DB, migrationFS fs.FS, dir string) error { } func queryEventsEndpoint(inverterSerial string) (*EventsResponse, error) { - remoteURL := config.OpenDTU - endpoint := fmt.Sprintf("http://"+remoteURL+"/api/eventlog/status?inv=%s", inverterSerial) + endpoint := fmt.Sprintf("http://"+config.OpenDTUAddress+"/api/eventlog/status?inv=%s", inverterSerial) - resp, err := http.Get(endpoint) + // Create a new HTTP request + req, err := http.NewRequest("GET", endpoint, nil) + if err != nil { + return nil, err + } + + if config.OpenDTUAuth { + // Add Basic Auth header + req.Header.Add("Authorization", basicAuth(config.OpenDTUUser, config.OpenDTUPassword)) + } + + // Send the request + client := &http.Client{} + resp, err := client.Do(req) if err != nil { return nil, err } defer resp.Body.Close() + // Check for HTTP errors + if resp.StatusCode != http.StatusOK { + return nil, fmt.Errorf("HTTP request failed with status: %s", resp.Status) + } + + // Decode the response var eventsResponse EventsResponse if err := json.NewDecoder(resp.Body).Decode(&eventsResponse); err != nil { return nil, err @@ -508,6 +574,12 @@ func updateEvents(db *sql.DB, inverterSerial string, events *EventsResponse) { } } +// basicAuth generates the Basic Auth header value +func basicAuth(username, password string) string { + credentials := username + ":" + password + return "Basic " + base64.StdEncoding.EncodeToString([]byte(credentials)) +} + // TODO: finish this function. // func updateInverterConfig(db *sql.DB) { // // Periodically query the /api/inverter/list @@ -526,8 +598,8 @@ func updateEvents(db *sql.DB, inverterSerial string, events *EventsResponse) { // } // func queryConfigEndpoint() (*InverterSettingsData, error) { -// remoteURL := os.Getenv("REMOTE_URL") -// endpoint := fmt.Sprintf("http://" + remoteURL + "/api/inverter/list") +// openDTUAddress := os.Getenv("OPENDTU_ADDRESS") +// endpoint := fmt.Sprintf("http://" + openDTUAddress + "/api/inverter/list") // resp, err := http.Get(endpoint) // if err != nil { diff --git a/systemd/opendtu-logger.service b/systemd/opendtu-logger.service index 9c14fb6..60fa257 100644 --- a/systemd/opendtu-logger.service +++ b/systemd/opendtu-logger.service @@ -16,7 +16,10 @@ Type=simple User=opendtu-logger Group=opendtu-logger -Environment="REMOTE_URL=opendtu.local:80" +Environment="OPENDTU_ADDRESS=opendtu.local:80" +Environment="OPENDTU_AUTH=false" +Environment="OPENDTU_USERNAME=admin" +Environment="OPENDTU_PASSWORD=your_super_secret_password" Environment="DB_URL=host=localhost port=5432 user=postgres password=secret dbname=dtu sslmode=disable" Environment="TIMESCALEDB_ENABLED=true" Environment="TZ=Europe/Amsterdam" From b63c1e85d33b47812049a8526c743c8a1647baf4 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 27 Jul 2024 00:08:40 +0200 Subject: [PATCH 06/23] Add DEBUG log_level. --- main.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/main.go b/main.go index 2d3921f..60d76ae 100644 --- a/main.go +++ b/main.go @@ -156,6 +156,7 @@ type Config struct { OpenDTUPassword string `json:"opendtu_password"` TimescaleDB bool `json:"timescaledb"` TZ string `json:"tz"` + LogLevel string `json:"log_level"` } var logger = slog.New(slog.NewJSONHandler(os.Stdout, nil)) @@ -240,6 +241,30 @@ func loadConfig() Config { return config } +// Helper function to map environment variable to slog.Level +func getLogLevel(defaultLevel slog.Level) slog.Level { + logLevelStr := config.LogLevel + switch logLevelStr { + case "DEBUG": + return slog.LevelDebug + case "INFO": + return slog.LevelInfo + case "WARN": + return slog.LevelWarn + case "ERROR": + return slog.LevelError + default: + return defaultLevel + } +} + +// Function to create a new logger with a specified log level +func createLoggerWithLevel(level slog.Level) *slog.Logger { + return slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{ + Level: level, + })) +} + // Main program func main() { // Initial logger setup @@ -248,6 +273,10 @@ func main() { // Load the configuration config := loadConfig() + // Set the logLevel + logLevel := getLogLevel(slog.LevelInfo) // Default to info level + logger = createLoggerWithLevel(logLevel) + dbConnStr := config.DB // Connect to PostgreSQL db, err := sql.Open("postgres", dbConnStr) @@ -262,6 +291,8 @@ func main() { // Create WebSocket URL from config variable wsURL := "ws://" + config.OpenDTUAddress + "/livedata" + logger.Debug(wsURL) + // Create headers with optional Basic Auth headers := http.Header{} if config.OpenDTUAuth { From 3556e401bc3fc0aebdfe91d196c604aa42ff49c9 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 27 Jul 2024 00:42:51 +0200 Subject: [PATCH 07/23] Add configurable LOG_LEVEL env vars. --- docker/compose.with-database-grafana.yml | 1 + docker/compose.with-database.yml | 2 ++ docker/compose.yml | 1 + docker/example.env | 11 +++++++++++ docker/example.with-database.env | 3 +++ main.go | 1 + systemd/opendtu-logger.service | 2 ++ 7 files changed, 21 insertions(+) create mode 100644 docker/example.env diff --git a/docker/compose.with-database-grafana.yml b/docker/compose.with-database-grafana.yml index d72d7e7..1833916 100644 --- a/docker/compose.with-database-grafana.yml +++ b/docker/compose.with-database-grafana.yml @@ -32,6 +32,7 @@ services: OPENDTU_PASSWORD: ${OPENDTU_PASSWORD} TIMESCALEDB_ENABLED: ${TIMESCALEDB_ENABLED} TZ: ${TZ} + LOG_LEVEL: ${LOG_LEVEL} depends_on: timescaledb: condition: service_healthy diff --git a/docker/compose.with-database.yml b/docker/compose.with-database.yml index 277ee63..fdbb400 100644 --- a/docker/compose.with-database.yml +++ b/docker/compose.with-database.yml @@ -32,6 +32,8 @@ services: OPENDTU_PASSWORD: ${OPENDTU_PASSWORD} TIMESCALEDB_ENABLED: ${TIMESCALEDB_ENABLED} TZ: ${TZ} + LOG_LEVEL: ${LOG_LEVEL} + depends_on: timescaledb: condition: service_healthy diff --git a/docker/compose.yml b/docker/compose.yml index 2c29835..5d60048 100644 --- a/docker/compose.yml +++ b/docker/compose.yml @@ -11,6 +11,7 @@ services: OPENDTU_PASSWORD: ${OPENDTU_PASSWORD} TIMESCALEDB_ENABLED: ${TIMESCALEDB_ENABLED} TZ: ${TZ} + LOG_LEVEL: ${LOG_LEVEL} depends_on: timescaledb: condition: service_healthy diff --git a/docker/example.env b/docker/example.env new file mode 100644 index 0000000..aa51cd1 --- /dev/null +++ b/docker/example.env @@ -0,0 +1,11 @@ +# OpenDTU +OPENDTU_ADDRESS="192.168.1.89:80" +OPENDTU_AUTH=false +OPENDTU_USERNAME= +OPENDTU_PASSWORD= + +# OpenDTU Logger +DB_URL="host=timescaledb port=5432 user=postgres password=secret dbname=opendtu_logger sslmode=disable" +TIMESCALEDB_ENABLED=true +TZ="Europe/Amsterdam" +LOG_LEVEL=INFO" \ No newline at end of file diff --git a/docker/example.with-database.env b/docker/example.with-database.env index 5131f51..d6cd1d8 100644 --- a/docker/example.with-database.env +++ b/docker/example.with-database.env @@ -3,10 +3,13 @@ OPENDTU_ADDRESS="192.168.1.89:80" OPENDTU_AUTH=false OPENDTU_USERNAME= OPENDTU_PASSWORD= + # OpenDTU Logger DB_URL="host=timescaledb port=5432 user=postgres password=secret dbname=opendtu_logger sslmode=disable" TIMESCALEDB_ENABLED=true TZ="Europe/Amsterdam" +LOG_LEVEL=INFO" + # Database configuration PG_USER=postgres PG_PASSWORD= diff --git a/main.go b/main.go index 60d76ae..ac98c20 100644 --- a/main.go +++ b/main.go @@ -232,6 +232,7 @@ func loadConfig() Config { config.TimescaleDB = timescaleDB } config.TZ = os.Getenv("TZ") + config.LogLevel = os.Getenv("LOG_LEVEL") } _, err = time.LoadLocation(config.TZ) if err != nil { diff --git a/systemd/opendtu-logger.service b/systemd/opendtu-logger.service index 60fa257..88ad6ad 100644 --- a/systemd/opendtu-logger.service +++ b/systemd/opendtu-logger.service @@ -23,6 +23,8 @@ Environment="OPENDTU_PASSWORD=your_super_secret_password" Environment="DB_URL=host=localhost port=5432 user=postgres password=secret dbname=dtu sslmode=disable" Environment="TIMESCALEDB_ENABLED=true" Environment="TZ=Europe/Amsterdam" +Environment="LOG_LEVEL=INFO" + WorkingDirectory=/opt/opendtu-logger/ ExecStart=/opt/opendtu-logger/opendtu-logger From 32bebfdca2f4d4762d0cd54cfd8a85fb1c8198d2 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 27 Jul 2024 00:43:29 +0200 Subject: [PATCH 08/23] Add default admin user to OPENDTU_USERNAME --- docker/example.env | 2 +- docker/example.with-database.env | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/example.env b/docker/example.env index aa51cd1..f94605f 100644 --- a/docker/example.env +++ b/docker/example.env @@ -1,7 +1,7 @@ # OpenDTU OPENDTU_ADDRESS="192.168.1.89:80" OPENDTU_AUTH=false -OPENDTU_USERNAME= +OPENDTU_USERNAME=admin OPENDTU_PASSWORD= # OpenDTU Logger diff --git a/docker/example.with-database.env b/docker/example.with-database.env index d6cd1d8..b5d280f 100644 --- a/docker/example.with-database.env +++ b/docker/example.with-database.env @@ -1,7 +1,7 @@ # OpenDTU OPENDTU_ADDRESS="192.168.1.89:80" OPENDTU_AUTH=false -OPENDTU_USERNAME= +OPENDTU_USERNAME=admin OPENDTU_PASSWORD= # OpenDTU Logger From 014a5e85a2290b88ed93c0ee368b7a2dcfa40094 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Wed, 7 Aug 2024 18:55:26 +0200 Subject: [PATCH 09/23] Fix to take into account user-defined timezone for insertEvents. Add multi OpenDTU TODO. --- main.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/main.go b/main.go index ac98c20..295ed2a 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ // Idea: Gather settings only on start-up. // TODO: Only update meter readings such as yieldday, yieldtotal on-change. // TODO: Add a health check endpoint, potentially log to it. +// TODO: Add support for monitoring multiple OpenDTU's at once. package main import ( @@ -563,7 +564,9 @@ func getPreviousEventsCount(db *sql.DB, inverterSerial string) int { } func insertEvents(db *sql.DB, inverterSerial string, events *EventsResponse) { - timestamp := time.Now() + timeZone := config.TZ + loc, _ := time.LoadLocation(timeZone) + timestamp := time.Now().In(loc) for _, event := range events.Events { // Insert events data into the events table From b8ea94bb61bd1d53e61e176f88ecd0be8ec19b32 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Thu, 8 Aug 2024 11:18:26 +0200 Subject: [PATCH 10/23] Add TARGETOS and TARGETARCH to fix multi-platform compilation issue. --- Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Dockerfile b/Dockerfile index d05c839..3859d1c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,6 +11,8 @@ RUN go mod download COPY . . # Build the application for the specified target architecture +# https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/ +ARG TARGETOS TARGETARCH RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -o opendtu-logger . # Create a minimal runtime image From ce336b4f852970e333697daf1dd724d079c07e9d Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Thu, 8 Aug 2024 11:19:01 +0200 Subject: [PATCH 11/23] Make go build TARGETOS configurable. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 3859d1c..f5c5bfa 100644 --- a/Dockerfile +++ b/Dockerfile @@ -13,7 +13,7 @@ COPY . . # Build the application for the specified target architecture # https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/ ARG TARGETOS TARGETARCH -RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} go build -o opendtu-logger . +RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o opendtu-logger . # Create a minimal runtime image FROM --platform=${TARGETPLATFORM} scratch From c8b8211e3a29fe9495b028b4c53ac715790564d1 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 10 Aug 2024 09:54:57 +0200 Subject: [PATCH 12/23] Add documentation for ARG TARGET* --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index f5c5bfa..e3370f4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,6 +12,7 @@ COPY . . # Build the application for the specified target architecture # https://www.docker.com/blog/faster-multi-platform-builds-dockerfile-cross-compilation-guide/ +# Declare TARGETOS and TARGETARCH in the local scope so they can be used in the build stage. ARG TARGETOS TARGETARCH RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build -o opendtu-logger . From ed1b6d69eced04280c500d3a5b50eed71f4270ca Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 10 Aug 2024 23:42:38 +0200 Subject: [PATCH 13/23] Go dependency upgrades --- go.mod | 4 ++-- go.sum | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/go.mod b/go.mod index 1d86d89..56b9f3e 100644 --- a/go.mod +++ b/go.mod @@ -10,8 +10,8 @@ require ( require ( github.com/mfridman/interpolate v0.0.2 // indirect - github.com/sethvargo/go-retry v0.2.4 // indirect + github.com/sethvargo/go-retry v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect + golang.org/x/sync v0.8.0 // indirect ) diff --git a/go.sum b/go.sum index f93ce7b..4b6f974 100644 --- a/go.sum +++ b/go.sum @@ -26,6 +26,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94 github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= +github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= +github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= @@ -36,6 +38,8 @@ golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= From 626b7f9993856b3e76262a731ff178d96acb4814 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Wed, 14 Aug 2024 19:34:59 +0200 Subject: [PATCH 14/23] Update Go 1.22 -> 1.23 --- Dockerfile | 2 +- go.mod | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index e3370f4..0d495b7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use buildx for multi-architecture support -FROM --platform=${BUILDPLATFORM} golang:1.22 AS builder +FROM --platform=${BUILDPLATFORM} golang:1.23 AS builder WORKDIR /app diff --git a/go.mod b/go.mod index 56b9f3e..95f7e17 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module git.hollander.online/energy/opendtu-logger -go 1.22 +go 1.23 require ( github.com/gorilla/websocket v1.5.3 From 0052a9848b2e3d485c2e231d9f898608bfee4a2b Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Wed, 14 Aug 2024 23:18:54 +0200 Subject: [PATCH 15/23] go mod tidy --- go.mod | 2 +- go.sum | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/go.mod b/go.mod index 95f7e17..d12d80b 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,6 @@ require ( github.com/mfridman/interpolate v0.0.2 // indirect github.com/sethvargo/go-retry v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/net v0.27.0 // indirect golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.22.0 // indirect ) diff --git a/go.sum b/go.sum index 4b6f974..e94c10f 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkp github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY= -github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= @@ -24,25 +22,16 @@ github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78b github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/sethvargo/go-retry v0.2.4 h1:T+jHEQy/zKJf5s95UkguisicE0zuF9y7+/vgz08Ocec= -github.com/sethvargo/go-retry v0.2.4/go.mod h1:1afjQuvh7s4gflMObvjLPaWgluLLyhA1wmVZ6KLpICw= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= -golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= -golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= +golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= From dc6f41eeb05b2a8bb9112042e5d3d48dc85db699 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 14 Sep 2024 18:15:52 +0200 Subject: [PATCH 16/23] Update go dependencies. --- go.mod | 2 +- go.sum | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index d12d80b..bd0988c 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23 require ( github.com/gorilla/websocket v1.5.3 github.com/lib/pq v1.10.9 - github.com/pressly/goose/v3 v3.21.1 + github.com/pressly/goose/v3 v3.22.0 ) require ( diff --git a/go.sum b/go.sum index e94c10f..01051c6 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= +github.com/pressly/goose/v3 v3.22.0 h1:wd/7kNiPTuNAztWun7iaB98DrhulbWPrzMAaw2DEZNw= +github.com/pressly/goose/v3 v3.22.0/go.mod h1:yJM3qwSj2pp7aAaCvso096sguezamNb2OBgxCnh/EYg= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= @@ -38,12 +40,15 @@ modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQX modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= +modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= +modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4= modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 50d89748f7361163740e7ffb1eba35af45afb20d Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 14 Sep 2024 18:16:13 +0200 Subject: [PATCH 17/23] go mod tidy --- go.mod | 1 - go.sum | 11 +++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index bd0988c..aa9616d 100644 --- a/go.mod +++ b/go.mod @@ -13,5 +13,4 @@ require ( github.com/sethvargo/go-retry v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.22.0 // indirect ) diff --git a/go.sum b/go.sum index 01051c6..60e41cf 100644 --- a/go.sum +++ b/go.sum @@ -18,8 +18,6 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pressly/goose/v3 v3.21.1 h1:5SSAKKWej8LVVzNLuT6KIvP1eFDuPvxa+B6H0w78buQ= -github.com/pressly/goose/v3 v3.21.1/go.mod h1:sqthmzV8PitchEkjecFJII//l43dLOCzfWh8pHEe+vE= github.com/pressly/goose/v3 v3.22.0 h1:wd/7kNiPTuNAztWun7iaB98DrhulbWPrzMAaw2DEZNw= github.com/pressly/goose/v3 v3.22.0/go.mod h1:yJM3qwSj2pp7aAaCvso096sguezamNb2OBgxCnh/EYg= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= @@ -38,17 +36,14 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= -modernc.org/libc v1.41.0 h1:g9YAc6BkKlgORsUWj+JwqoB1wU3o4DE3bM3yvA3k+Gk= -modernc.org/libc v1.41.0/go.mod h1:w0eszPsiXoOnoMJgrXjglgLuDy/bt5RR4y3QzUUeodY= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= +modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= -modernc.org/memory v1.7.2 h1:Klh90S215mmH8c9gO98QxQFsY+W451E8AnzjoE2ee1E= -modernc.org/memory v1.7.2/go.mod h1:NO4NVCQy0N7ln+T9ngWqOQfi7ley4vpwvARR+Hjw95E= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= -modernc.org/sqlite v1.29.6 h1:0lOXGrycJPptfHDuohfYgNqoe4hu+gYuN/pKgY5XjS4= -modernc.org/sqlite v1.29.6/go.mod h1:S02dvcmm7TnTRvGhv8IGYyLnIt7AS2KPaB1F/71p75U= +modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= +modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 40abe7309d3bbd7f7104c952867902f0e70d38de Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Fri, 17 Jan 2025 12:40:34 +0100 Subject: [PATCH 18/23] Add note about OpenDTU version compatibility --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index faa518d..a1221fb 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,7 @@ Installation on Home Assistant can be done by adding the [Home Assistant add-on ### Configuring OpenDTU In order for OpenDTU Logger to work properly, it is required to ensure the following OpenDTU settings are used. +OpenDTU Logger 0.1.3 has been tested with OpenDTU versions v24.6.10 - v25.1.14. - Within OpenDTU, go to `Settings` -> `Inverter settings` (). - For each inverter in the inverter list, click on the pencil (Edit inverter) and go to `Advanced`. From af30019ba0226a0d2d913e90a3a107ac6f1bdcd4 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 15 Feb 2025 11:30:05 +0100 Subject: [PATCH 19/23] Upgrade dependencies. Upgrade go 1.23 > 1.24. --- go.mod | 6 +++--- go.sum | 7 +++++++ 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index aa9616d..292cd48 100644 --- a/go.mod +++ b/go.mod @@ -1,16 +1,16 @@ module git.hollander.online/energy/opendtu-logger -go 1.23 +go 1.24 require ( github.com/gorilla/websocket v1.5.3 github.com/lib/pq v1.10.9 - github.com/pressly/goose/v3 v3.22.0 + github.com/pressly/goose/v3 v3.24.1 ) require ( github.com/mfridman/interpolate v0.0.2 // indirect github.com/sethvargo/go-retry v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/sync v0.11.0 // indirect ) diff --git a/go.sum b/go.sum index 60e41cf..de9e9dd 100644 --- a/go.sum +++ b/go.sum @@ -20,18 +20,24 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pressly/goose/v3 v3.22.0 h1:wd/7kNiPTuNAztWun7iaB98DrhulbWPrzMAaw2DEZNw= github.com/pressly/goose/v3 v3.22.0/go.mod h1:yJM3qwSj2pp7aAaCvso096sguezamNb2OBgxCnh/EYg= +github.com/pressly/goose/v3 v3.24.1 h1:bZmxRco2uy5uu5Ng1MMVEfYsFlrMJI+e/VMXHQ3C4LY= +github.com/pressly/goose/v3 v3.24.1/go.mod h1:rEWreU9uVtt0DHCyLzF9gRcWiiTF/V+528DV+4DORug= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= github.com/sethvargo/go-retry v0.3.0/go.mod h1:mNX17F0C/HguQMyMyJxcnU471gOZGxCLyYaFyAZraas= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= @@ -44,6 +50,7 @@ modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= +modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From 7f5fa4962eee61be81c63559b40932fd60f49713 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 15 Feb 2025 11:33:16 +0100 Subject: [PATCH 20/23] Upgrade OpenDTU compatibiity to v25.2.3 --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a1221fb..7a6b4d0 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Installation on Home Assistant can be done by adding the [Home Assistant add-on ### Configuring OpenDTU In order for OpenDTU Logger to work properly, it is required to ensure the following OpenDTU settings are used. -OpenDTU Logger 0.1.3 has been tested with OpenDTU versions v24.6.10 - v25.1.14. +OpenDTU Logger 0.1.4 has been tested with OpenDTU versions v24.6.10 - v25.2.3. - Within OpenDTU, go to `Settings` -> `Inverter settings` (). - For each inverter in the inverter list, click on the pencil (Edit inverter) and go to `Advanced`. From f75fe8d72cb72664dbf5dd244376108ab3de9988 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Sat, 15 Feb 2025 11:41:19 +0100 Subject: [PATCH 21/23] Upgrade Docker golang 1.23 > 1.24 --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 0d495b7..f8e11a4 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # Use buildx for multi-architecture support -FROM --platform=${BUILDPLATFORM} golang:1.23 AS builder +FROM --platform=${BUILDPLATFORM} golang:1.24 AS builder WORKDIR /app From 39dd6ae0d61f750aa87bbe738e4c9feacddbc6b9 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Thu, 15 May 2025 14:04:48 +0200 Subject: [PATCH 22/23] Verify compatibility OpenDTU 25.5.10. Update dependencies. --- README.md | 2 +- go.mod | 4 ++-- go.sum | 9 +++++++++ 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 7a6b4d0..b90378a 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Installation on Home Assistant can be done by adding the [Home Assistant add-on ### Configuring OpenDTU In order for OpenDTU Logger to work properly, it is required to ensure the following OpenDTU settings are used. -OpenDTU Logger 0.1.4 has been tested with OpenDTU versions v24.6.10 - v25.2.3. +OpenDTU Logger 0.1.4 has been tested with OpenDTU versions v24.6.10 - v25.5.10. - Within OpenDTU, go to `Settings` -> `Inverter settings` (). - For each inverter in the inverter list, click on the pencil (Edit inverter) and go to `Advanced`. diff --git a/go.mod b/go.mod index 292cd48..9e78730 100644 --- a/go.mod +++ b/go.mod @@ -5,12 +5,12 @@ go 1.24 require ( github.com/gorilla/websocket v1.5.3 github.com/lib/pq v1.10.9 - github.com/pressly/goose/v3 v3.24.1 + github.com/pressly/goose/v3 v3.24.3 ) require ( github.com/mfridman/interpolate v0.0.2 // indirect github.com/sethvargo/go-retry v0.3.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sync v0.11.0 // indirect + golang.org/x/sync v0.14.0 // indirect ) diff --git a/go.sum b/go.sum index de9e9dd..0a2bb1c 100644 --- a/go.sum +++ b/go.sum @@ -22,6 +22,8 @@ github.com/pressly/goose/v3 v3.22.0 h1:wd/7kNiPTuNAztWun7iaB98DrhulbWPrzMAaw2DEZ github.com/pressly/goose/v3 v3.22.0/go.mod h1:yJM3qwSj2pp7aAaCvso096sguezamNb2OBgxCnh/EYg= github.com/pressly/goose/v3 v3.24.1 h1:bZmxRco2uy5uu5Ng1MMVEfYsFlrMJI+e/VMXHQ3C4LY= github.com/pressly/goose/v3 v3.24.1/go.mod h1:rEWreU9uVtt0DHCyLzF9gRcWiiTF/V+528DV+4DORug= +github.com/pressly/goose/v3 v3.24.3 h1:DSWWNwwggVUsYZ0X2VitiAa9sKuqtBfe+Jr9zFGwWlM= +github.com/pressly/goose/v3 v3.24.3/go.mod h1:v9zYL4xdViLHCUUJh/mhjnm6JrK7Eul8AS93IxiZM4E= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/sethvargo/go-retry v0.3.0 h1:EEt31A35QhrcRZtrYFDTBg91cqZVnFL2navjDrah2SE= @@ -35,22 +37,29 @@ golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ= +golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI= modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4= modernc.org/libc v1.55.3 h1:AzcW1mhlPNrRtjS5sS+eW2ISCgSOLLNyFzRh/V3Qj/U= modernc.org/libc v1.55.3/go.mod h1:qFXepLhz+JjFThQ4kzwzOjA/y/artDeg+pcYnY+Q83w= +modernc.org/libc v1.65.0 h1:e183gLDnAp9VJh6gWKdTy0CThL9Pt7MfcR/0bgb7Y1Y= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo= +modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E= modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU= +modernc.org/memory v1.10.0 h1:fzumd51yQ1DxcOxSO+S6X7+QTuVU+n8/Aj7swYjFfC4= modernc.org/sqlite v1.32.0 h1:6BM4uGza7bWypsw4fdLRsLxut6bHe4c58VeqjRgST8s= modernc.org/sqlite v1.32.0/go.mod h1:UqoylwmTb9F+IqXERT8bW9zzOWN8qwAIcLdzeBZs4hA= modernc.org/sqlite v1.34.1 h1:u3Yi6M0N8t9yKRDwhXcyp1eS5/ErhPTBggxWFuR6Hfk= +modernc.org/sqlite v1.37.0 h1:s1TMe7T3Q3ovQiK2Ouz4Jwh7dw4ZDqbebSDTlSJdfjI= modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA= modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0= modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= From a654dd802e6ff2908c83e53e2f79f76c23c35259 Mon Sep 17 00:00:00 2001 From: Pieter Hollander Date: Thu, 15 May 2025 14:19:06 +0200 Subject: [PATCH 23/23] Remove superfluous newline. --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index b90378a..3139d93 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,6 @@ OpenDTU Logger 0.1.4 has been tested with OpenDTU versions v24.6.10 - v25.5.10. - Click `Save` - Repeat this procedure for every inverter. - ### Docker Compose The `docker` folder in this [repository](https://git.hollander.online/energy/opendtu-logger) contains example Docker compose files. The `compose.with-database-grafana.yml` file contains a full setup suitable for a standalone deployment. The other compose files are aimed at integration into existing environments.