DbcLib 1.0
CAN DBC C++ library.
Loading...
Searching...
No Matches
signalobserver.h
Go to the documentation of this file.
1/*
2* Copyright 2022 Ingemar Hedvall
3* SPDX-License-Identifier: MIT
4 */
8#pragma once
10#include "dbc/signal.h"
11#include <utility>
12#include <memory>
13
14namespace dbc {
24 public:
25 explicit SignalObserver(const Signal& signal);
26 SignalObserver() = delete;
27 ~SignalObserver() override;
28
30 void MaxSamples(size_t max_nof_samples);
32 [[nodiscard]] size_t MaxSamples() const { return value_list_.size();}
33
35 [[nodiscard]] const Signal& GetSignal() const {return signal_;}
36
38 [[nodiscard]] uint64_t Time(size_t index) const;
39
41 [[nodiscard]] uint32_t CanId(size_t index) const;
42
52 template <typename V>
53 bool ChannelValue(size_t index, uint64_t& ns1970, V& value) const;
54
64 template <typename V>
65 bool EngValue(size_t index, uint64_t& ns1970, V& value) const;
66
68
69 [[nodiscard]] size_t FirstIndex() const;
70 [[nodiscard]] size_t LastIndex() const;
72 [[nodiscard]] size_t NofSamples() const {return nof_samples_;}
74 [[nodiscard]] size_t NofValidSamples() const;
75
77 [[nodiscard]] size_t SampleToIndex(size_t sample) const;
78
80 [[nodiscard]] std::pair<size_t, bool> TimeToIndex(uint64_t time) const;
81
82 void DetachObserver() override;
83 void OnSample() override;
84
85 protected:
86 private:
88 struct ChannelSample {
89 uint64_t ns1970 = 0;
90 uint32_t can_id = 0;
91 SignalValue value;
92
94 [[nodiscard]] uint8_t Source() const {
95 return static_cast<uint8_t>(can_id & 0xFF);
96 }
97 };
98 const Signal& signal_;
99 std::vector<ChannelSample> value_list_;
100
101 size_t sample_index_ = 0;
102 size_t nof_samples_ = 0;
103 bool attached_ = false;
104};
105
106template <typename V>
107bool SignalObserver::ChannelValue(size_t index, uint64_t& ns1970,
108 V& value) const {
109 if (index >= value_list_.size()) {
110 return false;
111 }
112 const auto& sample = value_list_[index];
113 bool valid = sample.value.valid;
114 ns1970 = sample.ns1970;
115
116 value = {};
117
118 switch (signal_.DataType()) {
120 try {
121 const auto temp = sample.value.signed_value;
122 value = static_cast<V>(temp);
123 } catch (const std::exception&) {
124 valid = false;
125 }
126 break;
127 }
128
130 size_t bytes = signal_.BitLength() / 8;
131 if ((signal_.BitLength() % 8) != 0) {
132 ++bytes;
133 }
134 if (bytes > 8) {
135 valid = false;
136 } else {
137 try {
138 const auto temp = sample.value.unsigned_value;
139 value = static_cast<V>(temp);
140 } catch (const std::exception&) {
141 valid = false;
142 }
143 }
144 break;
145 }
146
149 try {
150 const auto temp = sample.value.float_value;
151 value = static_cast<V>(temp);
152 } catch (const std::exception&) {
153 valid = false;
154 }
155 break;
156 }
157
158 default:
159 break;
160 }
161 return valid;
162}
164template <>
165bool SignalObserver::ChannelValue(size_t index, uint64_t& ns1970,
166 std::string& value) const;
167
168template <typename V>
169bool SignalObserver::EngValue(size_t index, uint64_t& ns1970,
170 V& value) const {
171 if (index >= value_list_.size()) {
172 return false;
173 }
174 const auto& sample = value_list_[index];
175 bool valid = sample.value.valid;
176 ns1970 = sample.ns1970;
177
178 value = {};
179
180 bool need_to_convert = true;
181 // If it is an enumerate. We could convert the enum string but that's weird.
182 if (!signal_.EnumList().empty()) {
183 need_to_convert = false;
184 }
185 // Avoid truncation
186 if (signal_.Scale() == 1.0 && signal_.Offset() == 0) {
187 need_to_convert = false;
188 }
189
190 switch (signal_.DataType()) {
192 int64_t channel = 0;
193 valid = ChannelValue(index, ns1970, channel);
194
195 if (need_to_convert) {
196 auto temp = static_cast<double>(channel);
197 temp *= signal_.Scale();
198 temp += signal_.Offset();
199 value = static_cast<V>(temp);
200 } else {
201 value = static_cast<V>(channel);
202 }
203 break;
204 }
205
207 uint64_t channel = 0;
208 valid = ChannelValue(index, ns1970, channel);
209 if (need_to_convert) {
210 auto temp = static_cast<double>(channel);
211 temp *= signal_.Scale();
212 temp += signal_.Offset();
213 value = static_cast<V>(temp);
214 } else {
215 value = static_cast<V>(channel);
216 }
217 break;
218 }
219
221 float channel = 0;
222 valid = ChannelValue(index, ns1970, channel);
223 if (need_to_convert) {
224 auto temp = static_cast<double>(channel);
225 temp *= signal_.Scale();
226 temp += signal_.Offset();
227 value = static_cast<V>(temp);
228 } else {
229 value = static_cast<V>(channel);
230 }
231 break;
232 }
233
235 double channel = 0;
236 valid = ChannelValue(index, ns1970, channel);
237 if (need_to_convert) {
238 auto temp = channel;
239 temp *= signal_.Scale();
240 temp += signal_.Offset();
241 value = static_cast<V>(temp);
242 } else {
243 value = static_cast<V>(channel);
244 }
245 break;
246 }
247
248 default:
249 break;
250 }
251 return valid;
252}
253
255template <>
256bool SignalObserver::EngValue(size_t index, uint64_t& ns1970,
257 std::string& value) const;
258
260using SignalObserverList = std::vector<std::unique_ptr<SignalObserver>>;
261
262} // namespace dbc
Interface that handles samples. Internal usage.
Definition: isampleobserver.h:13
Interface against a DBC signal configuration.
Definition: signal.h:68
void BitLength(size_t length)
Sets the bit length.
Definition: signal.h:111
void Offset(double offset)
Sets the offset.
Definition: signal.h:123
void Scale(double scale)
Sets the scaling constant.
Definition: signal.h:120
void EnumList(const std::map< int64_t, std::string > &enum_list)
Sets the enumeration.
void DataType(SignalDataType type)
Sets the data type.
Definition: signal.h:88
The sample observer hold a number of samples.
Definition: signalobserver.h:23
void OnSample() override
On sample callback handler.
size_t NofValidSamples() const
Returns number of valid samples.
uint64_t Time(size_t index) const
Returns the absolute time for a sample.
void ResetSampleIndex()
Reset the sample index.
bool ChannelValue(size_t index, uint64_t &ns1970, V &value) const
Returns the unscaled signal value.
Definition: signalobserver.h:107
size_t FirstIndex() const
First sample.
SignalObserver()=delete
Default constructor.
void MaxSamples(size_t max_nof_samples)
Sets the maximum number of samples.
~SignalObserver() override
Default destructor.
void DetachObserver() override
Detach an observer.
const Signal & GetSignal() const
Returns the signal object.
Definition: signalobserver.h:35
std::pair< size_t, bool > TimeToIndex(uint64_t time) const
Sample time to internal index.
size_t MaxSamples() const
Returns the max number of samples.
Definition: signalobserver.h:32
size_t NofSamples() const
Returns number of samples.
Definition: signalobserver.h:72
uint32_t CanId(size_t index) const
Returns the CAN ID for a sample.
bool EngValue(size_t index, uint64_t &ns1970, V &value) const
Returns the scaled signal value.
Definition: signalobserver.h:169
size_t SampleToIndex(size_t sample) const
Sample number (0..) to internal index.
SignalObserver(const Signal &signal)
Constructor.
size_t LastIndex() const
Last sample.
Internal object that define an observer interface that handle samples.
Main namespace for the DBC library.
Definition: attribute.h:13
@ SignedData
Signed integer.
@ DoubleData
Double value.
@ UnsignedData
Unsigned integer.
@ FloatData
Float value.
std::vector< std::unique_ptr< SignalObserver > > SignalObserverList
List of observer.
Definition: signalobserver.h:260
Interface against a DBC signal configuration.
Support function that holds the channel value for a signal.
Definition: signal.h:18