/
pgService.go
160 lines (129 loc) · 5.99 KB
/
pgService.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
package services
import (
"encoding/json"
"fmt"
"math/rand"
"strings"
"github.com/amine-amaach/simulators/pgmqtt/services/models"
"github.com/amine-amaach/simulators/pgmqtt/utils"
"github.com/bxcodec/faker/v3"
"go.uber.org/zap"
)
type pgService struct{}
func NewService(pGenerators []models.Generator, cfg *utils.Config, pgNumber int) *pgService {
pgSvc := pgService{}
pgSvc.BuildPowerGenerators(pGenerators, cfg, pgNumber)
return &pgSvc
}
// MakeMessagePayload generates random data for a given power-generator and
// returns a map contains its topics with corresponding message payloads.
func (svc *pgService) BuildPGMessagePayloads(sim *SimService, pg *models.Generator, logger *zap.SugaredLogger) map[string]json.RawMessage {
type pgPayload struct {
Name string
Lat float32
Lon float32
BaseFuel float32
}
msgPayloads := make(map[string]json.RawMessage, 1)
// Add power-generator general infos that gets published once.
jsonBytes, err := json.Marshal(pgPayload{Name: pg.GeneratorID, Lat: pg.Lat, Lon: pg.Lon, BaseFuel: pg.Base_fuel.ItemValue.(float32)})
if err != nil {
logger.Errorf("Couldn't marshal message payload ❌ %v", err)
} else {
msgPayloads[pg.GeneratorTopic] = jsonBytes
}
return msgPayloads
}
// Update used to update the power-generator tags message payload and republish it.
func (svc *pgService) Update(sim *SimService, pg *models.Generator, logger *zap.SugaredLogger) map[string]json.RawMessage {
msgPayloads := make(map[string]json.RawMessage, 5)
// For each tag of the generator encode its message payload
// As we don't have a lot of tags, it is fine to do it by hand.
// In case we have a lot of tags we should convert the pg struct
// to an iterable type.
marshalLoad(sim, pg, msgPayloads, logger)
marshalTemperature(sim, pg, msgPayloads, logger)
marshalPower(sim, pg, msgPayloads, logger)
marshalCurrentFuel(sim, pg, msgPayloads, logger)
marshalFuelUsed(sim, pg, msgPayloads, logger)
// In case there is an error, we return the map with the encoded
// payloads. The map could be empty in case all the encoding failed.
return msgPayloads
}
// BuildPowerGenerators returns a slice of power-generators of length nb.
func (svc *pgService) BuildPowerGenerators(pGenerators []models.Generator, cfg *utils.Config, nb int) {
for i := 0; i < nb; i++ {
svc.initPG(&pGenerators[i], i+1)
svc.buildPublishTopicString(&pGenerators[i], cfg)
}
}
// initPG() initializes a power-generator instance.
func (svc *pgService) initPG(pg *models.Generator, pgNumber int) {
baseFuel := float32(900. + rand.Float32() + 9.)
pg.GeneratorID = "Generator_" + fmt.Sprint(pgNumber)
pg.Lat = float32(faker.Latitude())
pg.Lon = float32(faker.Latitude())
pg.Load = models.NewMessage(0, "Load", fmt.Sprint(faker.UnixTime()), "INT")
pg.Temperature = models.NewMessage(float32(0.), "Temperature", fmt.Sprint(faker.UnixTime()), "FLOAT32")
pg.Power = models.NewMessage(float32(0.), "Power", fmt.Sprint(faker.UnixTime()), "FLOAT32")
pg.CurrentFuel = models.NewMessage(float32(0.), "Fuel", fmt.Sprint(faker.UnixTime()), "FLOAT32")
pg.Fuel_used = models.NewMessage(float32(0.), "FuelUsed", fmt.Sprint(faker.UnixTime()), "FLOAT32")
pg.Base_fuel = models.NewMessage(baseFuel, "BaseFuel", fmt.Sprint(faker.UnixTime()), "FLOAT32")
{
pg.Base_fuel.ItemOldValue = baseFuel
}
}
// buildPublishTopicString() builds a power-generator publish topics.
func (svc *pgService) buildPublishTopicString(g *models.Generator, cfg *utils.Config) {
rootTopic := strings.Join([]string{cfg.Site, cfg.Area, "Power_Generators"}, "/")
g.GeneratorTopic = strings.Join([]string{rootTopic, g.GeneratorID}, "/")
g.Load.ItemTopic = strings.Join([]string{rootTopic, g.GeneratorID, g.Load.ItemName}, "/")
g.Temperature.ItemTopic = strings.Join([]string{rootTopic, g.GeneratorID, g.Temperature.ItemName}, "/")
g.Power.ItemTopic = strings.Join([]string{rootTopic, g.GeneratorID, g.Power.ItemName}, "/")
g.CurrentFuel.ItemTopic = strings.Join([]string{rootTopic, g.GeneratorID, g.CurrentFuel.ItemName}, "/")
g.Base_fuel.ItemTopic = strings.Join([]string{rootTopic, g.GeneratorID, g.Base_fuel.ItemName}, "/")
g.Fuel_used.ItemTopic = strings.Join([]string{rootTopic, g.GeneratorID, g.Fuel_used.ItemName}, "/")
}
// marshXXX() used to return the JSON encoding of a message payload.
func marshalTemperature(sim *SimService, pg *models.Generator, msgPayloads map[string]json.RawMessage, logger *zap.SugaredLogger) {
sim.SetTemperature(pg)
if jsonBytes, err := json.Marshal(pg.Temperature); err != nil {
logger.Errorf("Couldn't marshal message payload ❌ %v", err)
} else {
msgPayloads[pg.Temperature.ItemTopic] = jsonBytes
}
}
func marshalPower(sim *SimService, pg *models.Generator, msgPayloads map[string]json.RawMessage, logger *zap.SugaredLogger) {
sim.SetPower(pg)
if jsonBytes, err := json.Marshal(pg.Power); err != nil {
logger.Errorf("Couldn't marshal message payload ❌ %v", err)
} else {
msgPayloads[pg.Power.ItemTopic] = jsonBytes
}
}
func marshalLoad(sim *SimService, pg *models.Generator, msgPayloads map[string]json.RawMessage, logger *zap.SugaredLogger) {
sim.SetLoad(pg)
if jsonBytes, err := json.Marshal(pg.Load); err != nil {
logger.Errorf("Couldn't marshal message payload ❌ %v", err)
} else {
msgPayloads[pg.Load.ItemTopic] = jsonBytes
}
}
func marshalCurrentFuel(sim *SimService, pg *models.Generator, msgPayloads map[string]json.RawMessage, logger *zap.SugaredLogger) {
sim.SetFuelLevel(pg)
if jsonBytes, err := json.Marshal(pg.CurrentFuel); err != nil {
logger.Errorf("Couldn't marshal message payload ❌ %v", err)
} else {
msgPayloads[pg.CurrentFuel.ItemTopic] = jsonBytes
}
}
func marshalFuelUsed(sim *SimService, pg *models.Generator, msgPayloads map[string]json.RawMessage, logger *zap.SugaredLogger) {
// Fuel used is updated when calling SetFuelLevel()
// SetFuelUsed updates old values.
sim.SetFuelUsed(pg)
if jsonBytes, err := json.Marshal(pg.Fuel_used); err != nil {
logger.Errorf("Couldn't marshal message payload ❌ %v", err)
} else {
msgPayloads[pg.Fuel_used.ItemTopic] = jsonBytes
}
}