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

wirenboard / wb-mqtt-serial / 964

28 Sep 2026 06:54AM UTC coverage: 83.234% (+6.4%) from 76.817%
964

push

github

web-flow
Add disable_fast_modbus option to ports and Modbus devices (#1270)

11435 of 13496 branches covered (84.73%)

150 of 152 new or added lines in 11 files covered. (98.68%)

1282 existing lines in 91 files now uncovered.

19376 of 23279 relevant lines covered (83.23%)

1598.47 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
2,026 ✔
4
{
5
    if (r1->GetConfig()->Type != r2->GetConfig()->Type) {
2,026 ✔
6
        return r1->GetConfig()->Type > r2->GetConfig()->Type;
488 ✔
7
    }
8
    auto cmp = r1->GetConfig()->GetAddress().Compare(r2->GetConfig()->GetAddress());
1,538 ✔
9
    if (cmp != 0) {
1,538 ✔
10
        return cmp > 0;
1,470 ✔
11
    }
12
    // addresses are equal, compare offsets
13
    return r1->GetConfig()->GetDataOffset() > r2->GetConfig()->GetDataOffset();
68 ✔
14
}
15

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

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

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

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

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

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

74
    return registerRange;
848 ✔
UNCOV
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 ✔
UNCOV
89
}
×
90

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

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

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

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

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

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

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

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