• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wirenboard / wb-mqtt-serial / 2

29 Dec 2025 12:28PM UTC coverage: 76.817% (+4.0%) from 72.836%
2

Pull #1045

github

54aa0c
pgasheev
up changelog
Pull Request #1045: Fix firmware version in WB-M1W2 template

6873 of 9161 branches covered (75.02%)

12966 of 16879 relevant lines covered (76.82%)

1651.61 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

99.3
/test/mercury230_test.cpp
1
#include "devices/mercury230_device.h"
2
#include "fake_serial_port.h"
3
#include "mercury230_expectations.h"
4
#include <string>
5

6
class TMercury230Test: public TSerialDeviceTest, public TMercury230Expectations
7
{
8
protected:
9
    void SetUp();
10
    void VerifyEnergyQuery();
11
    void VerifyParamQuery();
12

13
    virtual PDeviceConfig GetDeviceConfig() const;
14

15
    PMercury230Device Mercury230Dev;
16

17
    PRegister Mercury230TotalReactiveEnergyReg;
18
    PRegister Mercury230TotalConsumptionReg;
19
    PRegister Mercury230PReg;
20
    PRegister Mercury230P1Reg;
21
    PRegister Mercury230P2Reg;
22
    PRegister Mercury230P3Reg;
23
    PRegister Mercury230QReg;
24
    PRegister Mercury230Q1Reg;
25
    PRegister Mercury230Q2Reg;
26
    PRegister Mercury230Q3Reg;
27
    PRegister Mercury230U1Reg;
28
    PRegister Mercury230U2Reg;
29
    PRegister Mercury230U3Reg;
30
    PRegister Mercury230I1Reg;
31
    PRegister Mercury230I2Reg;
32
    PRegister Mercury230I3Reg;
33
    PRegister Mercury230FrequencyReg;
34
    PRegister Mercury230PFReg;
35
    PRegister Mercury230PF1Reg;
36
    PRegister Mercury230PF2Reg;
37
    PRegister Mercury230PF3Reg;
38
    PRegister Mercury230KU1Reg;
39
    PRegister Mercury230KU2Reg;
40
    PRegister Mercury230KU3Reg;
41
    PRegister Mercury230TempReg;
42
};
43

44
PDeviceConfig TMercury230Test::GetDeviceConfig() const
10✔
45
{
46
    return std::make_shared<TDeviceConfig>("mercury230", std::to_string(0x00), "mercury230");
20✔
47
}
48

49
void TMercury230Test::SetUp()
10✔
50
{
51
    TSerialDeviceTest::SetUp();
10✔
52

53
    Mercury230Dev = std::make_shared<TMercury230Device>(GetDeviceConfig(), DeviceFactory.GetProtocol("mercury230"));
10✔
54
    Mercury230TotalConsumptionReg =
55
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_VALUE_ARRAY, 0x00, U32));
10✔
56
    TRegisterDesc regAddress;
10✔
57
    regAddress.Address = std::make_shared<TUint32RegisterAddress>(0x00);
10✔
58
    regAddress.DataOffset = 2;
10✔
59
    Mercury230TotalReactiveEnergyReg =
60
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_VALUE_ARRAY, regAddress, U32));
10✔
61

62
    Mercury230PReg =
63
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1100, S24));
10✔
64
    Mercury230P1Reg =
65
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1101, S24));
10✔
66
    Mercury230P2Reg =
67
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1102, S24));
10✔
68
    Mercury230P3Reg =
69
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1103, S24));
10✔
70

71
    Mercury230QReg =
72
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_REACT, 0x1104, S24));
10✔
73
    Mercury230Q1Reg =
74
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_REACT, 0x1105, S24));
10✔
75
    Mercury230Q2Reg =
76
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_REACT, 0x1106, S24));
10✔
77
    Mercury230Q3Reg =
78
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_REACT, 0x1107, S24));
10✔
79

80
    Mercury230U1Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1111, U24));
10✔
81
    Mercury230U2Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1112, U24));
10✔
82
    Mercury230U3Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1113, U24));
10✔
83

84
    Mercury230I1Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1121, U24));
10✔
85
    Mercury230I2Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1122, U24));
10✔
86
    Mercury230I3Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1123, U24));
10✔
87

88
    Mercury230FrequencyReg =
89
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1140, U24));
10✔
90

91
    Mercury230PFReg =
92
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1130, S24));
10✔
93
    Mercury230PF1Reg =
94
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1131, S24));
10✔
95
    Mercury230PF2Reg =
96
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1132, S24));
10✔
97
    Mercury230PF3Reg =
98
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_SIGN_ACT, 0x1133, S24));
10✔
99

100
    Mercury230KU1Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1161, U16));
10✔
101
    Mercury230KU2Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1162, U16));
10✔
102
    Mercury230KU3Reg = Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM, 0x1163, U16));
10✔
103

104
    Mercury230TempReg =
105
        Mercury230Dev->AddRegister(TRegisterConfig::Create(TMercury230Device::REG_PARAM_BE, 0x1170, U16));
10✔
106

107
    SerialPort->Open();
10✔
108
}
10✔
109

110
TEST_F(TMercury230Test, ReadEnergy)
16✔
111
{
112
    EnqueueMercury230SessionSetupResponse();
4✔
113
    EnqueueMercury230EnergyResponse1();
4✔
114

115
    // Register address for energy arrays:
116
    // 0000 0000 CCCC CCCC TTTT AAAA MMMM IIII
117
    // C = command (0x05)
118
    // A = array number
119
    // M = month
120
    // T = tariff (FIXME!!! 5 values)
121
    // I = index
122
    // Note: for A=6, 12-byte and not 16-byte value is returned.
123
    // This is not supported at the moment.
124

125
    // Here we make sure that consecutive requests querying the same array
126
    // don't cause redundant requests during the single poll cycle.
127
    ASSERT_EQ(TRegisterValue{3196200},
8✔
128
              Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TotalConsumptionReg->GetConfig()));
129
    ASSERT_EQ(TRegisterValue{300444},
8✔
130
              Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TotalReactiveEnergyReg->GetConfig()));
131
    ASSERT_EQ(TRegisterValue{3196200},
8✔
132
              Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TotalConsumptionReg->GetConfig()));
133
    Mercury230Dev->InvalidateReadCache();
4✔
134

135
    EnqueueMercury230EnergyResponse2();
4✔
136
    ASSERT_EQ(TRegisterValue{3196201},
8✔
137
              Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TotalConsumptionReg->GetConfig()));
138
    ASSERT_EQ(TRegisterValue{300445},
8✔
139
              Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TotalReactiveEnergyReg->GetConfig()));
140
    ASSERT_EQ(TRegisterValue{3196201},
8✔
141
              Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TotalConsumptionReg->GetConfig()));
142
    Mercury230Dev->InvalidateReadCache();
4✔
143
    SerialPort->Close();
4✔
144
}
145

146
void TMercury230Test::VerifyParamQuery()
6✔
147
{
148
    EnqueueMercury230U1Response();
6✔
149
    // Register address for params:
150
    // 0000 0000 CCCC CCCC NNNN NNNN BBBB BBBB
151
    // C = command (0x08)
152
    // N = param number (0x11)
153
    // B = subparam spec (BWRI), 0x11 = voltage, phase 1
154
    ASSERT_EQ(TRegisterValue{24128}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230U1Reg->GetConfig()));
12✔
155

156
    EnqueueMercury230I1Response();
6✔
157
    // subparam 0x21 = current (phase 1)
158
    ASSERT_EQ(TRegisterValue{69}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230I1Reg->GetConfig()));
12✔
159

160
    EnqueueMercury230I2Response();
6✔
161
    // subparam 0x22 = current (phase 2)
162
    ASSERT_EQ(TRegisterValue{96}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230I2Reg->GetConfig()));
12✔
163

164
    EnqueueMercury230U2Response();
6✔
165
    // subparam 0x12 = voltage (phase 2)
166
    ASSERT_EQ(TRegisterValue{24043}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230U2Reg->GetConfig()));
12✔
167

168
    EnqueueMercury230U3Response();
6✔
169
    // subparam 0x12 = voltage (phase 3)
170
    ASSERT_EQ(TRegisterValue{50405}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230U3Reg->GetConfig()));
12✔
171

172
    EnqueueMercury230PResponse();
6✔
173
    // Total power (P)
174
    ASSERT_EQ(TRegisterValue{553095}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230PReg->GetConfig()));
12✔
175

176
    EnqueueMercury230TempResponse();
6✔
177
    ASSERT_EQ(TRegisterValue{24}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230TempReg->GetConfig()));
12✔
178
}
179

180
TEST_F(TMercury230Test, ReadParams)
16✔
181
{
182
    EnqueueMercury230SessionSetupResponse();
4✔
183
    VerifyParamQuery();
4✔
184
    Mercury230Dev->InvalidateReadCache();
4✔
185
    VerifyParamQuery();
4✔
186
    Mercury230Dev->InvalidateReadCache();
4✔
187
    SerialPort->Close();
4✔
188
}
4✔
189

190
TEST_F(TMercury230Test, Reconnect)
16✔
191
{
192
    EnqueueMercury230SessionSetupResponse();
4✔
193
    EnqueueMercury230NoSessionResponse();
4✔
194
    // re-setup happens here
195
    EnqueueMercury230SessionSetupResponse();
4✔
196
    EnqueueMercury230U2Response();
4✔
197

198
    // subparam 0x12 = voltage (phase 2)
199
    ASSERT_EQ(TRegisterValue{24043}, Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230U2Reg->GetConfig()));
8✔
200
    SerialPort->Close();
4✔
201
}
202

203
TEST_F(TMercury230Test, Exception)
16✔
204
{
205
    EnqueueMercury230SessionSetupResponse();
4✔
206
    EnqueueMercury230InternalMeterErrorResponse();
4✔
207
    try {
208
        Mercury230Dev->ReadRegisterImpl(*SerialPort, *Mercury230U2Reg->GetConfig());
8✔
209
        FAIL() << "No exception thrown";
×
210
    } catch (const TSerialDeviceException& e) {
8✔
211
        ASSERT_STREQ("Serial protocol error: Internal meter error", e.what());
4✔
212
        SerialPort->Close();
4✔
213
    }
214
}
215

216
class TMercury230CustomPasswordTest: public TMercury230Test
217
{
218
public:
219
    PDeviceConfig GetDeviceConfig() const override;
220
};
221

222
PDeviceConfig TMercury230CustomPasswordTest::GetDeviceConfig() const
2✔
223
{
224
    PDeviceConfig device_config = TMercury230Test::GetDeviceConfig();
2✔
225
    device_config->Password = {0x12, 0x13, 0x14, 0x15, 0x16, 0x17};
2✔
226
    device_config->AccessLevel = 2;
2✔
227
    return device_config;
2✔
228
}
229

230
TEST_F(TMercury230CustomPasswordTest, Test)
16✔
231
{
232
    EnqueueMercury230AccessLevel2SessionSetupResponse();
4✔
233
    VerifyParamQuery();
4✔
234
    SerialPort->Close();
4✔
235
}
4✔
236

237
class TMercury230IntegrationTest: public TSerialDeviceIntegrationTest, public TMercury230Expectations
238
{
239
protected:
240
    void SetUp() override;
241
    void TearDown() override;
242
    const char* ConfigPath() const override
2✔
243
    {
244
        return "configs/config-mercury230-test.json";
2✔
245
    }
246
    std::string GetTemplatePath() const override
2✔
247
    {
248
        return "device-templates";
4✔
249
    }
250
    void ExpectQueries(bool firstPoll);
251
};
252

253
void TMercury230IntegrationTest::SetUp()
2✔
254
{
255
    TSerialDeviceIntegrationTest::SetUp();
2✔
256
    SerialPort->SetExpectedFrameTimeout(std::chrono::milliseconds(7));
2✔
257
    ASSERT_TRUE(!!SerialPort);
2✔
258
}
259

260
void TMercury230IntegrationTest::TearDown()
2✔
261
{
262
    SerialPort->Close();
2✔
263
    TSerialDeviceIntegrationTest::TearDown();
2✔
264
}
2✔
265

266
void TMercury230IntegrationTest::ExpectQueries(bool firstPoll)
2✔
267
{
268
    if (firstPoll) {
2✔
269
        EnqueueMercury230SessionSetupResponse();
2✔
270
    }
271

272
    EnqueueMercury230EnergyResponse1();
2✔
273

274
    EnqueueMercury230U1Response();
2✔
275
    EnqueueMercury230U2Response();
2✔
276
    EnqueueMercury230U3Response();
2✔
277

278
    EnqueueMercury230I1Response();
2✔
279
    EnqueueMercury230I2Response();
2✔
280
    EnqueueMercury230I3Response();
2✔
281

282
    EnqueueMercury230FrequencyResponse();
2✔
283

284
    EnqueueMercury230KU1Response();
2✔
285
    EnqueueMercury230KU2Response();
2✔
286
    EnqueueMercury230KU3Response();
2✔
287

288
    EnqueueMercury230PResponse();
2✔
289
    EnqueueMercury230P1Response();
2✔
290
    EnqueueMercury230P2Response();
2✔
291
    EnqueueMercury230P3Response();
2✔
292

293
    EnqueueMercury230PFResponse();
2✔
294
    EnqueueMercury230PF1Response();
2✔
295
    EnqueueMercury230PF2Response();
2✔
296
    EnqueueMercury230PF3Response();
2✔
297

298
    EnqueueMercury230QResponse();
2✔
299
    EnqueueMercury230Q1Response();
2✔
300
    EnqueueMercury230Q2Response();
2✔
301
    EnqueueMercury230Q3Response();
2✔
302

303
    EnqueueMercury230TempResponse();
2✔
304
    EnqueueMercury230PerPhaseEnergyResponse();
2✔
305
}
2✔
306

307
TEST_F(TMercury230IntegrationTest, Poll)
16✔
308
{
309
    ExpectQueries(true);
4✔
310
    Note() << "LoopOnce()";
4✔
311
    for (auto i = 0; i < 25; ++i) {
104✔
312
        SerialDriver->LoopOnce();
100✔
313
    }
314
}
4✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc