• 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

91.21
/src/pollable_device.cpp
1
#include "pollable_device.h"
2

3
bool TRegisterComparePredicate::operator()(const PRegister& r1, const PRegister& r2) const
4,184 ✔
4
{
5
    if (r1->GetConfig()->Type != r2->GetConfig()->Type) {
4,184 !
6
        return r1->GetConfig()->Type > r2->GetConfig()->Type;
976 !
7
    }
8
    auto cmp = r1->GetConfig()->GetAddress().Compare(r2->GetConfig()->GetAddress());
3,208 !
9
    if (cmp != 0) {
3,208 ✔
10
        return cmp > 0;
3,072 ✔
11
    }
12
    // addresses are equal, compare offsets
13
    return r1->GetConfig()->GetDataOffset() > r2->GetConfig()->GetDataOffset();
136 !
14
}
15

16
TPollableDevice::TPollableDevice(PSerialDevice device,
928 ✔
17
                                 std::chrono::steady_clock::time_point currentTime,
18
                                 TPriority priority)
928 ✔
19
    : Device(device),
928 ✔
20
      Priority(priority),
928 ✔
21
      DisconnectedPollDelay(0)
928 !
22
{
23
    for (const auto& reg: Device->GetRegisters()) {
3,724 !
24
        if ((Priority == TPriority::High && reg->GetConfig()->IsHighPriority()) ||
8,374 !
25
            (Priority == TPriority::Low && !reg->GetConfig()->IsHighPriority()))
5,578 !
26
        {
27
            if (reg->GetConfig()->AccessType != TRegisterConfig::EAccessType::WRITE_ONLY) {
1,398 !
28
                Registers.AddEntry(reg, currentTime);
1,394 !
29
            }
30
        }
31
    }
32
}
928 ✔
33

34
PRegisterRange TPollableDevice::ReadRegisterRange(TFeaturePort& port,
9,808 ✔
35
                                                  std::chrono::milliseconds pollLimit,
36
                                                  bool readAtLeastOneRegister,
37
                                                  const util::TSpentTimeMeter& sessionTime,
38
                                                  TSerialClientDeviceAccessHandler& lastAccessedDevice)
39
{
40
    auto currentTime = sessionTime.GetStartTime();
9,808 !
41
    auto registerRange = Device->CreateRegisterRange();
9,808 !
42
    while (Registers.HasReadyItems(currentTime)) {
20,440 !
43
        const auto limit = (readAtLeastOneRegister && registerRange->RegisterList().empty())
11,402 !
44
                               ? std::chrono::milliseconds::max()
21,242 ✔
45
                               : pollLimit;
11,600 ✔
46
        const auto& item = Registers.GetTop();
11,600 !
47
        if (!registerRange->Add(port, item.Data, limit)) {
11,600 !
48
            break;
968 ✔
49
        }
50
        Registers.Pop();
10,632 !
51
    }
52

53
    if (!registerRange->RegisterList().empty()) {
9,808 !
54
        bool readOk = false;
9,734 ✔
55
        if (lastAccessedDevice.PrepareToAccess(port, Device)) {
9,734 !
56
            Device->ReadRegisterRange(port, registerRange);
9,687 !
57
            readOk = true;
9,687 ✔
58
        }
59

60
        for (auto& reg: registerRange->RegisterList()) {
20,344 !
61
            reg->SetLastPollTime(currentTime);
10,610 !
62
            if (!readOk) {
10,610 ✔
63
                reg->SetError(TRegister::TError::ReadError);
83 !
64
            }
65
        }
66

67
        for (const auto& reg: registerRange->RegisterList()) {
20,344 !
68
            ScheduleNextPoll(reg, currentTime);
10,610 !
69
        }
70

71
        Device->SetLastReadTime(currentTime + sessionTime.GetSpentTime());
9,734 !
72
    }
73

74
    return registerRange;
9,808 ✔
UNCOV
75
}
×
76

77
std::list<PRegister> TPollableDevice::MarkWaitingRegistersAsReadErrorAndReschedule(
66 ✔
78
    std::chrono::steady_clock::time_point currentTime)
79
{
80
    std::list<PRegister> res;
66 ✔
81
    while (Registers.HasReadyItems(currentTime)) {
140 !
82
        res.push_back(Registers.GetTop().Data);
74 !
83
        Registers.Pop();
74 !
84
    }
85
    for (const auto& reg: res) {
140 ✔
86
        ScheduleNextPoll(reg, currentTime);
74 !
87
    }
88
    return res;
66 ✔
UNCOV
89
}
×
90

91
std::chrono::steady_clock::time_point TPollableDevice::GetDeadline() const
9,856 ✔
92
{
93
    if (Priority == TPriority::Low && Device->DeviceConfig()->MinRequestInterval != std::chrono::milliseconds::zero()) {
9,856 !
94
        auto deadline = Registers.GetDeadline();
×
UNCOV
95
        auto minNextReadTime = Device->GetLastReadTime() + Device->DeviceConfig()->MinRequestInterval;
×
UNCOV
96
        return minNextReadTime > deadline ? minNextReadTime : deadline;
×
97
    }
98
    return Registers.GetDeadline();
9,856 ✔
99
}
100

101
std::chrono::milliseconds TPollableDevice::GetDisconnectedPollDelay() const
187 ✔
102
{
103
    return DisconnectedPollDelay;
187 ✔
104
}
105

106
void TPollableDevice::SetDisconnectedPollDelay(const std::chrono::milliseconds& delay)
9,800 ✔
107
{
108
    DisconnectedPollDelay = delay;
9,800 ✔
109
}
9,800 ✔
110

111
TPriority TPollableDevice::GetPriority() const
30,274 ✔
112
{
113
    return Priority;
30,274 ✔
114
}
115

116
PSerialDevice TPollableDevice::GetDevice() const
19,930 ✔
117
{
118
    return Device;
19,930 ✔
119
}
120

121
bool TPollableDevice::HasRegisters() const
10,728 ✔
122
{
123
    return !Registers.IsEmpty();
10,728 ✔
124
}
125

126
void TPollableDevice::RescheduleAllRegisters()
56 ✔
127
{
128
    for (const auto& reg: Device->GetRegisters()) {
144 !
129
        if ((Priority == TPriority::High && reg->GetConfig()->IsHighPriority()) ||
262 !
130
            (Priority == TPriority::Low && !reg->GetConfig()->IsHighPriority()))
174 !
131
        {
132
            if (reg->GetConfig()->AccessType != TRegisterConfig::EAccessType::WRITE_ONLY) {
84 !
133
                if (reg->IsExcludedFromPolling() && !Registers.Contains(reg)) {
84 !
UNCOV
134
                    reg->SetAvailable(TRegisterAvailability::UNKNOWN);
×
UNCOV
135
                    reg->IncludeInPolling();
×
UNCOV
136
                    Registers.AddEntry(reg, std::chrono::steady_clock::time_point());
×
137
                }
138
            }
139
        }
140
    }
141
}
56 ✔
142

143
void TPollableDevice::ScheduleNextPoll(PRegister reg, std::chrono::steady_clock::time_point currentTime)
10,684 ✔
144
{
145
    if (reg->IsExcludedFromPolling()) {
10,684 ✔
146
        // If register is sporadic it must be read once to get actual value
147
        // Keep polling it until successful read
148
        if (reg->GetValue().GetType() == TRegisterValue::ValueType::Undefined) {
46 !
149
            Registers.AddEntry(reg, currentTime + std::chrono::microseconds(1));
32 !
150
        }
151
        return;
46 ✔
152
    }
153
    if (Priority == TPriority::High) {
10,638 ✔
154
        Registers.AddEntry(reg, currentTime + *(reg->GetConfig()->ReadPeriod));
84 !
155
        return;
84 ✔
156
    }
157
    if (reg->GetConfig()->ReadRateLimit) {
10,554 !
158
        Registers.AddEntry(reg, currentTime + *(reg->GetConfig()->ReadRateLimit));
28 !
159
        return;
28 ✔
160
    }
161
    // Low priority registers should be scheduled to read as soon as possible,
162
    // but with a small delay after current read.
163
    Registers.AddEntry(reg, currentTime + std::chrono::microseconds(1));
10,526 !
164
}
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