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

wirenboard / wb-mqtt-serial / 1

08 Jul 2025 01:20PM UTC coverage: 73.854% (+1.0%) from 72.836%
1

Pull #963

github

39d9bc
KraPete
Bump version
Pull Request #963: Bump version

6444 of 9057 branches covered (71.15%)

12341 of 16710 relevant lines covered (73.85%)

305.53 hits per line

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

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

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

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

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

52
    if (!registerRange->RegisterList().empty()) {
753✔
53
        bool readOk = false;
716✔
54
        if (lastAccessedDevice.PrepareToAccess(port, Device)) {
716✔
55
            Device->ReadRegisterRange(port, registerRange);
698✔
56
            readOk = true;
698✔
57
        }
58

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

66
        for (const auto& reg: registerRange->RegisterList()) {
1,845✔
67
            ScheduleNextPoll(reg, currentTime);
1,129✔
68
        }
69

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

73
    return registerRange;
1,506✔
74
}
75

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

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

100
TPriority TPollableDevice::GetPriority() const
2,620✔
101
{
102
    return Priority;
2,620✔
103
}
104

105
PSerialDevice TPollableDevice::GetDevice() const
780✔
106
{
107
    return Device;
780✔
108
}
109

110
bool TPollableDevice::HasRegisters() const
914✔
111
{
112
    return !Registers.IsEmpty();
914✔
113
}
114

115
void TPollableDevice::RescheduleAllRegisters()
18✔
116
{
117
    for (const auto& reg: Device->GetRegisters()) {
52✔
118
        if ((Priority == TPriority::High && reg->GetConfig()->IsHighPriority()) ||
101✔
119
            (Priority == TPriority::Low && !reg->GetConfig()->IsHighPriority()))
67✔
120
        {
121
            if (reg->GetConfig()->AccessType != TRegisterConfig::EAccessType::WRITE_ONLY) {
32✔
122
                if (reg->IsExcludedFromPolling() && !Registers.Contains(reg)) {
32✔
123
                    reg->SetAvailable(TRegisterAvailability::UNKNOWN);
×
124
                    reg->IncludeInPolling();
×
125
                    Registers.AddEntry(reg, std::chrono::steady_clock::time_point());
×
126
                }
127
            }
128
        }
129
    }
130
}
18✔
131

132
void TPollableDevice::ScheduleNextPoll(PRegister reg, std::chrono::steady_clock::time_point currentTime)
1,137✔
133
{
134
    if (reg->IsExcludedFromPolling()) {
1,137✔
135
        // If register is sporadic it must be read once to get actual value
136
        // Keep polling it until successful read
137
        if (reg->GetValue().GetType() == TRegisterValue::ValueType::Undefined) {
22✔
138
            Registers.AddEntry(reg, currentTime + std::chrono::microseconds(1));
16✔
139
        }
140
        return;
22✔
141
    }
142
    if (Priority == TPriority::High) {
1,115✔
143
        Registers.AddEntry(reg, currentTime + *(reg->GetConfig()->ReadPeriod));
42✔
144
        return;
42✔
145
    }
146
    if (reg->GetConfig()->ReadRateLimit) {
1,073✔
147
        Registers.AddEntry(reg, currentTime + *(reg->GetConfig()->ReadRateLimit));
9✔
148
        return;
9✔
149
    }
150
    // Low priority registers should be scheduled to read as soon as possible,
151
    // but with a small delay after current read.
152
    Registers.AddEntry(reg, currentTime + std::chrono::microseconds(1));
1,064✔
153
}
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