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

wirenboard / wb-mqtt-serial / 678

25 Jul 2025 02:31PM UTC coverage: 72.915% (-0.02%) from 72.937%
678

push

github

web-flow
Feature/modbus tcp rpc rebase

6465 of 9231 branches covered (70.04%)

0 of 10 new or added lines in 2 files covered. (0.0%)

2 existing lines in 1 file now uncovered.

12373 of 16969 relevant lines covered (72.92%)

372.91 hits per line

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

0.0
/src/rpc/rpc_port_load_modbus_serial_client_task.cpp
1
#include "rpc_port_load_modbus_serial_client_task.h"
2
#include "modbus_base.h"
3
#include "rpc_port_handler.h"
4
#include "serial_exc.h"
5
#include "serial_port.h"
6

7
template<> bool inline WBMQTT::JSON::Is<uint8_t>(const Json::Value& value)
×
8
{
9
    return value.isUInt();
×
10
}
11

12
template<> inline uint8_t WBMQTT::JSON::As<uint8_t>(const Json::Value& value)
×
13
{
14
    return value.asUInt() & 0xFF;
×
15
}
16

17
template<> bool inline WBMQTT::JSON::Is<uint16_t>(const Json::Value& value)
×
18
{
19
    return value.isUInt();
×
20
}
21

22
template<> inline uint16_t WBMQTT::JSON::As<uint16_t>(const Json::Value& value)
×
23
{
24
    return value.asUInt() & 0xFFFF;
×
25
}
26

27
template<> bool inline WBMQTT::JSON::Is<Modbus::EFunction>(const Json::Value& value)
×
28
{
29
    if (!value.isUInt()) {
×
30
        return false;
×
31
    }
32
    auto fun = value.asUInt();
×
33
    return Modbus::IsSupportedFunction(fun & 0xFF);
×
34
}
35

36
template<> inline Modbus::EFunction WBMQTT::JSON::As<Modbus::EFunction>(const Json::Value& value)
×
37
{
38
    return static_cast<Modbus::EFunction>(value.asUInt() & 0xFF);
×
39
}
40

41
TRPCPortLoadModbusRequest::TRPCPortLoadModbusRequest(TRPCDeviceParametersCache& parametersCache)
×
42
    : ParametersCache(parametersCache)
×
43
{}
44

45
PRPCPortLoadModbusRequest ParseRPCPortLoadModbusRequest(const Json::Value& request,
×
46
                                                        TRPCDeviceParametersCache& parametersCache)
47
{
48
    PRPCPortLoadModbusRequest RPCRequest = std::make_shared<TRPCPortLoadModbusRequest>(parametersCache);
×
49

50
    try {
51
        ParseRPCPortLoadRequest(request, *RPCRequest);
×
52
        WBMQTT::JSON::Get(request, "slave_id", RPCRequest->SlaveId);
×
53
        WBMQTT::JSON::Get(request, "address", RPCRequest->Address);
×
54
        WBMQTT::JSON::Get(request, "count", RPCRequest->Count);
×
55
        WBMQTT::JSON::Get(request, "write_address", RPCRequest->WriteAddress);
×
56
        WBMQTT::JSON::Get(request, "write_count", RPCRequest->WriteCount);
×
57
        WBMQTT::JSON::Get(request, "function", RPCRequest->Function);
×
NEW
58
        WBMQTT::JSON::Get(request, "protocol", RPCRequest->Protocol);
×
59
    } catch (const std::runtime_error& e) {
×
60
        throw TRPCException(e.what(), TRPCResultCode::RPC_WRONG_PARAM_VALUE);
×
61
    }
62

63
    return RPCRequest;
×
64
}
65

66
void ExecRPCPortLoadModbusRequest(TPort& port, PRPCPortLoadModbusRequest rpcRequest)
×
67
{
68
    try {
69
        port.CheckPortOpen();
×
70
        port.SkipNoise();
×
71
        port.SleepSinceLastInteraction(rpcRequest->FrameTimeout);
×
72

73
        // Select traits based on protocol
NEW
74
        std::unique_ptr<Modbus::IModbusTraits> traits;
×
NEW
75
        if (rpcRequest->Protocol == "modbus-tcp") {
×
NEW
76
            traits = std::make_unique<Modbus::TModbusTCPTraits>();
×
77
        } else {
NEW
78
            traits = std::make_unique<Modbus::TModbusRTUTraits>();
×
79
        }
80

81
        auto pdu = Modbus::MakePDU(rpcRequest->Function,
×
82
                                   rpcRequest->Address,
×
83
                                   rpcRequest->Count,
×
84
                                   rpcRequest->WriteAddress,
×
85
                                   rpcRequest->WriteCount,
×
86
                                   rpcRequest->Message);
×
87

UNCOV
88
        auto responsePduSize = Modbus::CalcResponsePDUSize(rpcRequest->Function, rpcRequest->Count);
×
NEW
89
        auto res = traits->Transaction(port,
×
NEW
90
                                       rpcRequest->SlaveId,
×
91
                                       pdu,
92
                                       responsePduSize,
NEW
93
                                       rpcRequest->ResponseTimeout,
×
NEW
94
                                       rpcRequest->FrameTimeout);
×
UNCOV
95
        auto response = Modbus::ExtractResponseData(rpcRequest->Function, res.Pdu);
×
96

97
        if (rpcRequest->OnResult) {
×
98
            Json::Value replyJSON;
×
99
            replyJSON["response"] = FormatResponse(response, rpcRequest->Format);
×
100
            rpcRequest->OnResult(replyJSON);
×
101
        }
102

103
        if (rpcRequest->Function == Modbus::EFunction::FN_WRITE_SINGLE_COIL ||
×
104
            rpcRequest->Function == Modbus::EFunction::FN_WRITE_SINGLE_REGISTER ||
×
105
            rpcRequest->Function == Modbus::EFunction::FN_WRITE_MULTIPLE_COILS ||
×
106
            rpcRequest->Function == Modbus::EFunction::FN_WRITE_MULTIPLE_REGISTERS ||
×
107
            rpcRequest->Function == Modbus::EFunction::FN_READ_WRITE_MULTIPLE_REGISTERS)
×
108
        {
109
            std::string id = rpcRequest->ParametersCache.GetId(port, std::to_string(rpcRequest->SlaveId));
×
110
            rpcRequest->ParametersCache.Remove(id);
×
111
        }
112
    } catch (const Modbus::TModbusExceptionError& error) {
×
113
        Json::Value replyJSON;
×
114
        replyJSON["exception"]["code"] = error.GetExceptionCode();
×
115
        replyJSON["exception"]["msg"] = error.what();
×
116
        rpcRequest->OnResult(replyJSON);
×
117
    } catch (const TResponseTimeoutException& error) {
×
118
        if (rpcRequest->OnError) {
×
119
            rpcRequest->OnError(WBMQTT::E_RPC_REQUEST_TIMEOUT, error.what());
×
120
        }
121
    }
122
}
123

124
TRPCPortLoadModbusSerialClientTask::TRPCPortLoadModbusSerialClientTask(const Json::Value& request,
×
125
                                                                       WBMQTT::TMqttRpcServer::TResultCallback onResult,
126
                                                                       WBMQTT::TMqttRpcServer::TErrorCallback onError,
127
                                                                       TRPCDeviceParametersCache& parametersCache)
×
128
    : Request(ParseRPCPortLoadModbusRequest(request, parametersCache))
×
129
{
130
    Request->OnResult = onResult;
×
131
    Request->OnError = onError;
×
132
    ExpireTime = std::chrono::steady_clock::now() + Request->TotalTimeout;
×
133
}
134

135
ISerialClientTask::TRunResult TRPCPortLoadModbusSerialClientTask::Run(
×
136
    PPort port,
137
    TSerialClientDeviceAccessHandler& lastAccessedDevice,
138
    const std::list<PSerialDevice>& polledDevices)
139
{
140
    if (std::chrono::steady_clock::now() > ExpireTime) {
×
141
        if (Request->OnError) {
×
142
            Request->OnError(WBMQTT::E_RPC_REQUEST_TIMEOUT, "RPC request timeout");
×
143
        }
144
        return ISerialClientTask::TRunResult::OK;
×
145
    }
146

147
    try {
148
        if (!port->IsOpen()) {
×
149
            port->Open();
×
150
        }
151
        lastAccessedDevice.PrepareToAccess(*port, nullptr);
×
152
        TSerialPortSettingsGuard settingsGuard(port, Request->SerialPortSettings);
×
153
        ExecRPCPortLoadModbusRequest(*port, Request);
×
154
    } catch (const std::exception& error) {
×
155
        if (Request->OnError) {
×
156
            Request->OnError(WBMQTT::E_RPC_SERVER_ERROR, std::string("Port IO error: ") + error.what());
×
157
        }
158
    }
159
    return ISerialClientTask::TRunResult::OK;
×
160
}
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