All checks were successful
continuous-integration/drone/push Build is passing
353 lines
11 KiB
Go
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
|
|
}
|