• 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

0.0
/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_exception.h"
7
#include "wblib/exceptions.h"
8

9
#define LOG(logger) ::logger.Log() << "[RPC] "
10

11
namespace
12
{
13
    const std::string CUSTOM_GROUP_NAME = "g-custom";
14
    const std::string WB_GROUP_NAME = "g-wb";
15
    const std::string WB_OLD_GROUP_NAME = "g-wb-old";
16

17
    const std::string PROTOCOL_PREFIX = "protocol:";
18

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

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

27
    Json::Value MakeDeviceTypeJson(const PDeviceTemplate& dt, const std::string& lang)
×
28
    {
29
        Json::Value res;
×
30
        res["name"] = dt->GetTitle(lang);
×
31
        res["deprecated"] = dt->IsDeprecated();
×
32
        res["type"] = dt->Type;
×
33
        res["protocol"] = dt->GetProtocol();
×
34
        res["mqtt-id"] = dt->GetMqttId();
×
35
        res["with-subdevices"] = dt->WithSubdevices();
×
36
        if (!dt->GetHardware().empty()) {
×
37
            auto& hwJsonArray = MakeArray("hw", res);
×
38
            for (const auto& hw: dt->GetHardware()) {
×
39
                Json::Value hwJson;
×
40
                hwJson["signature"] = hw.Signature;
×
41
                if (!hw.Fw.empty()) {
×
42
                    hwJson["fw"] = hw.Fw;
×
43
                }
44
                hwJsonArray.append(hwJson);
×
45
            }
46
        }
47
        return res;
×
48
    }
49

50
    Json::Value MakeProtocolJson(const TProtocolConfedSchema& schema, const std::string& lang)
×
51
    {
52
        Json::Value res;
×
53
        res["name"] = schema.GetTitle(lang);
×
54
        res["deprecated"] = false;
×
55
        res["type"] = PROTOCOL_PREFIX + schema.Type;
×
56
        res["protocol"] = schema.Type;
×
57
        res["mqtt-id"] = schema.Type;
×
58
        return res;
×
59
    }
60

61
    Json::Value MakeDeviceTypeList(const TDeviceTypeGroup::TemplatesArray& templates, const std::string& lang)
×
62
    {
63
        Json::Value res(Json::arrayValue);
×
64
        std::for_each(templates.cbegin(), templates.cend(), [&res, &lang](const auto& t) {
×
65
            res.append(MakeDeviceTypeJson(t, lang));
×
66
        });
×
67
        return res;
×
68
    }
69

70
    Json::Value MakeDeviceGroupJson(const TDeviceTypeGroup& group, const std::string& lang)
×
71
    {
72
        Json::Value res;
×
73
        res["name"] = group.Name;
×
74
        res["types"] = MakeDeviceTypeList(group.Templates, lang);
×
75
        return res;
×
76
    }
77

78
    std::vector<Json::Value> GetProtocols(TProtocolConfedSchemasMap& protocolConfedSchemas, const std::string& lang)
×
79
    {
80
        std::vector<Json::Value> res;
×
81
        for (const auto& protocolSchema: protocolConfedSchemas.GetSchemas()) {
×
82
            res.emplace_back(MakeProtocolJson(protocolSchema.second, lang));
×
83
        }
84
        std::sort(res.begin(), res.end(), [](const auto& p1, const auto& p2) {
×
85
            return p1["name"].asString() < p2["name"].asString();
×
86
        });
87
        return res;
×
88
    }
89

90
    std::string GetGroupTranslation(const std::string& group,
×
91
                                    const std::string& lang,
92
                                    const Json::Value& groupTranslations)
93
    {
94
        auto res = groupTranslations.get(lang, Json::Value(Json::objectValue)).get(group, "").asString();
×
95
        return res.empty() ? group : res;
×
96
    }
97

98
    std::vector<TDeviceTypeGroup> OrderTemplates(const std::vector<PDeviceTemplate>& templates,
×
99
                                                 const Json::Value& groupTranslations,
100
                                                 const std::string& lang)
101
    {
102
        std::map<std::string, std::vector<PDeviceTemplate>> groups;
×
103
        std::vector<PDeviceTemplate> groupWb;
×
104
        std::vector<PDeviceTemplate> groupWbOld;
×
105

106
        for (const auto& templatePtr: templates) {
×
107
            const auto& group = templatePtr->GetGroup();
×
108
            if (group == WB_GROUP_NAME) {
×
109
                groupWb.push_back(templatePtr);
×
110
            } else if (group == WB_OLD_GROUP_NAME) {
×
111
                groupWbOld.push_back(templatePtr);
×
112
            } else if (group.empty()) {
×
113
                groups[CUSTOM_GROUP_NAME].push_back(templatePtr);
×
114
            } else {
115
                groups[group].push_back(templatePtr);
×
116
            }
117
        }
118

119
        auto titleSortFn = [&lang](const auto& t1, const auto& t2) { return t1->GetTitle(lang) < t2->GetTitle(lang); };
×
120
        std::for_each(groups.begin(), groups.end(), [&](auto& group) {
×
121
            std::sort(group.second.begin(), group.second.end(), titleSortFn);
×
122
        });
×
123
        std::sort(groupWb.begin(), groupWb.end(), titleSortFn);
×
124
        std::sort(groupWbOld.begin(), groupWbOld.end(), titleSortFn);
×
125

126
        std::vector<TDeviceTypeGroup> res;
×
127
        std::transform(groups.begin(), groups.end(), std::back_inserter(res), [&](auto& group) {
×
128
            return TDeviceTypeGroup{GetGroupTranslation(group.first, lang, groupTranslations), std::move(group.second)};
×
129
        });
×
130

131
        std::sort(res.begin(), res.end(), [](const auto& g1, const auto& g2) { return g1.Name < g2.Name; });
×
132
        res.insert(
133
            res.begin(),
×
134
            TDeviceTypeGroup{GetGroupTranslation(WB_OLD_GROUP_NAME, lang, groupTranslations), std::move(groupWbOld)});
×
135
        res.insert(res.begin(),
×
136
                   TDeviceTypeGroup{GetGroupTranslation(WB_GROUP_NAME, lang, groupTranslations), std::move(groupWb)});
×
137
        return res;
×
138
    }
139
}
140

141
TRPCConfigHandler::TRPCConfigHandler(const std::string& configPath,
×
142
                                     const Json::Value& portsSchema,
143
                                     PTemplateMap templates,
144
                                     TDevicesConfedSchemasMap& deviceConfedSchemas,
145
                                     TProtocolConfedSchemasMap& protocolConfedSchemas,
146
                                     const Json::Value& groupTranslations,
147
                                     WBMQTT::PMqttRpcServer rpcServer)
×
148
    : ConfigPath(configPath),
149
      PortsSchema(portsSchema),
150
      Templates(templates),
151
      DeviceConfedSchemas(deviceConfedSchemas),
152
      ProtocolConfedSchemas(protocolConfedSchemas),
153
      GroupTranslations(groupTranslations)
×
154
{
155
    rpcServer->RegisterMethod("config", "Load", std::bind(&TRPCConfigHandler::LoadConfig, this, std::placeholders::_1));
×
156
    rpcServer->RegisterMethod("config",
×
157
                              "GetSchema",
158
                              std::bind(&TRPCConfigHandler::GetSchema, this, std::placeholders::_1));
×
159
}
160

161
Json::Value TRPCConfigHandler::LoadConfig(const Json::Value& request)
×
162
{
163
    Json::Value res;
×
164
    res["config"] = MakeJsonForConfed(ConfigPath, *Templates);
×
165
    res["schema"] = PortsSchema;
×
166
    res["types"] = GetDeviceTypes(request);
×
167
    return res;
×
168
}
169

170
Json::Value TRPCConfigHandler::GetDeviceTypes(const Json::Value& request)
×
171
{
172
    std::string lang(request.get("lang", "en").asString());
×
173
    Json::Value res(Json::arrayValue);
×
174
    auto templateGroups = OrderTemplates(Templates->GetTemplates(), GroupTranslations, lang);
×
175
    auto customGroupName = GetGroupTranslation(CUSTOM_GROUP_NAME, lang, GroupTranslations);
×
176
    bool customGroupIsMissing = true;
×
177
    std::for_each(templateGroups.cbegin(), templateGroups.cend(), [&](const auto& group) {
×
178
        auto groupJson = MakeDeviceGroupJson(group, lang);
×
179
        if (group.Name == customGroupName) {
×
180
            customGroupIsMissing = false;
×
181
            for (auto& protocolJson: GetProtocols(ProtocolConfedSchemas, lang)) {
×
182
                groupJson["types"].append(std::move(protocolJson));
×
183
            }
184
        }
185
        res.append(groupJson);
×
186
    });
×
187
    if (customGroupIsMissing) {
×
188
        Json::Value groupJson;
×
189
        groupJson["name"] = customGroupName;
×
190
        groupJson["types"] = Json::Value(Json::arrayValue);
×
191
        for (auto& protocolJson: GetProtocols(ProtocolConfedSchemas, lang)) {
×
192
            groupJson["types"].append(std::move(protocolJson));
×
193
        }
194
        res.append(groupJson);
×
195
    }
196
    return res;
×
197
}
198

199
Json::Value TRPCConfigHandler::GetSchema(const Json::Value& request)
×
200
{
201
    std::string type = request.get("type", "").asString();
×
202
    if (type.find(PROTOCOL_PREFIX) == 0) {
×
203
        type = type.substr(PROTOCOL_PREFIX.size());
×
204
        return ProtocolConfedSchemas.GetSchema(type);
×
205
    }
206
    try {
207
        return *DeviceConfedSchemas.GetSchema(type);
×
208
    } catch (const std::runtime_error& e) {
×
209
        LOG(Error) << e.what();
×
210
        throw TRPCException("Template \"" + type + "\" schema validation failed",
×
211
                            TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
212
    }
213
}
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