Git Product home page Git Product logo

gosunspec's Introduction

This project is unmaintained. Please see #38

SunSpec tools for Go

This package contains Go data types representing the SunSpec information model. Subpackages implement particular use-cases that rely on this domain model:

  • /core contains the types used by the remainder of the library
  • /smdx contains types that represent (XML) SMDX models defined by the Sunspec specification
  • /generators implements code generators that transform the SMDX models into Go code
  • /models contains 1 generated package for each SMDX model
  • /xml contains utilities for exchanging SunSpec data using the XML format
  • /modbus contains utilities for talking to SunSpec devices via Modbus RTU
  • /server is an example HTTP server that receives SunSpec XML data

Generated code

This package uses typesafe representations of each model type. To avoid excessive manual maintenance, structs for each type of model defined by SunSpec are generated from the SMDX model files. To regenerate this code, first initialise the spec submodule with:

git submodule update --init spec

Then run the generators:

go generate ./models

gosunspec's People

Contributors

andig avatar crabmusket avatar jonseymour avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

Forkers

jonseymour andig

gosunspec's Issues

Cross-block scale factors not supported

Some models like e.g. 160 MPPT apparently define scale factors inside the fixed block and use them out of the repeating block. These "referenced" scale factors are currently not supported.

Example with corresponding modbus data:

--------- Model 160 mppt ---------
-- Definition --
Length: 28 (0x1c words, 0x38 bytes)
Blocks: 2
-- block #0 -
Length: 8
   0    0       DCA_SF          sunssf
   1    0       DCV_SF          sunssf
   2    0       DCW_SF          sunssf
   3    0      DCWH_SF          sunssf
   4    0          Evt          bitfield32
   6    0            N          count
   7    0       TmsPer          uint16
-- block #1 - module
Length: 20
   0    0           ID          uint16
   1    8        IDStr          string
   9    0          DCA A        uint16
  10    0          DCV V        uint16
  11    0          DCW W        uint16
  12    0         DCWH Wh       acc32
  14    0          Tms Secs     uint32
  16    0          Tmp C        int16
  17    0         DCSt          enum16
  18    0        DCEvt          bitfield32
-- Data --
modbus: send 00 22 00 00 00 06 7e 03 9e af 00 08
modbus: recv 00 22 00 00 00 13 7e 03 10 ff ff 00 00 00 02 80 00 ff ff ff ff 00 02 ff ff
    sunssf DCA_SF                     -1
    sunssf DCV_SF                      0
    sunssf DCW_SF                      2
    sunssf DCWH_SF                -32768
bitfield32 Evt                4294967295
     count N                           2
    uint16 TmsPer                  65535        NaN
modbus: send 00 23 00 00 00 06 7e 03 9e b7 00 14
modbus: recv 00 23 00 00 00 2b 7e 03 28 00 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 04 01 a5 00 02 00 00 00 00 ff ff ff ff 80 00 ff ff ff ff ff ff
    uint16 ID                          1       1.00
    string IDStr
    uint16 DCA                         4       4.00
    uint16 DCV                       421     421.00
    uint16 DCW                         2       2.00
     acc32 DCWH                        0       0.00
    uint32 Tms                4294967295        NaN
     int16 Tmp                    -32768        NaN
    enum16 DCSt                    65535
bitfield32 DCEvt              4294967295
modbus: send 00 24 00 00 00 06 7e 03 9e cb 00 14
modbus: recv 00 24 00 00 00 2b 7e 03 28 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 01 98 00 01 00 00 00 00 ff ff ff ff 80 00 ff ff ff ff ff ff
    uint16 ID                          2       2.00
    string IDStr
    uint16 DCA                         2       2.00
    uint16 DCV                       408     408.00
    uint16 DCW                         1       1.00
     acc32 DCWH                        0       0.00
    uint32 Tms                4294967295        NaN
     int16 Tmp                    -32768        NaN
    enum16 DCSt                    65535

Notice how e.g. DCA is not scaled by 10^-1 and how the power is not amps x volts.

Reading model 11 points broken on SMA inverter

I'm trying to loop through all devices/blocks/models in a simple way:

in.Do(func(d sunspec.Device) {
	d.Do(func(m sunspec.Model) {
		log.Printf("--------- Model %d ---------", m.Id())

		m.Do(func(b sunspec.Block) {
			err = b.Read()
			if err != nil {
				log.Fatal(err)
			}

			b.Do(func(p sunspec.Point) {
				t := p.Type()[0:3]
				v := ""
				if t == "int" || t == "uin" || t == "acc" {
					v = fmt.Sprintf("%.2f", p.ScaledValue())
				}
				log.Printf("%10s %-16s %8v %10s", p.Type(), p.Id(), p.Value(), v)
			})
		})
	})
})

On various SMA inverters this breaks on model 11 even before the points are read:

2019/06/13 19:19:54 --------- Model 1 ---------
2019/06/13 19:19:54 modbus: send 00 14 00 00 00 06 7e 03 9c 44 00 42
2019/06/13 19:19:54 modbus: recv 00 14 00 00 00 87 7e 03 84 53 4d 41 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 53 6f 6c 61 72 20 49 6e 76 65 72 74 65 72 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 39 30 37 36 00 00 00 00 00 00 00 00 00 00 00 00 34 32 30 30 38 38 33 36 00 00 00 00 00 00 00 00 32 31 33 30 30 33 38 39 34 34 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff 80 00
2019/06/13 19:19:54     string Mn                    SMA           
2019/06/13 19:19:54     string Md               Solar Inverter           
2019/06/13 19:19:54     string Opt                  9076           
2019/06/13 19:19:54     string Vr               42008836           
2019/06/13 19:19:54     string SN               2130038944           
2019/06/13 19:19:54     uint16 DA                  65535   65535.00
2019/06/13 19:19:54        pad Pad                 32768           
2019/06/13 19:19:54 --------- Model 11 ---------
2019/06/13 19:19:54 modbus: send 00 15 00 00 00 06 7e 03 9c 88 00 06
2019/06/13 19:19:54 modbus: recv 00 15 00 00 00 03 7e 83 02
2019/06/13 19:19:54 modbus: exception '2' (illegal data address), function '131'
exit status 1

If I skip model 11 reading continues just fine.

Handle multiple devices per modbus address space.

I have come across a device that lays out in sequence multiple devices, each with their own common block, in the modbus address space. AFAICT, this situation wasn't explicitly anticipated within the Sunspec specifications themselves but otherwise seems sane.

There is only one instance of the "SunS" eye catcher at the start of the map.

The API can probably handle this case using the Array abstraction, but the memory implementation will need to be updated to cater for it.

Is this repo dead?

ping @crabmusket @jonseymour I realize the last commit to this repo is already two years old. The codebase looks great gut is in some parts beyond my skill or my modbus/sunspec expertise.

Are these issues (and one PR) something you'd still consider looking into?

Carry strings from smdx models into go

The smdx models contain a lot of labels and descriptions, e.g. model names, that are currently lost in the conversion.

It would be nice to add these to the trget data model and enhance the generation process to populate these.

slice bounds out of range panic when unmarshalling common block

Only today I've stumbled on this excellent codebase after working on mbmd for quite some time. I really love it!

However I've stumbled across a problem. This happens when parsing the address space of a grid inverter like this:

in.Do(func(d sunspec.Device) {
	d.Do(func(m sunspec.Model) {
		log.Println(m.Id())

		m.Do(func(b sunspec.Block) {
			err = b.Read()
			if err != nil {
				log.Fatal(err)
			}
			log.Println(b)
		})
	})
})
panic: runtime error: slice bounds out of range

goroutine 1 [running]:
github.com/crabmusket/gosunspec/impl.(*point).Unmarshal(0xc0000b0280, 0xc00020a050, 0x10, 0x34, 0xc00020812e, 0x0)
        /Users/andig/htdocs/go/pkg/mod/github.com/crabmusket/[email protected]/impl/point.go:496 +0x12e1
github.com/crabmusket/gosunspec/modbus.(*modbusDriver).Read(0xc0000ae6a0, 0x11b9fc0, 0xc0001a8200, 0x0, 0x0, 0x0, 0x0, 0xc000042d88)
        /Users/andig/htdocs/go/pkg/mod/github.com/crabmusket/[email protected]/modbus/modbus.go:156 +0x656
github.com/crabmusket/gosunspec/impl.(*block).Read(0xc0001a8200, 0x0, 0x0, 0x0, 0x13b2d98, 0x0)
        /Users/andig/htdocs/go/pkg/mod/github.com/crabmusket/[email protected]/impl/block.go:54 +0x63
main.main.func1.1.1(0x11b8120, 0xc0001a8200)
        /Users/andig/htdocs/mbmd/cmd/scan/main.go:90 +0x4f

This is inside https://github.com/crabmusket/gosunspec/blob/master/impl/point.go#L487, the panic happens right at the first Common block.

I've added some logging to Unmarshal to see what actually goes in (would be nice if a block allowed to "dump" its contents to simplify this):

2019/06/12 20:52:18 {XMLName:{Space: Local:} Id:Mn Offset:0 Length:16 Type:string ScaleFactor: Units: Mandatory:true Access: Symbols:[]}
2019/06/12 20:52:18 Unmarshal: 53 6f 6c 61 72 45 64 67 65 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2019/06/12 20:52:18 {XMLName:{Space: Local:} Id:Md Offset:16 Length:16 Type:string ScaleFactor: Units: Mandatory:true Access: Symbols:[]}
2019/06/12 20:52:18 Unmarshal: 53 45 33 30 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2019/06/12 20:52:18 {XMLName:{Space: Local:} Id:Opt Offset:32 Length:8 Type:string ScaleFactor: Units: Mandatory:false Access: Symbols:[]}
2019/06/12 20:52:18 Unmarshal: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
2019/06/12 20:52:18 {XMLName:{Space: Local:} Id:Vr Offset:40 Length:8 Type:string ScaleFactor: Units: Mandatory:false Access: Symbols:[]}
2019/06/12 20:52:18 Unmarshal: 30 30 30 33 2e 32 31 38 36 00 00 00 00 00 00 00

I think b should actually be copied from bytes which is longer than b as b is only initialized with the length of the point and will fail if the string uses all characters of the point:

			b = bytes[0:i]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.