Write meter data to store
continuous-integration/drone/push Build is passing Details

This commit is contained in:
Rob Watson 2022-07-19 21:34:32 +02:00
parent 1d716594da
commit a7f18e4f75
5 changed files with 63 additions and 42 deletions

View File

@ -60,9 +60,16 @@ func main() {
continue
}
reqBody, err := json.Marshal(runtimeData)
meterData, err := inv.MeterData(context.Background(), conn)
if err != nil {
log.Printf("error encoding runtime data: %s", err)
log.Printf("error fetching meter data: %s", err)
continue
}
frame := inverter.ETDataFrame{ETRuntimeData: runtimeData, ETMeterData: meterData}
reqBody, err := json.Marshal(frame)
if err != nil {
log.Printf("error encoding frame: %s", err)
continue
}

View File

@ -12,7 +12,7 @@ import (
const timestampMinimumYear = 2022
type Store interface {
InsertETRuntimeData(*inverter.ETRuntimeData) error
InsertDataFrame(*inverter.ETDataFrame) error
}
type Handler struct {
@ -48,7 +48,7 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
var runtimeData inverter.ETRuntimeData
err = json.Unmarshal(body, &runtimeData)
if err != nil {
log.Printf("could not unmarshal body: %v", err)
log.Printf("could not unmarshal runtime data body: %v", err)
http.Error(w, "unexpected error", http.StatusInternalServerError)
return
}
@ -59,7 +59,16 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return
}
if err = h.store.InsertETRuntimeData(&runtimeData); err != nil {
var meterData inverter.ETMeterData
err = json.Unmarshal(body, &meterData)
if err != nil {
log.Printf("could not unmarshal meterData body: %v", err)
http.Error(w, "unexpected error", http.StatusInternalServerError)
return
}
dataFrame := inverter.ETDataFrame{ETRuntimeData: &runtimeData, ETMeterData: &meterData}
if err = h.store.InsertDataFrame(&dataFrame); err != nil {
log.Printf("error storing data: %v", err)
http.Error(w, "unexpected error", http.StatusInternalServerError)
return

View File

@ -14,11 +14,11 @@ import (
"github.com/stretchr/testify/require"
)
type store struct {
type mockStore struct {
err error
}
func (s *store) InsertETRuntimeData(*inverter.ETRuntimeData) error {
func (s *mockStore) InsertDataFrame(*inverter.ETDataFrame) error {
return s.err
}
@ -90,7 +90,7 @@ func TestHandler(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
mockStore := store{err: tc.storeErr}
mockStore := mockStore{err: tc.storeErr}
handler := handler.New(&mockStore)
req := httptest.NewRequest(tc.httpMethod, tc.path, strings.NewReader(tc.body))
rec := httptest.NewRecorder()

View File

@ -15,10 +15,10 @@ func NewSQL(db *sqlx.DB) *PostgresStore {
return &PostgresStore{db: db}
}
const insertSql = `INSERT INTO et_runtime_data (timestamp, pv1_voltage, pv1_current, pv1_power, pv2_voltage, pv2_current, pv2_power, pv_power, pv2_mode, pv1_mode, on_grid_l1_voltage, on_grid_l1_current, on_grid_l1_frequency, on_grid_l1_power, on_grid_l2_voltage, on_grid_l2_current, on_grid_l2_frequency, on_grid_l2_power, on_grid_l3_voltage, on_grid_l3_current, on_grid_l3_frequency, on_grid_l3_power, grid_mode, total_inverter_power, active_power, reactive_power, apparent_power, backup_l1_voltage, backup_l1_current, backup_l1_frequency, load_mode_l1, backup_l1_power, backup_l2_voltage, backup_l2_current, backup_l2_frequency, load_mode_l2, backup_l2_power, backup_l3_voltage, backup_l3_current, backup_l3_frequency, load_mode_l3, backup_l3_power, load_l1, load_l2, load_l3, backup_load, load, ups_load, temperature_air, temperature_module, temperature, bus_voltage, nbus_voltage, battery_voltage, battery_current, battery_mode, warning_code, safety_country_code, work_mode, operation_code, energy_generation_total, energy_generation_today, energy_export_total, energy_export_total_hours, energy_export_today, energy_import_total, energy_import_today, energy_load_total, energy_load_day, battery_charge_total, battery_charge_today, battery_discharge_total, battery_discharge_today, house_consumption, created_at) VALUES (:timestamp, :pv1_voltage, :pv1_current, :pv1_power, :pv2_voltage, :pv2_current, :pv2_power, :pv_power, :pv2_mode, :pv1_mode, :on_grid_l1_voltage, :on_grid_l1_current, :on_grid_l1_frequency, :on_grid_l1_power, :on_grid_l2_voltage, :on_grid_l2_current, :on_grid_l2_frequency, :on_grid_l2_power, :on_grid_l3_voltage, :on_grid_l3_current, :on_grid_l3_frequency, :on_grid_l3_power, :grid_mode, :total_inverter_power, :active_power, :reactive_power, :apparent_power, :backup_l1_voltage, :backup_l1_current, :backup_l1_frequency, :load_mode_l1, :backup_l1_power, :backup_l2_voltage, :backup_l2_current, :backup_l2_frequency, :load_mode_l2, :backup_l2_power, :backup_l3_voltage, :backup_l3_current, :backup_l3_frequency, :load_mode_l3, :backup_l3_power, :load_l1, :load_l2, :load_l3, :backup_load, :load, :ups_load, :temperature_air, :temperature_module, :temperature, :bus_voltage, :nbus_voltage, :battery_voltage, :battery_current, :battery_mode, :warning_code, :safety_country_code, :work_mode, :operation_code, :energy_generation_total, :energy_generation_today, :energy_export_total, :energy_export_total_hours, :energy_export_today, :energy_import_total, :energy_import_today, :energy_load_total, :energy_load_day, :battery_charge_total, :battery_charge_today, :battery_discharge_total, :battery_discharge_today, :house_consumption, NOW());`
const insertSql = `INSERT INTO et_runtime_data (timestamp, pv1_voltage, pv1_current, pv1_power, pv2_voltage, pv2_current, pv2_power, pv_power, pv2_mode, pv1_mode, on_grid_l1_voltage, on_grid_l1_current, on_grid_l1_frequency, on_grid_l1_power, on_grid_l2_voltage, on_grid_l2_current, on_grid_l2_frequency, on_grid_l2_power, on_grid_l3_voltage, on_grid_l3_current, on_grid_l3_frequency, on_grid_l3_power, grid_mode, total_inverter_power, active_power, reactive_power, apparent_power, backup_l1_voltage, backup_l1_current, backup_l1_frequency, load_mode_l1, backup_l1_power, backup_l2_voltage, backup_l2_current, backup_l2_frequency, load_mode_l2, backup_l2_power, backup_l3_voltage, backup_l3_current, backup_l3_frequency, load_mode_l3, backup_l3_power, load_l1, load_l2, load_l3, backup_load, load, ups_load, temperature_air, temperature_module, temperature, bus_voltage, nbus_voltage, battery_voltage, battery_current, battery_mode, warning_code, safety_country_code, work_mode, operation_code, energy_generation_total, energy_generation_today, energy_export_total, energy_export_total_hours, energy_export_today, energy_import_total, energy_import_today, energy_load_total, energy_load_day, battery_charge_total, battery_charge_today, battery_discharge_total, battery_discharge_today, house_consumption, meter_test_status, meter_comm_status, active_power_l1, active_power_l2, active_power_l3, active_power_total, reactive_power_total, meter_power_factor1, meter_power_factor2, meter_power_factor3, meter_power_factor, meter_frequency, meter_energy_export_total, meter_energy_import_total, meter_active_power1, meter_active_power2, meter_active_power3, meter_active_power_total, meter_reactive_power1, meter_reactive_power2, meter_reactive_power3, meter_reactive_power_total, meter_apparent_power1, meter_apparent_power2, meter_apparent_power3, meter_apparent_power_total, meter_software_version, created_at) VALUES (:timestamp, :pv1_voltage, :pv1_current, :pv1_power, :pv2_voltage, :pv2_current, :pv2_power, :pv_power, :pv2_mode, :pv1_mode, :on_grid_l1_voltage, :on_grid_l1_current, :on_grid_l1_frequency, :on_grid_l1_power, :on_grid_l2_voltage, :on_grid_l2_current, :on_grid_l2_frequency, :on_grid_l2_power, :on_grid_l3_voltage, :on_grid_l3_current, :on_grid_l3_frequency, :on_grid_l3_power, :grid_mode, :total_inverter_power, :active_power, :reactive_power, :apparent_power, :backup_l1_voltage, :backup_l1_current, :backup_l1_frequency, :load_mode_l1, :backup_l1_power, :backup_l2_voltage, :backup_l2_current, :backup_l2_frequency, :load_mode_l2, :backup_l2_power, :backup_l3_voltage, :backup_l3_current, :backup_l3_frequency, :load_mode_l3, :backup_l3_power, :load_l1, :load_l2, :load_l3, :backup_load, :load, :ups_load, :temperature_air, :temperature_module, :temperature, :bus_voltage, :nbus_voltage, :battery_voltage, :battery_current, :battery_mode, :warning_code, :safety_country_code, :work_mode, :operation_code, :energy_generation_total, :energy_generation_today, :energy_export_total, :energy_export_total_hours, :energy_export_today, :energy_import_total, :energy_import_today, :energy_load_total, :energy_load_day, :battery_charge_total, :battery_charge_today, :battery_discharge_total, :battery_discharge_today, :house_consumption, :meter_test_status, :meter_comm_status, :active_power_l1, :active_power_l2, :active_power_l3, :active_power_total, :reactive_power_total, :meter_power_factor1, :meter_power_factor2, :meter_power_factor3, :meter_power_factor, :meter_frequency, :meter_energy_export_total, :meter_energy_import_total, :meter_active_power1, :meter_active_power2, :meter_active_power3, :meter_active_power_total, :meter_reactive_power1, :meter_reactive_power2, :meter_reactive_power3, :meter_reactive_power_total, :meter_apparent_power1, :meter_apparent_power2, :meter_apparent_power3, :meter_apparent_power_total, :meter_software_version, NOW());`
func (s *PostgresStore) InsertETRuntimeData(runtimeData *inverter.ETRuntimeData) error {
if _, err := s.db.NamedExec(insertSql, runtimeData); err != nil {
func (s *PostgresStore) InsertDataFrame(frame *inverter.ETDataFrame) error {
if _, err := s.db.NamedExec(insertSql, frame); err != nil {
return fmt.Errorf("error inserting data: %s", err)
}

View File

@ -138,35 +138,40 @@ type ETRuntimeData struct {
}
type ETMeterData struct {
ComMode int `json:"com_mode"`
RSSI int `json:"rssi"`
ManufactureCode int `json:"manufacture_code"`
MeterTestStatus int `json:"meter_test_status"`
MeterCommStatus int `json:"meter_comm_status"`
ActivePowerL1 Power `json:"active_power_l1"`
ActivePowerL2 Power `json:"active_power_l2"`
ActivePowerL3 Power `json:"active_power_l3"`
ActivePowerTotal Power `json:"active_power_total"`
ReactivePowerTotal int `json:"reactive_power_total"`
MeterPowerFactor1 float64 `json:"meter_power_factor1"`
MeterPowerFactor2 float64 `json:"meter_power_factor2"`
MeterPowerFactor3 float64 `json:"meter_power_factor3"`
MeterPowerFactor float64 `json:"meter_power_factor"`
MeterFrequency Frequency `json:"meter_frequency"`
EnergyExportTotal Power `json:"energy_export_total"`
EnergyImportTotal Power `json:"energy_import_total"`
MeterActivePower1 Power `json:"meter_active_power1"`
MeterActivePower2 Power `json:"meter_active_power2"`
MeterActivePower3 Power `json:"meter_active_power3"`
MeterActivePowerTotal Power `json:"meter_active_power_total"`
MeterReactivePower1 int `json:"meter_reactive_power1"`
MeterReactivePower2 int `json:"meter_reactive_power2"`
MeterReactivePower3 int `json:"meter_reactive_power3"`
MeterReactivePowerTotal int `json:"meter_reactive_power_total"`
MeterApparentPower1 int `json:"meter_apparent_power1"`
MeterApparentPower2 int `json:"meter_apparent_power2"`
MeterApparentPower3 int `json:"meter_apparent_power3"`
MeterApparentPowerTotal int `json:"meter_apparent_power_total"`
MeterType int `json:"meter_type"`
MeterSoftwareVersion int `json:"meter_software_version"`
ComMode int `json:"com_mode" db:"-"`
RSSI int `json:"-" db:"-"`
ManufactureCode int `json:"manufacture_code" db:"-"`
MeterTestStatus int `json:"meter_test_status" db:"meter_test_status"`
MeterCommStatus int `json:"meter_comm_status" db:"meter_comm_status"`
ActivePowerL1 Power `json:"active_power_l1" db:"active_power_l1"`
ActivePowerL2 Power `json:"active_power_l2" db:"active_power_l2"`
ActivePowerL3 Power `json:"active_power_l3" db:"active_power_l3"`
ActivePowerTotal Power `json:"active_power_total" db:"active_power_total"`
ReactivePowerTotal int `json:"reactive_power_total" db:"reactive_power_total"`
MeterPowerFactor1 float64 `json:"meter_power_factor1" db:"meter_power_factor1"`
MeterPowerFactor2 float64 `json:"meter_power_factor2" db:"meter_power_factor2"`
MeterPowerFactor3 float64 `json:"meter_power_factor3" db:"meter_power_factor3"`
MeterPowerFactor float64 `json:"meter_power_factor" db:"meter_power_factor"`
MeterFrequency Frequency `json:"meter_frequency" db:"meter_frequency"`
EnergyExportTotal Power `json:"meter_energy_export_total" db:"meter_energy_export_total"`
EnergyImportTotal Power `json:"meter_energy_import_total" db:"meter_energy_import_total"`
MeterActivePower1 Power `json:"meter_active_power1" db:"meter_active_power1"`
MeterActivePower2 Power `json:"meter_active_power2" db:"meter_active_power2"`
MeterActivePower3 Power `json:"meter_active_power3" db:"meter_active_power3"`
MeterActivePowerTotal Power `json:"meter_active_power_total" db:"meter_active_power_total"`
MeterReactivePower1 int `json:"meter_reactive_power1" db:"meter_reactive_power1"`
MeterReactivePower2 int `json:"meter_reactive_power2" db:"meter_reactive_power2"`
MeterReactivePower3 int `json:"meter_reactive_power3" db:"meter_reactive_power3"`
MeterReactivePowerTotal int `json:"meter_reactive_power_total" db:"meter_reactive_power_total"`
MeterApparentPower1 int `json:"meter_apparent_power1" db:"meter_apparent_power1"`
MeterApparentPower2 int `json:"meter_apparent_power2" db:"meter_apparent_power2"`
MeterApparentPower3 int `json:"meter_apparent_power3" db:"meter_apparent_power3"`
MeterApparentPowerTotal int `json:"meter_apparent_power_total" db:"meter_apparent_power_total"`
MeterType int `json:"meter_type" db:"-"`
MeterSoftwareVersion int `json:"meter_software_version" db:"meter_software_version"`
}
type ETDataFrame struct {
*ETRuntimeData
*ETMeterData
}