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

wirenboard / wb-mqtt-serial / 673

15 Jul 2025 07:07AM UTC coverage: 73.028% (-0.8%) from 73.863%
673

push

github

web-flow
Add device/Load and device/Set RPC

6463 of 9217 branches covered (70.12%)

51 of 322 new or added lines in 13 files covered. (15.84%)

7 existing lines in 2 files now uncovered.

12368 of 16936 relevant lines covered (73.03%)

373.64 hits per line

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

0.0
/src/rpc/rpc_device_set_task.cpp
1
#include "rpc_device_set_task.h"
2
#include "config_merge_template.h"
3
#include "rpc_helpers.h"
4
#include "serial_port.h"
5
#include "wb_registers.h"
6

7
#define LOG(logger) ::logger.Log() << "[RPC] "
8

9
namespace
10
{
NEW
11
    void ExecRPCRequest(PPort port, PRPCDeviceSetRequest rpcRequest)
×
12
    {
NEW
13
        if (!rpcRequest->OnResult) {
×
NEW
14
            return;
×
15
        }
16

NEW
17
        TDeviceSetupItems setupItems;
×
NEW
18
        rpcRequest->GetChannelsSetupItems(setupItems);
×
NEW
19
        rpcRequest->GetParametersSetupItems(setupItems);
×
NEW
20
        if (setupItems.empty()) {
×
NEW
21
            rpcRequest->OnResult(Json::Value());
×
22
        }
23

NEW
24
        std::string error;
×
25
        try {
NEW
26
            rpcRequest->Device->Prepare(*port, TDevicePrepareMode::WITHOUT_SETUP);
×
NEW
27
        } catch (const TSerialDeviceException& e) {
×
NEW
28
            error = std::string("Failed to prepare session: ") + e.what();
×
NEW
29
            LOG(Warn) << port->GetDescription() << " " << rpcRequest->Device->ToString() << ": " << error;
×
NEW
30
            throw TRPCException(error, TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
31
        }
32

33
        try {
NEW
34
            rpcRequest->Device->WriteSetupRegisters(*port, setupItems, true);
×
NEW
35
        } catch (const TSerialDeviceException& e) {
×
NEW
36
            error = e.what();
×
37
        }
38

39
        try {
NEW
40
            rpcRequest->Device->EndSession(*port);
×
NEW
41
        } catch (const TSerialDeviceException& e) {
×
NEW
42
            LOG(Warn) << port->GetDescription() << rpcRequest->Device->ToString()
×
NEW
43
                      << " unable to end session: " << e.what();
×
44
        }
45

NEW
46
        if (!error.empty()) {
×
NEW
47
            LOG(Warn) << port->GetDescription() << rpcRequest->Device->ToString() << ": " << error;
×
NEW
48
            throw TRPCException(error, TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
49
        }
50

NEW
51
        rpcRequest->OnResult(Json::Value());
×
52
    }
53
} // namespace
54

NEW
55
TRPCDeviceSetRequest::TRPCDeviceSetRequest(const TDeviceProtocolParams& protocolParams,
×
56
                                           PSerialDevice device,
57
                                           PDeviceTemplate deviceTemplate,
NEW
58
                                           bool deviceFromConfig)
×
NEW
59
    : TRPCDeviceRequest(protocolParams, device, deviceTemplate, deviceFromConfig)
×
60
{}
61

NEW
62
void TRPCDeviceSetRequest::ParseRequestItems(const Json::Value& items,
×
63
                                             std::unordered_map<std::string, std::string>& map)
64
{
NEW
65
    for (auto it = items.begin(); it != items.end(); ++it) {
×
NEW
66
        map[it.key().asString()] = (*it).asString();
×
67
    }
68
}
69

NEW
70
void TRPCDeviceSetRequest::GetChannelsSetupItems(TDeviceSetupItems& setupItems)
×
71
{
NEW
72
    for (auto item: DeviceTemplate->GetTemplate()["channels"]) {
×
NEW
73
        if (item["readonly"].asBool()) {
×
NEW
74
            continue;
×
75
        }
NEW
76
        auto id = item["name"].asString();
×
NEW
77
        if (Channels.count(id)) {
×
NEW
78
            setupItems.insert(CreateSetupItem(id, item, Channels[id]));
×
NEW
79
            Channels.erase(id);
×
80
        }
81
    }
NEW
82
    if (!Channels.empty()) {
×
NEW
83
        throw TRPCException("Channel \"" + Channels.begin()->first + "\" is read only or not found in \"" +
×
NEW
84
                                DeviceTemplate->Type + "\" device template",
×
NEW
85
                            TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
86
    }
87
}
88

NEW
89
void TRPCDeviceSetRequest::GetParametersSetupItems(TDeviceSetupItems& setupItems)
×
90
{
NEW
91
    auto params = DeviceTemplate->GetTemplate()["parameters"];
×
NEW
92
    for (auto it = params.begin(); it != params.end(); ++it) {
×
NEW
93
        auto item = *it;
×
NEW
94
        if (item["readonly"].asBool()) {
×
NEW
95
            continue;
×
96
        }
NEW
97
        auto id = params.isObject() ? it.key().asString() : item["id"].asString();
×
NEW
98
        if (Parameters.count(id)) {
×
NEW
99
            setupItems.insert(CreateSetupItem(id, item, Parameters[id]));
×
NEW
100
            Parameters.erase(id);
×
101
        }
102
    }
NEW
103
    if (!Parameters.empty()) {
×
NEW
104
        throw TRPCException("Parameter \"" + Parameters.begin()->first + "\" is read only or not found in \"" +
×
NEW
105
                                DeviceTemplate->Type + "\" device template",
×
NEW
106
                            TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
107
    }
108
}
109

NEW
110
PDeviceSetupItem TRPCDeviceSetRequest::CreateSetupItem(const std::string& id,
×
111
                                                       const Json::Value& data,
112
                                                       const std::string& value)
113
{
114
    auto config = LoadRegisterConfig(data,
NEW
115
                                     *ProtocolParams.protocol->GetRegTypes(),
×
NEW
116
                                     std::string(),
×
NEW
117
                                     *ProtocolParams.factory,
×
NEW
118
                                     ProtocolParams.factory->GetRegisterAddressFactory().GetBaseRegisterAddress(),
×
NEW
119
                                     0);
×
NEW
120
    auto itemConfig = std::make_shared<TDeviceSetupItemConfig>(id, config.RegisterConfig, value);
×
NEW
121
    return std::make_shared<TDeviceSetupItem>(itemConfig, Device);
×
122
}
123

NEW
124
PRPCDeviceSetRequest ParseRPCDeviceSetRequest(const Json::Value& request,
×
125
                                              const TDeviceProtocolParams& protocolParams,
126
                                              PSerialDevice device,
127
                                              PDeviceTemplate deviceTemplate,
128
                                              bool deviceFromConfig,
129
                                              WBMQTT::TMqttRpcServer::TResultCallback onResult,
130
                                              WBMQTT::TMqttRpcServer::TErrorCallback onError)
131
{
NEW
132
    auto res = std::make_shared<TRPCDeviceSetRequest>(protocolParams, device, deviceTemplate, deviceFromConfig);
×
NEW
133
    res->ParseSettings(request, onResult, onError);
×
NEW
134
    res->ParseRequestItems(request["channels"], res->Channels);
×
NEW
135
    res->ParseRequestItems(request["parameters"], res->Parameters);
×
NEW
136
    return res;
×
137
}
138

NEW
139
TRPCDeviceSetSerialClientTask::TRPCDeviceSetSerialClientTask(PRPCDeviceSetRequest request): Request(request)
×
140
{
NEW
141
    ExpireTime = std::chrono::steady_clock::now() + Request->TotalTimeout;
×
142
}
143

NEW
144
ISerialClientTask::TRunResult TRPCDeviceSetSerialClientTask::Run(PPort port,
×
145
                                                                 TSerialClientDeviceAccessHandler& lastAccessedDevice,
146
                                                                 const std::list<PSerialDevice>& polledDevices)
147
{
NEW
148
    if (std::chrono::steady_clock::now() > ExpireTime) {
×
NEW
149
        if (Request->OnError) {
×
NEW
150
            Request->OnError(WBMQTT::E_RPC_REQUEST_TIMEOUT, "RPC request timeout");
×
151
        }
NEW
152
        return ISerialClientTask::TRunResult::OK;
×
153
    }
154
    try {
NEW
155
        if (!port->IsOpen()) {
×
NEW
156
            port->Open();
×
157
        }
NEW
158
        lastAccessedDevice.PrepareToAccess(*port, nullptr);
×
NEW
159
        if (!Request->DeviceFromConfig) {
×
NEW
160
            TSerialPortSettingsGuard settingsGuard(port, Request->SerialPortSettings);
×
161
        }
NEW
162
        ExecRPCRequest(port, Request);
×
NEW
163
    } catch (const std::exception& error) {
×
NEW
164
        if (Request->OnError) {
×
NEW
165
            Request->OnError(WBMQTT::E_RPC_SERVER_ERROR, std::string("Port IO error: ") + error.what());
×
166
        }
167
    }
NEW
168
    return ISerialClientTask::TRunResult::OK;
×
169
}
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