| Directory: | src/ |
|---|---|
| File: | src/Message.cpp |
| Date: | 2026-10-06 07:41:07 |
| Exec | Total | Coverage | |
|---|---|---|---|
| Lines: | 57 | 75 | 76.0% |
| Branches: | 51 | 102 | 50.0% |
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | /***************************************************************************** | ||
| 2 | * | ||
| 3 | * Copyright (C) 2021 Jonathan Grahl <jonathan.grahl@igh.de> | ||
| 4 | * 2021 Florian Pose <florian.pose@igh.de> | ||
| 5 | * | ||
| 6 | * This file is part of the reta library (realtime-automation). | ||
| 7 | * | ||
| 8 | * The reta library is free software: you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU Lesser General Public License as published | ||
| 10 | * by the Free Software Foundation, either version 3 of the License, or (at | ||
| 11 | * your option) any later version. | ||
| 12 | * | ||
| 13 | * The reta library is distributed in the hope that it will be useful, but | ||
| 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser | ||
| 16 | * General Public License for more details. | ||
| 17 | * | ||
| 18 | * You should have received a copy of the GNU Lesser General Public License | ||
| 19 | * along with the reta library. If not, see <http://www.gnu.org/licenses/>. | ||
| 20 | * | ||
| 21 | ****************************************************************************/ | ||
| 22 | |||
| 23 | #include "reta/Message.h" | ||
| 24 | |||
| 25 | #include "Base.h" | ||
| 26 | |||
| 27 | #include <sstream> | ||
| 28 | #include <time.h> | ||
| 29 | |||
| 30 | using namespace Reta; | ||
| 31 | using namespace std; | ||
| 32 | |||
| 33 | /****************************************************************************/ | ||
| 34 | |||
| 35 | 1 | struct RETA_LOCAL Message::Impl : public Base | |
| 36 | { | ||
| 37 | Impl(shared_ptr<Task>, const string &, unsigned int width, int priority); | ||
| 38 | |||
| 39 | shared_ptr<Task> task; | ||
| 40 | |||
| 41 | int priority; | ||
| 42 | vector<uint8_t> enable; | ||
| 43 | vector<uint8_t> state; | ||
| 44 | vector<uint8_t> prevState; | ||
| 45 | vector<double> time; | ||
| 46 | vector<string> texts; | ||
| 47 | vector<const char *> textArray; | ||
| 48 | struct pdevent *event; | ||
| 49 | }; | ||
| 50 | |||
| 51 | /****************************************************************************/ | ||
| 52 | |||
| 53 | 1 | Message::Impl::Impl( | |
| 54 | shared_ptr<Task> task, | ||
| 55 | const string &prefix, | ||
| 56 | unsigned int width, | ||
| 57 | 1 | int priorityInit) : | |
| 58 | Base {prefix}, | ||
| 59 | task {task}, | ||
| 60 | priority {priorityInit}, | ||
| 61 | enable(width, true), | ||
| 62 | state(width, false), | ||
| 63 | prevState(width, false), | ||
| 64 | time(width, 0.0), | ||
| 65 | 2 | texts(width, string()), | |
| 66 | textArray(width, nullptr), | ||
| 67 |
6/12✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
✓ Branch 9 taken 1 times.
✗ Branch 10 not taken.
✓ Branch 14 taken 1 times.
✗ Branch 15 not taken.
✓ Branch 19 taken 1 times.
✗ Branch 20 not taken.
✓ Branch 24 taken 1 times.
✗ Branch 25 not taken.
✓ Branch 29 taken 1 times.
✗ Branch 30 not taken.
|
3 | event {nullptr} |
| 68 | { | ||
| 69 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | checkZeroWidth(width); |
| 70 | |||
| 71 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | pdserv *pdserv {task->getPdServ()}; |
| 72 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | pdtask *pdtask {task->getPdTask()}; |
| 73 | |||
| 74 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | pdserv_parameter( |
| 75 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | pdserv, (prefix + "/Enable").c_str(), 0666, pd_boolean_T, |
| 76 | 1 | enable.data(), enable.size(), NULL, NULL, NULL); | |
| 77 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | pdserv_signal( |
| 78 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
2 | pdtask, 1, (prefix + "/state").c_str(), pd_boolean_T, |
| 79 | 1 | state.data(), state.size(), NULL); | |
| 80 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | pdserv_signal( |
| 81 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | pdtask, 1, (prefix + "/time").c_str(), pd_double_T, time.data(), |
| 82 | time.size(), NULL); | ||
| 83 | |||
| 84 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
|
1 | event = pdserv_event(pdserv, (prefix + "/Event").c_str(), width); |
| 85 | |||
| 86 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | for (unsigned int i = 0; i < width; i++) { |
| 87 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
2 | stringstream str; |
| 88 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
1 | str << prefix << "/Event"; |
| 89 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (width > 1) { |
| 90 | ✗ | str << "/" << i; | |
| 91 | } | ||
| 92 |
1/2✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
|
1 | texts[i] = str.str(); |
| 93 | 1 | textArray[i] = texts[i].c_str(); | |
| 94 | } | ||
| 95 | |||
| 96 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | pdserv_event_set_text(event, textArray.data()); |
| 97 | 1 | } | |
| 98 | |||
| 99 | /****************************************************************************/ | ||
| 100 | |||
| 101 | 1 | Message::Message( | |
| 102 | shared_ptr<Task> task, | ||
| 103 | const string &prefix, | ||
| 104 | unsigned int width, | ||
| 105 | 1 | int priority) : | |
| 106 | 1 | impl {make_unique<Impl>(task, prefix, width, priority)} | |
| 107 | 1 | {} | |
| 108 | |||
| 109 | /****************************************************************************/ | ||
| 110 | |||
| 111 | 1 | Message::~Message() | |
| 112 | 1 | {} | |
| 113 | |||
| 114 | /****************************************************************************/ | ||
| 115 | |||
| 116 | 12 | void Message::update(bool input, bool acknowledge) | |
| 117 | { | ||
| 118 |
2/4✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
|
12 | update(vector<uint8_t> {input}, acknowledge); |
| 119 | 12 | } | |
| 120 | |||
| 121 | /****************************************************************************/ | ||
| 122 | |||
| 123 | ✗ | void Message::update(function<bool(unsigned int)> input, bool acknowledge) | |
| 124 | { | ||
| 125 | ✗ | vector<uint8_t> inputVector(impl->state.size()); | |
| 126 | |||
| 127 | ✗ | for (unsigned int i = 0; i < impl->state.size(); i++) { | |
| 128 | ✗ | inputVector[i] = input(i); | |
| 129 | } | ||
| 130 | |||
| 131 | ✗ | update(inputVector, acknowledge); | |
| 132 | } | ||
| 133 | |||
| 134 | /****************************************************************************/ | ||
| 135 | |||
| 136 | 12 | void Message::update(const vector<uint8_t> &input, bool acknowledge) | |
| 137 | { | ||
| 138 |
1/2✓ Branch 3 taken 12 times.
✗ Branch 4 not taken.
|
12 | impl->checkSize(input, impl->state); |
| 139 | |||
| 140 | 12 | struct timespec t = {}; | |
| 141 | |||
| 142 |
2/2✓ Branch 2 taken 12 times.
✓ Branch 3 taken 12 times.
|
24 | for (unsigned int i = 0; i < impl->state.size(); i++) { |
| 143 | 12 | impl->prevState[i] = impl->state[i]; | |
| 144 | |||
| 145 |
3/4✓ Branch 1 taken 9 times.
✓ Branch 2 taken 3 times.
✓ Branch 5 taken 9 times.
✗ Branch 6 not taken.
|
12 | bool condition {input[i] and impl->enable[i]}; |
| 146 | |||
| 147 |
6/6✓ Branch 0 taken 9 times.
✓ Branch 1 taken 3 times.
✓ Branch 4 taken 2 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 10 times.
|
12 | if (condition and not impl->state[i]) { |
| 148 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if (!t.tv_sec) { |
| 149 | 2 | clock_gettime(CLOCK_REALTIME, &t); | |
| 150 | } | ||
| 151 | |||
| 152 | 2 | impl->time[i] = (double) t.tv_sec + (double) t.tv_nsec * 1e-9; | |
| 153 | 2 | impl->state[i] = true; | |
| 154 | |||
| 155 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
2 | pdserv_event_set(impl->event, i, impl->priority, &t); |
| 156 | } | ||
| 157 |
4/4✓ Branch 0 taken 2 times.
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 1 times.
|
10 | else if (acknowledge and not condition) { |
| 158 | // A message can only be acknowledged, if its condition is gone. | ||
| 159 | // Otherwise it would be raised again in the next cycle. | ||
| 160 | 1 | impl->time[i] = 0.0; | |
| 161 | 1 | impl->state[i] = false; | |
| 162 | |||
| 163 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!t.tv_sec) { |
| 164 | 1 | clock_gettime(CLOCK_REALTIME, &t); | |
| 165 | } | ||
| 166 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | pdserv_event_reset(impl->event, i, &t); |
| 167 | } | ||
| 168 | } | ||
| 169 | 12 | } | |
| 170 | |||
| 171 | /****************************************************************************/ | ||
| 172 | |||
| 173 | 12 | bool Message::getState(unsigned int i) const | |
| 174 | { | ||
| 175 | 12 | return impl->state.at(i); | |
| 176 | } | ||
| 177 | |||
| 178 | /****************************************************************************/ | ||
| 179 | |||
| 180 | ✗ | vector<uint8_t> Message::getStateVector() const | |
| 181 | { | ||
| 182 | ✗ | return impl->state; | |
| 183 | } | ||
| 184 | |||
| 185 | /****************************************************************************/ | ||
| 186 | |||
| 187 | ✗ | bool Message::anyState() const | |
| 188 | { | ||
| 189 | ✗ | for (auto state : impl->state) { | |
| 190 | ✗ | if (state) { | |
| 191 | ✗ | return state; | |
| 192 | } | ||
| 193 | } | ||
| 194 | |||
| 195 | ✗ | return false; | |
| 196 | } | ||
| 197 | |||
| 198 | /****************************************************************************/ | ||
| 199 | |||
| 200 | 11 | bool Message::getRising(unsigned int i) const | |
| 201 | { | ||
| 202 |
4/4✓ Branch 2 taken 9 times.
✓ Branch 3 taken 2 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 7 times.
|
11 | return impl->state.at(i) && !impl->prevState.at(i); |
| 203 | } | ||
| 204 | |||
| 205 | /****************************************************************************/ | ||
| 206 | |||
| 207 | ✗ | bool Message::anyRising() const | |
| 208 | { | ||
| 209 | ✗ | for (unsigned int i = 0; i < impl->state.size(); i++) { | |
| 210 | ✗ | if (getRising(i)) { | |
| 211 | ✗ | return true; | |
| 212 | } | ||
| 213 | } | ||
| 214 | |||
| 215 | ✗ | return false; | |
| 216 | } | ||
| 217 | |||
| 218 | /****************************************************************************/ | ||
| 219 |