66 "fmt"
77 "io"
88 "os"
9+ "strings"
910 "time"
1011)
1112
@@ -15,6 +16,7 @@ type ElectricUsage struct {
1516 EndTime time.Time
1617 WattHours int64
1718 CostInCents * int64
19+ MeterName * string
1820}
1921
2022// Response holds the parsed response from the SmartHub poll api.
@@ -35,6 +37,7 @@ type SmartHubData struct {
3537// SmartHubSeries holds parsed response data from the SmartHub poll api.
3638// It holds a list of SmartHubPoints.
3739type SmartHubSeries struct {
40+ Name string `json:"name"`
3841 Data []SmartHubPoint `json:"data"`
3942}
4043
@@ -94,13 +97,13 @@ func ParseReader(readCloser io.ReadCloser) ([]ElectricUsage, error) {
9497 if ! ok {
9598 return nil , errors .New ("no ELECTRIC key" )
9699 }
97- var usageSeries , costSeries []SmartHubPoint
100+ var usageData , costData []SmartHubSeries
98101 for _ , data := range datas {
99102 switch data .Type {
100103 case "USAGE" :
101- usageSeries = data .Series [ 0 ]. Data
104+ usageData = data .Series
102105 case "COST" :
103- costSeries = data .Series [ 0 ]. Data
106+ costData = data .Series
104107 }
105108 }
106109 // this is dumb, but the SmartHub api returns "unix timestamps"
@@ -112,20 +115,42 @@ func ParseReader(readCloser io.ReadCloser) ([]ElectricUsage, error) {
112115 return nil , err
113116 }
114117 _ , offset := time .Now ().In (zone ).Zone ()
115- period := time .UnixMilli (usageSeries [1 ].UnixMillis ).Sub (time .UnixMilli (usageSeries [0 ].UnixMillis ))
116- records := make ([]ElectricUsage , len (usageSeries ))
117- for i := range usageSeries {
118- usage := usageSeries [i ]
119- // see note above about "unix timestamps"
120- start := time .UnixMilli (usage .UnixMillis ).Add (time .Second * time .Duration (- offset ))
121- records [i ].StartTime = start
122- records [i ].EndTime = start .Add (period )
123- records [i ].WattHours = int64 (usage .Value * 1000 )
124- }
125- // note: cost is not returned by all SmartHub implementations. So this is a no-op sometimes.
126- for i := range costSeries {
127- cost := int64 (costSeries [i ].Value * 100 )
128- records [i ].CostInCents = & cost
118+
119+ seriesCount := len (usageData )
120+ dataCount := len (usageData [0 ].Data )
121+ records := make ([]ElectricUsage , seriesCount * dataCount )
122+ for i := range usageData {
123+ meterName := parseName (usageData [i ].Name , seriesCount )
124+ usageSeries := usageData [i ].Data
125+ period := time .UnixMilli (usageSeries [1 ].UnixMillis ).Sub (time .UnixMilli (usageSeries [0 ].UnixMillis ))
126+ for j := range usageSeries {
127+ usage := usageSeries [j ]
128+ index := j + (i * dataCount )
129+ // see note above about "unix timestamps"
130+ start := time .UnixMilli (usage .UnixMillis ).Add (time .Second * time .Duration (- offset ))
131+ records [index ].StartTime = start
132+ records [index ].EndTime = start .Add (period )
133+ records [index ].WattHours = int64 (usage .Value * 1000 )
134+ records [index ].MeterName = meterName
135+ }
136+ // note: cost is not returned by all SmartHub implementations.
137+ if len (costData ) > i {
138+ costSeries := costData [i ].Data
139+ for j := range costSeries {
140+ cost := int64 (costSeries [j ].Value * 100 )
141+ records [j + (i * dataCount )].CostInCents = & cost
142+ }
143+ }
129144 }
130145 return records , nil
131146}
147+
148+ // parseName returns the last part of a string after a space. If seriesCount is 1, returns nil.
149+ func parseName (name string , seriesCount int ) * string {
150+ var result * string
151+ if seriesCount > 1 {
152+ tokens := strings .Split (name , " " )
153+ result = & tokens [len (tokens )- 1 ]
154+ }
155+ return result
156+ }
0 commit comments