README
¶
GS2 decoder/encoder
Tool for decoding and encoding data according to the GS2 format (https://sintef.brage.unit.no/sintef-xmlui/handle/11250/2391930).
Current version is mostly forgiving. Mainly because there is a a lot of variation in the applications of this format in pratice.
Inspired by go json decoding/encoding, but does not support custom types as of yet.
Usage
package main
import (
"github.com/rejlersembriq/gs2"
"log"
"os"
)
func main() {
file, _ := os.Open("someGS2File.gs2")
// Decode
g, err := gs2.NewDecoder(file).Decode()
if err != nil {
log.Fatalf("error decoding: %v", err)
}
// Encode
if err = gs2.NewEncoder(file).Encode(g); err != nil {
log.Fatalf("error encoding: %v", err)
}
}
Encoder/Decoder Options
Current options supported:
- Decoder
- DecodeValidators (slice of Validator to be run on GS2 object after decoding)
- Encoder
- EncodeValidators (slice of Validator to be run on GS2 object before encoding)
- EncodeFloatPrecision (sets float precision when encoding floats. Default -1 = auto)
Validator
A validator is simply a function with a pointer to a GS2 object as an argument and an error as a return value.
type Validator func(*GS2) error
If you need some kind of validation that is not already defined you can define your own Validators and add them to the Encoder/Decoder before encoding/decoding. NB: When adding Validators manually remeber to also add the default validators if they are needed. Validators can also be disabled by providing an empty slice.
Example
package main
import (
"fmt"
"github.com/rejlersembriq/gs2"
"log"
"os"
)
func customValidator(g *gs2.GS2) error {
if g.StartMessage.Description == "" {
return fmt.Errorf("startmessage needs a description")
}
return nil
}
func main() {
file, _ := os.Open("someGS2File.gs2")
g := gs2.GS2{}
options := []gs2.EncoderOption{
gs2.EncodeFloatPrecision(4),
gs2.EncodeValidators(
gs2.ValidateNoOfObjects,
gs2.ValidateTimeSeriesValues,
customValidator,
),
}
// Encode
encoder := gs2.NewEncoder(file, options...)
if err := encoder.Encode(&g); err != nil {
log.Fatalf("error encoding: %v", err)
}
}
Documentation
¶
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValidateNoOfObjects ¶
ValidateNoOfObjects validates that the reported number of objects are equal to the actual number of objects in the decoded object.
func ValidateTimeSeriesValues ¶
ValidateTimeSeriesValues validates the number ov values are consistent and that sum og values in a time series block are equal to the sum attribute.
Types ¶
type Decoder ¶
type Decoder struct {
// contains filtered or unexported fields
}
Decoder reads and decodes GS2 input. NB: year, month and day is not supported in Step attribute. Only hour, minute and seconds are used when decoding duration.
func NewDecoder ¶
func NewDecoder(r io.Reader, opt ...DecoderOption) *Decoder
NewDecoder returna a new Decoder reading from r.
type DecoderOption ¶
type DecoderOption func(*decoderOptions)
DecoderOption sets configuration for a Decoder.
func DecodeValidators ¶
func DecodeValidators(v ...Validator) DecoderOption
DecodeValidators sets the validators to be run after decoding an object. Will overwrite the default ones. So remeber to add the defaults as well if needed.
type Encoder ¶
type Encoder struct {
// contains filtered or unexported fields
}
Encoder encodes a GS2 object and writes to an io.Writer. NB: year, month and day is not supported in Step attribute. Only hour, minute and seconds are used when encoding duration.
func NewEncoder ¶
func NewEncoder(w io.Writer, opt ...EncoderOption) *Encoder
NewEncoder returna a new Encoder writing to w.
type EncoderOption ¶
type EncoderOption func(*encoderOptions)
EncoderOption sets configuration for a Encoder.
func EncodeFloatPrecision ¶
func EncodeFloatPrecision(i int) EncoderOption
EncodeFloatPrecision sets precision when encoding floats.
func EncodeValidators ¶
func EncodeValidators(v ...Validator) EncoderOption
EncodeValidators sets the validators to be run before encoding an object. Will overwrite the default ones. So remeber to add the defaults as well if needed.
type EndMessage ¶
type EndMessage struct { ID string `gs2:"Id,omitempty"` MessageType string `gs2:"Message-type,omitempty"` Version string `gs2:"Version,omitempty"` Time time.Time `gs2:"Time,omitempty"` To string `gs2:"To,omitempty"` From string `gs2:"From,omitempty"` ReferenceTable string `gs2:"Reference-table,omitempty"` GMTReference int `gs2:"GMT-reference,omitempty"` NumberOfObjects int `gs2:"Number-of-objects"` TypeOfObjects string `gs2:"Type-of-objects,omitempty"` ContainsObjects string `gs2:"Contains-objects,omitempty"` RequestedAction string `gs2:"Requested-action,omitempty"` Description string `gs2:"Description,omitempty"` }
EndMessage should always be the last object in any GS2-file-
type GS2 ¶
type GS2 struct { StartMessage StartMessage `gs2:"Start-message"` MeterReadings []MeterReading `gs2:"Meter-reading"` TimeSeries []TimeSeries `gs2:"Time-series"` EndMessage EndMessage `gs2:"End-message"` }
GS2 represents the data of a GS2 file.
type MeterReading ¶
type MeterReading struct { Reference string `gs2:"Reference,omitempty"` Time time.Time `gs2:"Time,omitempty"` Unit string `gs2:"Unit,omitempty"` Value Triplet `gs2:"Value"` Installation string `gs2:"Installation,omitempty"` Plant string `gs2:"Plant,omitempty"` MeterLocation string `gs2:"Meter-location,omitempty"` NetOwner string `gs2:"Net-owner,omitempty"` Supplier string `gs2:"Supplier,omitempty"` Customer string `gs2:"Customer,omitempty"` Meter string `gs2:"Meter,omitempty"` Channel string `gs2:"Channel,omitempty"` Description string `gs2:"Description,omitempty"` DirectionOfFlow string `gs2:"Direction-of-flow,omitempty"` }
MeterReading contains a single value that is a channel reading at a given point in time.
type StartMessage ¶
type StartMessage struct { ID string `gs2:"Id,omitempty"` MessageType string `gs2:"Message-type,omitempty"` Version string `gs2:"Version,omitempty"` Time time.Time `gs2:"Time,omitempty"` To string `gs2:"To,omitempty"` From string `gs2:"From,omitempty"` ReferenceTable string `gs2:"Reference-table,omitempty"` GMTReference int `gs2:"GMT-reference,omitempty"` NumberOfObjects int `gs2:"Number-of-objects,omitempty"` TypeOfObjects string `gs2:"Type-of-objects,omitempty"` ContainsObjects string `gs2:"Contains-objects,omitempty"` RequestedAction string `gs2:"Requested-action,omitempty"` Description string `gs2:"Description,omitempty"` }
StartMessage should always be the first object in any GS2-file-
type TimeSeries ¶
type TimeSeries struct { Reference string `gs2:"Reference,omitempty"` Start time.Time `gs2:"Start,omitempty"` Stop time.Time `gs2:"Stop,omitempty"` Step time.Duration `gs2:"Step,omitempty"` Unit string `gs2:"Unit,omitempty"` TypeOfValue string `gs2:"Type-of-value,omitempty"` DirectionOfFlow string `gs2:"Direction-of-flow,omitempty"` Value []Triplet `gs2:"Value,omitempty"` NoOfValues int `gs2:"No-of-values"` Sum float64 `gs2:"Sum"` Installation string `gs2:"Installation,omitempty"` Plant string `gs2:"Plant,omitempty"` MeterLocation string `gs2:"Meter-location,omitempty"` NetOwner string `gs2:"Net-owner,omitempty"` Supplier string `gs2:"Supplier,omitempty"` Customer string `gs2:"Customer,omitempty"` Meter string `gs2:"Meter,omitempty"` Channel string `gs2:"Channel,omitempty"` Description string `gs2:"Description,omitempty"` }
TimeSeries contains time series of metered values within the interval given by start and stop.