Files
invertergui/mk2driver/mk2interface.go
Nathan Coad e8153e2953
All checks were successful
continuous-integration/drone/push Build is passing
implement some features of Venus OS
2026-02-19 15:37:41 +11:00

353 lines
11 KiB
Go

package mk2driver
import "time"
type Led int
const (
LedMain Led = iota
LedAbsorption
LedBulk
LedFloat
LedInverter
LedOverload
LedLowBattery
LedTemperature
)
var LedNames = map[Led]string{
LedTemperature: "led_over_temp",
LedLowBattery: "led_bat_low",
LedOverload: "led_overload",
LedInverter: "led_inverter",
LedFloat: "led_float",
LedBulk: "led_bulk",
LedAbsorption: "led_absorb",
LedMain: "led_mains",
}
type LEDstate int
const (
LedOff LEDstate = iota
LedOn
LedBlink
)
var StateNames = map[LEDstate]string{
LedOff: "off",
LedOn: "on",
LedBlink: "blink",
}
type Mk2Info struct {
// Will be marked as false if an error is detected.
Valid bool
Version uint32
BatVoltage float64
// Positive current == charging
// Negative current == discharging
BatCurrent float64
// Input AC parameters
InVoltage float64
InCurrent float64
InFrequency float64
// Output AC parameters
OutVoltage float64
OutCurrent float64
OutFrequency float64
// Charge state 0.0 to 1.0
ChargeState float64
// List LEDs
LEDs map[Led]LEDstate
Errors []error
Timestamp time.Time
}
type Mk2 interface {
C() chan *Mk2Info
Close()
}
type PanelSwitchState byte
const (
// PanelSwitchChargerOnly enables charging only.
PanelSwitchChargerOnly PanelSwitchState = 0x01
// PanelSwitchInverterOnly enables inverter output and disables charging.
PanelSwitchInverterOnly PanelSwitchState = 0x02
// PanelSwitchOn enables both inverter and charger.
PanelSwitchOn PanelSwitchState = 0x03
// PanelSwitchOff disables inverter and charger.
PanelSwitchOff PanelSwitchState = 0x04
)
type SettingsWriter interface {
// WriteRAMVar writes a signed 16-bit value to a RAM variable id.
WriteRAMVar(id uint16, value int16) error
// WriteSetting writes a signed 16-bit value to a setting id.
WriteSetting(id uint16, value int16) error
// SetPanelState sends the MK2 "S" command using a virtual panel switch state.
// If currentLimitA is nil, the command does not update the AC current limit.
SetPanelState(switchState PanelSwitchState, currentLimitA *float64) error
// SetStandby configures the remote panel standby line.
// When enabled, the inverter is prevented from sleeping while switched off.
SetStandby(enabled bool) error
}
type DeviceState byte
const (
// DeviceStateChargerOnly enables charging only.
DeviceStateChargerOnly DeviceState = 0x02
// DeviceStateInverterOnly enables inverter output and disables charging.
DeviceStateInverterOnly DeviceState = 0x03
// DeviceStateOn enables both inverter and charger.
DeviceStateOn DeviceState = 0x04
// DeviceStateOff disables inverter and charger.
DeviceStateOff DeviceState = 0x05
)
var DeviceStateNames = map[DeviceState]string{
DeviceStateChargerOnly: "charger_only",
DeviceStateInverterOnly: "inverter_only",
DeviceStateOn: "on",
DeviceStateOff: "off",
}
type RAMVarInfo struct {
ID uint16
Scale int16
Offset int16
Factor float64
Signed bool
Supported bool
}
// ProtocolControl exposes protocol 3.14 command paths for direct MK2 control.
type ProtocolControl interface {
SettingsWriter
// GetDeviceState returns the current VE.Bus state using command 0x0E.
GetDeviceState() (DeviceState, error)
// SetDeviceState sets the VE.Bus state using command 0x0E.
SetDeviceState(state DeviceState) error
// ReadRAMVarByID reads a RAM variable via command 0x30.
ReadRAMVarByID(id uint16) (int16, error)
// ReadSettingByID reads a setting via command 0x31.
ReadSettingByID(id uint16) (int16, error)
// SelectRAMVar selects a RAM variable for follow-up read-selected/write-selected paths.
SelectRAMVar(id uint16) error
// SelectSetting selects a setting for follow-up read-selected/write-selected paths.
SelectSetting(id uint16) error
// ReadSelected reads the currently selected value via command 0x35.
ReadSelected() (int16, error)
// ReadRAMVarInfo reads RAM variable metadata via command 0x36.
ReadRAMVarInfo(id uint16) (RAMVarInfo, error)
// WriteSelectedData writes to the currently selected register via command 0x34.
WriteSelectedData(value int16) error
// WriteSettingBySelection performs 0x33 (select setting) followed by 0x34 (write data).
WriteSettingBySelection(id uint16, value int16) error
// WriteRAMVarBySelection performs 0x32 (select RAM var) followed by 0x34 (write data).
WriteRAMVarBySelection(id uint16, value int16) error
// WriteSettingByID writes a setting via command 0x37.
WriteSettingByID(id uint16, value int16) error
// WriteRAMVarByID writes a RAM variable via command 0x38.
WriteRAMVarByID(id uint16, value int16) error
}
type RegisterKind string
const (
RegisterKindSetting RegisterKind = "setting"
RegisterKindRAMVar RegisterKind = "ram_var"
)
type RegisterSafetyClass string
const (
// RegisterSafetyReadOnly indicates no write path should be exposed.
RegisterSafetyReadOnly RegisterSafetyClass = "read_only"
// RegisterSafetyOperational indicates normal runtime write usage is expected.
RegisterSafetyOperational RegisterSafetyClass = "operational"
// RegisterSafetyGuarded indicates writes should be policy-guarded.
RegisterSafetyGuarded RegisterSafetyClass = "guarded"
// RegisterSafetyCritical indicates high-impact settings that need stricter controls.
RegisterSafetyCritical RegisterSafetyClass = "critical"
)
type TimeoutClass string
const (
TimeoutClassFast TimeoutClass = "fast"
TimeoutClassStandard TimeoutClass = "standard"
TimeoutClassSlow TimeoutClass = "slow"
)
// RegisterMetadata documents known MK2 register IDs and expected value behavior.
type RegisterMetadata struct {
Kind RegisterKind
ID uint16
Name string
Description string
Unit string
Scale float64
Writable bool
Signed bool
MinValue *int16
MaxValue *int16
SafetyClass RegisterSafetyClass
}
// TransactionOptions controls retry and verification semantics for safe writes.
type TransactionOptions struct {
// Retries is the number of additional write attempts after the first try.
Retries int
// RetryDelay is slept between retries. Zero uses a sensible default.
RetryDelay time.Duration
// BackoffFactor multiplies retry delay for each additional attempt (1 disables backoff).
BackoffFactor float64
// ReadBeforeWrite captures previous value before writing when possible.
ReadBeforeWrite bool
// VerifyAfterWrite reads the register back and compares with written value.
VerifyAfterWrite bool
// TimeoutClass applies standard timeout buckets when CommandTimeout is not set.
TimeoutClass TimeoutClass
// CommandTimeout overrides timeout class for each protocol command inside the transaction.
CommandTimeout time.Duration
}
// RegisterTransactionResult reports details about a transactional register write.
type RegisterTransactionResult struct {
Kind RegisterKind
ID uint16
TargetValue int16
PreviousValue *int16
VerifiedValue *int16
Attempts int
Timeout time.Duration
Duration time.Duration
}
// MetadataControl adds register metadata and transactional safety helpers.
type MetadataControl interface {
ProtocolControl
// RegisterMetadata returns metadata for a known register.
RegisterMetadata(kind RegisterKind, id uint16) (RegisterMetadata, bool)
// ListRegisterMetadata returns all known register metadata.
ListRegisterMetadata() []RegisterMetadata
// ReadRegister reads a setting or RAM var by kind and id.
ReadRegister(kind RegisterKind, id uint16) (int16, error)
// WriteRegister performs a safe transactional write with optional retry/verify.
WriteRegister(kind RegisterKind, id uint16, value int16, opts TransactionOptions) (RegisterTransactionResult, error)
}
type RegisterAddress struct {
Kind RegisterKind `json:"kind"`
ID uint16 `json:"id"`
}
type RegisterSnapshotEntry struct {
Kind RegisterKind `json:"kind"`
ID uint16 `json:"id"`
Name string `json:"name,omitempty"`
Value int16 `json:"value"`
Writable bool `json:"writable"`
Safety RegisterSafetyClass `json:"safety_class,omitempty"`
CapturedAt time.Time `json:"captured_at"`
}
type RegisterSnapshot struct {
CapturedAt time.Time `json:"captured_at"`
Entries []RegisterSnapshotEntry `json:"entries"`
}
type SnapshotDiff struct {
Kind RegisterKind `json:"kind"`
ID uint16 `json:"id"`
Name string `json:"name,omitempty"`
Current int16 `json:"current"`
Target int16 `json:"target"`
Changed bool `json:"changed"`
Writable bool `json:"writable"`
Safety RegisterSafetyClass `json:"safety_class,omitempty"`
DiffValue int32 `json:"diff_value"`
}
type SnapshotRestoreResult struct {
Applied []RegisterTransactionResult `json:"applied"`
RolledBack bool `json:"rolled_back"`
RollbackErrors []string `json:"rollback_errors,omitempty"`
}
// SnapshotControl provides register snapshot, diff preview, and rollback-aware restore.
type SnapshotControl interface {
MetadataControl
// CaptureSnapshot reads the provided register list. Empty addresses captures known writable registers.
CaptureSnapshot(addresses []RegisterAddress) (RegisterSnapshot, error)
// DiffSnapshot compares current values against a snapshot.
DiffSnapshot(snapshot RegisterSnapshot) ([]SnapshotDiff, error)
// RestoreSnapshot applies snapshot target values; if restore fails mid-way it attempts rollback.
RestoreSnapshot(snapshot RegisterSnapshot, opts TransactionOptions) (SnapshotRestoreResult, error)
}
type TraceDirection string
const (
TraceDirectionTX TraceDirection = "tx"
TraceDirectionRX TraceDirection = "rx"
)
type ProtocolTrace struct {
Timestamp time.Time `json:"timestamp"`
Direction TraceDirection `json:"direction"`
Frame string `json:"frame"`
Command string `json:"command,omitempty"`
BytesHex string `json:"bytes_hex"`
}
type DriverDiagnostics struct {
GeneratedAt time.Time `json:"generated_at"`
HealthScore int `json:"health_score"`
LastFrameAt *time.Time `json:"last_frame_at,omitempty"`
CommandTimeouts uint64 `json:"command_timeouts"`
CommandFailures uint64 `json:"command_failures"`
ChecksumFailures uint64 `json:"checksum_failures"`
RecentErrors []string `json:"recent_errors,omitempty"`
Traces []ProtocolTrace `json:"traces"`
}
// DiagnosticsControl exposes recent protocol traces and health information for troubleshooting bundles.
type DiagnosticsControl interface {
DriverDiagnostics(limit int) DriverDiagnostics
}
type CommandSource string
const (
CommandSourceUnknown CommandSource = "unknown"
CommandSourceUI CommandSource = "ui"
CommandSourceMQTT CommandSource = "mqtt"
CommandSourceAutomation CommandSource = "automation"
)
// SourceAwareSettingsWriter accepts source tags for arbitration and diagnostics.
type SourceAwareSettingsWriter interface {
SettingsWriter
WriteRAMVarWithSource(source CommandSource, id uint16, value int16) error
WriteSettingWithSource(source CommandSource, id uint16, value int16) error
SetPanelStateWithSource(source CommandSource, switchState PanelSwitchState, currentLimitA *float64) error
SetStandbyWithSource(source CommandSource, enabled bool) error
}
type CommandHistoryProvider interface {
History(limit int) []CommandEvent
}