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

wirenboard / wb-mqtt-serial / 1

20 Oct 2026 04:57AM UTC coverage: 86.817% (+14.0%) from 72.836%
1

Pull #1281

github

fab311
KraPete
Fix device model fallback in device/LoadConfig RPC

The short model register was never read because the extended register
error was converted to TRPCException. The RPC error now says that
the device model could not be read.
Pull Request #1281: Fix device model fallback in device/LoadConfig RPC

31180 of 80922 branches covered (38.53%)

74 of 76 new or added lines in 2 files covered. (97.37%)

1379 existing lines in 84 files now uncovered.

22464 of 25875 relevant lines covered (86.82%)

5205.91 hits per line

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

78.69
/src/rpc/rpc_config_handler.cpp
1
#include "rpc_config_handler.h"
2
#include "confed_json_generator.h"
3
#include "file_utils.h"
4
#include "json_common.h"
5
#include "log.h"
6
#include "rpc_device_type_json.h"
7
#include "rpc_exception.h"
8
#include "wblib/exceptions.h"
9

10
#ifndef __EMSCRIPTEN__
11
#include "rpc_helpers.h"
12
#endif
13

14
#define LOG(logger) ::logger.Log() << "[RPC] "
15

16
namespace
17
{
18
    const std::string PROTOCOL_PREFIX = "protocol:";
19

20
    struct TDeviceTypeGroup
21
    {
22
        typedef std::vector<PDeviceTemplate> TemplatesArray;
23

24
        std::string Name;
25
        TemplatesArray Templates;
26
    };
27

28
    Json::Value MakeProtocolJson(const TProtocolConfedSchema& schema, const std::string& lang)
180 ✔
29
    {
30
        Json::Value res;
180 ✔
31
        res["name"] = schema.GetTitle(lang);
180 !
32
        res["deprecated"] = false;
180 !
33
        res["type"] = PROTOCOL_PREFIX + schema.Type;
180 !
34
        res["protocol"] = schema.Type;
180 !
35
        res["mqtt-id"] = schema.Type;
180 !
36
        return res;
180 ✔
37
    }
×
38

39
    Json::Value MakeDeviceTypeList(const TDeviceTypeGroup::TemplatesArray& templates, const std::string& lang)
44 ✔
40
    {
41
        Json::Value res(Json::arrayValue);
44 ✔
42
        std::for_each(templates.cbegin(), templates.cend(), [&res, &lang](const auto& t) {
44 !
43
            res.append(MakeDeviceTypeJson(t, lang));
366 !
44
        });
366 ✔
45
        return res;
44 ✔
46
    }
×
47

48
    Json::Value MakeDeviceGroupJson(const TDeviceTypeGroup& group, const std::string& lang)
44 ✔
49
    {
50
        Json::Value res;
44 ✔
51
        res["name"] = group.Name;
44 !
52
        res["types"] = MakeDeviceTypeList(group.Templates, lang);
44 !
53
        return res;
44 ✔
54
    }
×
55

56
    std::vector<Json::Value> GetProtocols(TProtocolConfedSchemasMap& protocolConfedSchemas, const std::string& lang)
12 ✔
57
    {
58
        std::vector<Json::Value> res;
12 ✔
59
        for (const auto& protocolSchema: protocolConfedSchemas.GetSchemas()) {
192 !
60
            res.emplace_back(MakeProtocolJson(protocolSchema.second, lang));
180 !
61
        }
62
        std::sort(res.begin(), res.end(), [](const auto& p1, const auto& p2) {
12 !
63
            return p1["name"].asString() < p2["name"].asString();
612 !
64
        });
65
        return res;
12 ✔
66
    }
×
67

68
    std::vector<TDeviceTypeGroup> OrderTemplates(const std::vector<PDeviceTemplate>& templates,
12 ✔
69
                                                 const Json::Value& groupTranslations,
70
                                                 const std::string& lang)
71
    {
72
        std::map<std::string, std::vector<PDeviceTemplate>> groups;
12 ✔
73
        std::vector<PDeviceTemplate> groupWb;
12 ✔
74
        std::vector<PDeviceTemplate> groupWbOld;
12 ✔
75

76
        for (const auto& templatePtr: templates) {
378 ✔
77
            const auto& group = templatePtr->GetGroup();
366 !
78
            if (group == WB_GROUP_NAME) {
366 !
79
                groupWb.push_back(templatePtr);
×
80
            } else if (group == WB_OLD_GROUP_NAME) {
366 !
81
                groupWbOld.push_back(templatePtr);
×
82
            } else if (group.empty()) {
366 ✔
83
                groups[CUSTOM_GROUP_NAME].push_back(templatePtr);
358 !
84
            } else {
85
                groups[group].push_back(templatePtr);
8 !
86
            }
87
        }
88

89
        auto titleSortFn = [&lang](const auto& t1, const auto& t2) { return t1->GetTitle(lang) < t2->GetTitle(lang); };
2,290 !
90
        std::for_each(groups.begin(), groups.end(), [&](auto& group) {
12 !
91
            std::sort(group.second.begin(), group.second.end(), titleSortFn);
20 ✔
92
        });
20 ✔
93
        std::sort(groupWb.begin(), groupWb.end(), titleSortFn);
12 !
94
        std::sort(groupWbOld.begin(), groupWbOld.end(), titleSortFn);
12 !
95

96
        std::vector<TDeviceTypeGroup> res;
12 ✔
97
        std::transform(groups.begin(), groups.end(), std::back_inserter(res), [&](auto& group) {
12 !
98
            return TDeviceTypeGroup{GetGroupTranslation(group.first, lang, groupTranslations), std::move(group.second)};
80 ✔
99
        });
20 ✔
100

101
        std::sort(res.begin(), res.end(), [](const auto& g1, const auto& g2) { return g1.Name < g2.Name; });
28 !
102
        res.insert(
12 ✔
103
            res.begin(),
12 ✔
104
            TDeviceTypeGroup{GetGroupTranslation(WB_OLD_GROUP_NAME, lang, groupTranslations), std::move(groupWbOld)});
12 !
105
        res.insert(res.begin(),
12 ✔
106
                   TDeviceTypeGroup{GetGroupTranslation(WB_GROUP_NAME, lang, groupTranslations), std::move(groupWb)});
12 !
107
        return res;
12 ✔
108
    }
12 ✔
109
}
110

111
#ifndef __EMSCRIPTEN__
112
TRPCConfigHandler::TRPCConfigHandler(const Json::Value& groupTranslations,
106 ✔
113
                                     TSerialDriverCore& serialDriverCore,
114
                                     WBMQTT::PMqttRpcServer rpcServer)
106 ✔
115
    : ConfigPath(serialDriverCore.GetConfigPath()),
106 ✔
116
      PortsSchema(serialDriverCore.GetPortsSchema()),
106 !
117
      Templates(serialDriverCore.GetTemplates()),
106 !
118
      DeviceConfedSchemas(serialDriverCore.GetDeviceConfedSchemas()),
106 !
119
      ProtocolConfedSchemas(serialDriverCore.GetProtocolConfedSchemas()),
106 !
120
      GroupTranslations(groupTranslations),
106 !
121
      SerialDriverCore(serialDriverCore)
106 ✔
122
{
123
    rpcServer->RegisterMethod("config", "Load", std::bind(&TRPCConfigHandler::LoadConfig, this, std::placeholders::_1));
424 !
124
    rpcServer->RegisterMethod("config",
530 !
125
                              "GetSchema",
126
                              std::bind(&TRPCConfigHandler::GetSchema, this, std::placeholders::_1));
212 !
127
}
106 ✔
128
#else
129
TRPCConfigHandler::TRPCConfigHandler(const Json::Value& portsSchema,
130
                                     PTemplateMap templates,
131
                                     TDevicesConfedSchemasMap& deviceConfedSchemas,
132
                                     TProtocolConfedSchemasMap& protocolConfedSchemas,
133
                                     const Json::Value& groupTranslations)
134
    : PortsSchema(portsSchema),
135
      Templates(templates),
136
      DeviceConfedSchemas(deviceConfedSchemas),
137
      ProtocolConfedSchemas(protocolConfedSchemas),
138
      GroupTranslations(groupTranslations)
139
{}
140
#endif
141

142
Json::Value TRPCConfigHandler::LoadConfig(const Json::Value& request)
16 ✔
143
{
144
#ifndef __EMSCRIPTEN__
145
    if (SerialDriverCore.IsBusy()) {
16 ✔
146
        throw TRPCException(CONFIG_BUSY_ERROR, TRPCResultCode::RPC_WRONG_PARAM_VALUE);
4 !
147
    }
148
#endif
149
    Json::Value res;
12 ✔
150
    res["config"] = MakeJsonForConfed(ConfigPath, *Templates);
12 !
151
    res["schema"] = PortsSchema;
12 !
152
    res["types"] = GetDeviceTypes(request);
12 !
153
    return res;
12 ✔
154
}
×
155

156
Json::Value TRPCConfigHandler::GetDeviceTypes(const Json::Value& request)
12 ✔
157
{
158
    std::string lang(request.get("lang", "en").asString());
12 !
159
    Json::Value res(Json::arrayValue);
12 !
160
    auto templateGroups = OrderTemplates(Templates->GetTemplates(), GroupTranslations, lang);
12 !
161
    auto customGroupName = GetGroupTranslation(CUSTOM_GROUP_NAME, lang, GroupTranslations);
12 !
162
    bool customGroupIsMissing = true;
12 ✔
163
    std::for_each(templateGroups.cbegin(), templateGroups.cend(), [&](const auto& group) {
12 !
164
        auto groupJson = MakeDeviceGroupJson(group, lang);
44 !
165
        if (group.Name == customGroupName) {
44 ✔
166
            customGroupIsMissing = false;
12 ✔
167
            for (auto& protocolJson: GetProtocols(ProtocolConfedSchemas, lang)) {
192 !
168
                groupJson["types"].append(std::move(protocolJson));
180 !
169
            }
170
        }
171
        res.append(groupJson);
44 !
172
    });
44 ✔
173
    if (customGroupIsMissing) {
12 !
174
        Json::Value groupJson;
×
175
        groupJson["name"] = customGroupName;
×
176
        groupJson["types"] = Json::Value(Json::arrayValue);
×
177
        for (auto& protocolJson: GetProtocols(ProtocolConfedSchemas, lang)) {
×
178
            groupJson["types"].append(std::move(protocolJson));
×
179
        }
×
180
        res.append(groupJson);
×
181
    }
×
182
    return res;
12 ✔
183
}
12 ✔
184

185
Json::Value TRPCConfigHandler::GetSchema(const Json::Value& request)
2 ✔
186
{
187
#ifndef __EMSCRIPTEN__
188
    if (SerialDriverCore.IsBusy()) {
2 !
189
        throw TRPCException(CONFIG_BUSY_ERROR, TRPCResultCode::RPC_WRONG_PARAM_VALUE);
2 !
190
    }
191
#endif
UNCOV
192
    std::string type = request.get("type", "").asString();
×
193
    if (type.find(PROTOCOL_PREFIX) == 0) {
×
UNCOV
194
        type = type.substr(PROTOCOL_PREFIX.size());
×
195
        return ProtocolConfedSchemas.GetSchema(type);
×
196
    }
197
    try {
198
        return *DeviceConfedSchemas.GetSchema(type);
×
UNCOV
199
    } catch (const std::runtime_error& e) {
×
200
        LOG(Error) << e.what();
×
201
        throw TRPCException("Template \"" + type + "\" schema validation failed",
×
202
                            TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
203
    }
×
UNCOV
204
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE TRIAL · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc