Skip to content

Commit 510de61

Browse files
andigjoekokker
andauthored
Differentiate SDM220/230 meters (#74)
Co-authored-by: joekokker <[email protected]>
1 parent 9d53a95 commit 510de61

File tree

9 files changed

+208
-59
lines changed

9 files changed

+208
-59
lines changed

assets/index.html

+7
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,13 @@ <h1>Measurements</h1>
358358
<td class="col-3" v-if="pop(m.THD)">${ m.THD }</td>
359359
<td class="col-3" v-else>&mdash;</td>
360360
</tr>
361+
<tr class="d-flex" v-if="populated(m.PhaseAngle)">
362+
<td class="col-3">Phase Angle</td>
363+
<td class="col-2">&mdash;</td>
364+
<td class="col-2">&mdash;</td>
365+
<td class="col-2">&mdash;</td>
366+
<td class="col-3">${ m.PhaseAngle }</td>
367+
</tr>
361368
<tr class="d-flex" v-if="pop(m.Frequency)">
362369
<td class="col-3">Frequency (Hz)</td>
363370
<td class="col-2">&mdash;</td>

docs/mbmd_inspect.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@ mbmd inspect [flags]
2525
INEPRO Inepro Metering Pro 380
2626
JANITZA Janitza B-Series meters
2727
SBC Saia Burgess Controls ALE3 meters
28-
SDM Eastron SDM meters
28+
SDM Eastron SDM630
29+
SDM220 Eastron SDM220
30+
SDM230 Eastron SDM230
2931
TCP
3032
SUNS Sunspec-compatible MODBUS TCP device (SMA, SolarEdge, KOSTAL, etc)
3133
To use an adapter different from default, append RTU device or TCP address separated by @.

docs/mbmd_run.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ mbmd run [flags]
2424
INEPRO Inepro Metering Pro 380
2525
JANITZA Janitza B-Series meters
2626
SBC Saia Burgess Controls ALE3 meters
27-
SDM Eastron SDM meters
27+
SDM Eastron SDM630
28+
SDM220 Eastron SDM220
29+
SDM230 Eastron SDM230
2830
TCP
2931
SUNS Sunspec-compatible MODBUS TCP device (SMA, SolarEdge, KOSTAL, etc)
3032
To use an adapter different from default, append RTU device or TCP address separated by @.

meters/measurement_string.go

+3-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

meters/measurements.go

+3
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,8 @@ const (
138138
// Battery
139139
ChargeState
140140
BatteryVoltage
141+
142+
PhaseAngle
141143
)
142144

143145
var iec = map[Measurement][]string{
@@ -232,6 +234,7 @@ var iec = map[Measurement][]string{
232234
DCEnergyS3: {"String 3 Generation", "kWh"},
233235
ChargeState: {"Charge State", "%"},
234236
BatteryVoltage: {"Battery Voltage", "V"},
237+
PhaseAngle: {"Phase Angle", "°"},
235238
}
236239

237240
// MarshalText implements encoding.TextMarshaler

meters/rs485/sdm.go

+12-12
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,19 @@ type SDMProducer struct {
1616

1717
func NewSDMProducer() Producer {
1818
/**
19-
* Opcodes as defined by Eastron.
19+
* Opcodes as defined by Eastron SDM630.
2020
* See http://bg-etech.de/download/manual/SDM630Register.pdf
21-
* Please note that this is the superset of all SDM devices -
22-
* some opcodes might not work on some devicep.
21+
* This is to a large extent a superset of all SDM devices, however there are
22+
* subtle differences (see 220, 230). Some opcodes might not work on some devices.
2323
*/
2424
ops := Opcodes{
25-
VoltageL1: 0x0000,
25+
VoltageL1: 0x0000, // 220, 230
2626
VoltageL2: 0x0002,
2727
VoltageL3: 0x0004,
28-
CurrentL1: 0x0006,
28+
CurrentL1: 0x0006, // 220, 230
2929
CurrentL2: 0x0008,
3030
CurrentL3: 0x000A,
31-
PowerL1: 0x000C,
31+
PowerL1: 0x000C, // 230
3232
PowerL2: 0x000E,
3333
PowerL3: 0x0010,
3434
Power: 0x0034,
@@ -38,24 +38,24 @@ func NewSDMProducer() Producer {
3838
ImportL1: 0x015a,
3939
ImportL2: 0x015c,
4040
ImportL3: 0x015e,
41-
Import: 0x0048,
41+
Import: 0x0048, // 220, 230
4242
ExportL1: 0x0160,
4343
ExportL2: 0x0162,
4444
ExportL3: 0x0164,
45-
Export: 0x004a,
45+
Export: 0x004a, // 220, 230
4646
SumL1: 0x0166,
4747
SumL2: 0x0168,
4848
SumL3: 0x016a,
49-
Sum: 0x0156,
50-
CosphiL1: 0x001e,
49+
Sum: 0x0156, // 220
50+
CosphiL1: 0x001e, // 230
5151
CosphiL2: 0x0020,
5252
CosphiL3: 0x0022,
5353
Cosphi: 0x003e,
5454
THDL1: 0x00ea, // voltage
5555
THDL2: 0x00ec, // voltage
5656
THDL3: 0x00ee, // voltage
5757
THD: 0x00F8, // voltage
58-
Frequency: 0x0046,
58+
Frequency: 0x0046, // 230
5959
//L1THDCurrent: 0x00F0, // current
6060
//L2THDCurrent: 0x00F2, // current
6161
//L3THDCurrent: 0x00F4, // current
@@ -70,7 +70,7 @@ func (p *SDMProducer) Type() string {
7070
}
7171

7272
func (p *SDMProducer) Description() string {
73-
return "Eastron SDM meters"
73+
return "Eastron SDM630"
7474
}
7575

7676
func (p *SDMProducer) snip(iec Measurement) Operation {

meters/rs485/sdm220.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package rs485
2+
3+
import . "github.com/volkszaehler/mbmd/meters"
4+
5+
func init() {
6+
Register(NewSDM220Producer)
7+
}
8+
9+
const (
10+
METERTYPE_SDM220 = "SDM220"
11+
)
12+
13+
type SDM220Producer struct {
14+
Opcodes
15+
}
16+
17+
func NewSDM220Producer() Producer {
18+
/**
19+
* Opcodes as defined by Eastron SDM220.
20+
* See https://bg-etech.de/download/manual/SDM220StandardDE.pdf
21+
*/
22+
ops := Opcodes{
23+
Voltage: 0x0000, // 220, 230
24+
Current: 0x0006, // 220, 230
25+
Import: 0x0048, // 220, 230
26+
Export: 0x004a, // 220, 230
27+
Sum: 0x0156, // 220, 230
28+
ReactiveSum: 0x0158, // 220
29+
ReactiveImport: 0x4C, // 220, 230
30+
ReactiveExport: 0x4E, // 220, 230
31+
}
32+
return &SDM220Producer{Opcodes: ops}
33+
}
34+
35+
func (p *SDM220Producer) Type() string {
36+
return METERTYPE_SDM220
37+
}
38+
39+
func (p *SDM220Producer) Description() string {
40+
return "Eastron SDM220"
41+
}
42+
43+
func (p *SDM220Producer) snip(iec Measurement) Operation {
44+
operation := Operation{
45+
FuncCode: ReadInputReg,
46+
OpCode: p.Opcode(iec),
47+
ReadLen: 2,
48+
IEC61850: iec,
49+
Transform: RTUIeee754ToFloat64,
50+
}
51+
return operation
52+
}
53+
54+
func (p *SDM220Producer) Probe() Operation {
55+
return p.snip(Voltage)
56+
}
57+
58+
func (p *SDM220Producer) Produce() (res []Operation) {
59+
for op := range p.Opcodes {
60+
res = append(res, p.snip(op))
61+
}
62+
63+
return res
64+
}

meters/rs485/sdm230.go

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package rs485
2+
3+
import . "github.com/volkszaehler/mbmd/meters"
4+
5+
func init() {
6+
Register(NewSDM230Producer)
7+
}
8+
9+
const (
10+
METERTYPE_SDM230 = "SDM230"
11+
)
12+
13+
type SDM230Producer struct {
14+
Opcodes
15+
}
16+
17+
func NewSDM230Producer() Producer {
18+
/**
19+
* Opcodes as defined by Eastron SDM230.
20+
* See https://bg-etech.de/download/manual/SDM230-register.pdf
21+
*/
22+
ops := Opcodes{
23+
Voltage: 0x0000, // 220, 230
24+
Current: 0x0006, // 220, 230
25+
Power: 0x000C, // 230
26+
Import: 0x0048, // 220, 230
27+
Export: 0x004a, // 220, 230
28+
Cosphi: 0x001e, // 230
29+
Frequency: 0x0046, // 230
30+
ReactiveImport: 0x4C, // 220, 230
31+
ReactiveExport: 0x4E, // 220, 230
32+
ApparentPower: 0x0012, // 230
33+
ReactivePower: 0x0018, // 230
34+
Sum: 0x0156, // 230
35+
PhaseAngle: 0x0024, // 230
36+
}
37+
return &SDM230Producer{Opcodes: ops}
38+
}
39+
40+
func (p *SDM230Producer) Type() string {
41+
return METERTYPE_SDM230
42+
}
43+
44+
func (p *SDM230Producer) Description() string {
45+
return "Eastron SDM230"
46+
}
47+
48+
func (p *SDM230Producer) snip(iec Measurement) Operation {
49+
operation := Operation{
50+
FuncCode: ReadInputReg,
51+
OpCode: p.Opcode(iec),
52+
ReadLen: 2,
53+
IEC61850: iec,
54+
Transform: RTUIeee754ToFloat64,
55+
}
56+
return operation
57+
}
58+
59+
func (p *SDM230Producer) Probe() Operation {
60+
return p.snip(Voltage)
61+
}
62+
63+
func (p *SDM230Producer) Produce() (res []Operation) {
64+
for op := range p.Opcodes {
65+
res = append(res, p.snip(op))
66+
}
67+
68+
return res
69+
}

server/assets.go

+44-43
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)