Documentation
¶
Index ¶
- Constants
- Variables
- func FloatWholeUnits(v int64, unit string) (float64, string)
- func ParseRecord(rec map[string]string) map[string]interface{}
- func ParseRecordField(k string, v any) any
- func ParseRecordFieldString(k, v string) any
- func ParsedRecordDeltas(alldata []map[string]interface{}) []map[string]interface{}
- func ParsedRecordRebuild(deltas []map[string]interface{})
- func StringRecordDeltas(batch []map[string]string, deltas []map[string]interface{}, keyframePeriod int) []map[string]interface{}
- type Command
- type Option
- type RecTimeSort
- type RegType
- type StreamingSummary
- func (sum *StreamingSummary) Add(rec map[string]interface{}) error
- func (sum *StreamingSummary) GetData(raw_after int64) []map[string]interface{}
- func (sum *StreamingSummary) GetRawRecent(after int64, limit int) []map[string]interface{}
- func (sum *StreamingSummary) GetSummedRecent(after int64, limit int) []map[string]interface{}
- type VERegValue
- type VERegister
- type Vedirect
Constants ¶
const DefaultBinSeconds = 60
const DefaultKeepCount = 20000
Variables ¶
var DebugEnabled bool = false
var DebugWriter io.Writer = os.Stderr
var ErrHexDataShort = errors.New("VE HEX data too short for desired register")
var ErrHexTypeUnknown = errors.New("VE HEX data not a known register value type")
var ErrNoOutput = errors.New("no output configured")
var ErrNoTime = errors.New("record lacks _t time")
var ErrNotANumber = errors.New("could not convert non-number to int64")
var ErrNotData error = errors.New("VE HEX message is not 07 or 0A data")
var ErrTimeWrongType = errors.New("_t record wrong type not int64")
var IntFields map[string]string
IntFields map field name to unit description (if any).
Some fields will have empty string for unit description.
var OtherFields map[string]bool
OtherFields is a set of known VE.Direct fields that are not int.
isKnownOtherField := vedirect.OtherFields["BLAH"]
var ParseRecordDebug io.Writer
var RegTypeNameToRegType map[string]RegType = map[string]RegType{ "u8": RegType_u8, "u16": RegType_u16, "u32": RegType_u32, "s8": RegType_s8, "s16": RegType_s16, "s32": RegType_s32, "unk": RegType_unk, }
Functions ¶
func FloatWholeUnits ¶
FloatWholeUnits uses the unit string from IntFields to convert some values into float64 of their whole unit. e.g. (10_000, "mV)" -> (10.0, "V")
If there was no conversion, unit returned is same as passed in.
func ParseRecord ¶
ParseRecord will parse some field values to int64
func ParseRecordField ¶
func ParseRecordFieldString ¶
func ParsedRecordDeltas ¶
ParsedRecordDeltas converts records from ParseRecord() into a list of record deltas. The first record has full data and each following record only has fields that changed.
func ParsedRecordRebuild ¶
func ParsedRecordRebuild(deltas []map[string]interface{})
Convert *in-place* deltas into whole records
func StringRecordDeltas ¶
func StringRecordDeltas(batch []map[string]string, deltas []map[string]interface{}, keyframePeriod int) []map[string]interface{}
StringRecordDeltas makes a list of deltas. The first record has all its fields, each record after only has fields that have changed. passed in deltas object is appeneded to, or may be nil. Output records have ParseRecord applied
Types ¶
type RecTimeSort ¶
type RecTimeSort []map[string]interface{}
func (*RecTimeSort) Less ¶
func (rts *RecTimeSort) Less(i, j int) bool
func (*RecTimeSort) Swap ¶
func (rts *RecTimeSort) Swap(i, j int)
type StreamingSummary ¶
type StreamingSummary struct { // BinSeconds is the number of seconds of raw samples to merge BinSeconds int // KeepCount is the number of merged samples to keep KeepCount int // contains filtered or unexported fields }
Merge VE.Direct records based on time (e.g. 1 minute average of 1 second records), keep the most recent N.
Different fields are merged on different rules, some are averaged, some are last-value-wins ¶
BinSeconds * KeepCount is the amonut of total time covered. {BinSeconds:60, KeepCount: 24*60} will merge data into 1 minute bins and keep the most recent 24 hours of data.
func (*StreamingSummary) Add ¶
func (sum *StreamingSummary) Add(rec map[string]interface{}) error
func (*StreamingSummary) GetData ¶
func (sum *StreamingSummary) GetData(raw_after int64) []map[string]interface{}
GetData returns a merged set of data with merged samples before some time and raw samples after.
func (*StreamingSummary) GetRawRecent ¶
func (sum *StreamingSummary) GetRawRecent(after int64, limit int) []map[string]interface{}
get the newest records, up to limit.
after is time.Time.UnixMilli()
func (*StreamingSummary) GetSummedRecent ¶
func (sum *StreamingSummary) GetSummedRecent(after int64, limit int) []map[string]interface{}
get the newest records, up to limit the _t time for a summary is the _last_ time of any sample within the summarized range, thus you can query GetRawRecent after= from a summed _t value
type VERegValue ¶
type VERegValue struct { Register VERegister Value any }
func ParseHexRecord ¶
func ParseHexRecord(x string) (value *VERegValue, err error)
Parse register value from a VE.HEX message. Not fully general, this filters on 0x7 and 0xA messages which are:
- 0x7 response to register get
- 0xA asynchronously volunteered register update
type VERegister ¶
type VERegister struct { Address uint16 `json:"a"` Name string `json:"n"` Scale *float64 `json:"s,omitempty"` Size RegType `json:"f"` Unit string `json:"u,omitempty"` SummaryMode string `json:"m,omitempty"` }
func VE_MPPT_Registers ¶
func VE_MPPT_Registers() []VERegister
func VE_PhoenixInverter_Registers ¶
func VE_PhoenixInverter_Registers() []VERegister
type Vedirect ¶
type Vedirect struct { // AddTime if true will add to each record {"_t": time.Now().UnixMilli()} AddTime bool // contains filtered or unexported fields }
func Open ¶
func Open(path string, out chan<- map[string]string, wg *sync.WaitGroup, ctx context.Context, debugOut io.Writer, options ...Option) (v *Vedirect, err error)
Open a VE.Direct serial device (starts a thread). path is the serial device. out chan receives data. wg may be nil. debugOut may be nil.
func (*Vedirect) SendHexCommand ¶
SendHexCommand sends a HEX protocol command to a VE.Direct device.
If successful, response will come in normal message stream parsed into data["_x"] = "aabbccddeeff"
Parsed HEX messages have their command nybble filled out to a whole byte so that hex.DecodeString(data["_x"]) should work.
Actual message fields vary by length and content and are left to application code, but you might want "encoding/binary" LittleEndian.Uint16([]byte) and .PutUint16([]byte, uint16)