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

wirenboard / wb-mqtt-serial / 6

13 Jan 2026 06:31AM UTC coverage: 76.817% (+4.0%) from 72.836%
6

Pull #1049

github

8b2ffc
Ilia1S
Remove fw from groups
Pull Request #1049: WB-MR templates: Add delays

6873 of 9161 branches covered (75.02%)

12966 of 16879 relevant lines covered (76.82%)

830.18 hits per line

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

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

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

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

34
PRegisterRange TPollableDevice::ReadRegisterRange(TFeaturePort& port,
795✔
35
                                                  std::chrono::milliseconds pollLimit,
36
                                                  bool readAtLeastOneRegister,
37
                                                  const util::TSpentTimeMeter& sessionTime,
38
                                                  TSerialClientDeviceAccessHandler& lastAccessedDevice)
39
{
40
    auto currentTime = sessionTime.GetStartTime();
795✔
41
    auto registerRange = Device->CreateRegisterRange();
795✔
42
    while (Registers.HasReadyItems(currentTime)) {
1,993✔
43
        const auto limit = (readAtLeastOneRegister && registerRange->RegisterList().empty())
1,558✔
44
                               ? std::chrono::milliseconds::max()
2,369✔
45
                               : pollLimit;
1,656✔
46
        const auto& item = Registers.GetTop();
1,656✔
47
        if (!registerRange->Add(port, item.Data, limit)) {
1,656✔
48
            break;
458✔
49
        }
50
        Registers.Pop();
1,198✔
51
    }
52

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

60
        for (auto& reg: registerRange->RegisterList()) {
1,945✔
61
            reg->SetLastPollTime(currentTime);
1,187✔
62
            if (!readOk) {
1,187✔
63
                reg->SetError(TRegister::TError::ReadError);
33✔
64
            }
65
        }
66

67
        for (const auto& reg: registerRange->RegisterList()) {
1,945✔
68
            ScheduleNextPoll(reg, currentTime);
1,187✔
69
        }
70

71
        Device->SetLastReadTime(currentTime + sessionTime.GetSpentTime());
758✔
72
    }
73

74
    return registerRange;
1,590✔
75
}
76

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

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

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

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

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

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

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

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

143
void TPollableDevice::ScheduleNextPoll(PRegister reg, std::chrono::steady_clock::time_point currentTime)
1,195✔
144
{
145
    if (reg->IsExcludedFromPolling()) {
1,195✔
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) {
22✔
149
            Registers.AddEntry(reg, currentTime + std::chrono::microseconds(1));
16✔
150
        }
151
        return;
22✔
152
    }
153
    if (Priority == TPriority::High) {
1,173✔
154
        Registers.AddEntry(reg, currentTime + *(reg->GetConfig()->ReadPeriod));
42✔
155
        return;
42✔
156
    }
157
    if (reg->GetConfig()->ReadRateLimit) {
1,131✔
158
        Registers.AddEntry(reg, currentTime + *(reg->GetConfig()->ReadRateLimit));
11✔
159
        return;
11✔
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));
1,120✔
164
}
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