VSM C++ SDK
Vehicle Specific Modules SDK
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
property.h
1 // Copyright (c) 2018, Smart Projects Holdings Ltd
2 // All rights reserved.
3 // See LICENSE file for license details.
4 
5 #ifndef _UGCS_VSM_PROPERTY_H_
6 #define _UGCS_VSM_PROPERTY_H_
7 
8 #include <ucs_vsm_proto.h>
9 #include <ugcs/vsm/utils.h>
10 #include <ugcs/vsm/optional.h>
11 #include <unordered_map>
12 
13 namespace ugcs {
14 namespace vsm {
15 
16 class Property: public std::enable_shared_from_this<Property>
17 {
19 
20 public:
21  typedef enum {
22  VALUE_TYPE_INT = 1,
23  VALUE_TYPE_FLOAT = 2,
24  VALUE_TYPE_DOUBLE = 3,
25  VALUE_TYPE_STRING = 4,
26  VALUE_TYPE_BOOL = 5,
27  VALUE_TYPE_LIST = 6,
28  VALUE_TYPE_ENUM = 7,
29  VALUE_TYPE_NONE = 8,
30  } Value_type;
31 
32  typedef enum {
33  VALUE_SPEC_REGULAR = 1, // Value is valid
34  VALUE_SPEC_NA = 2, // Value is "N/A"
35  } Value_spec;
36 
37  // Create from built in semantics
38  Property(int id, const std::string& name, proto::Field_semantic semantic);
39 
40  // Create with user defined semantic
41  Property(int id, const std::string& name, Value_type type);
42 
43  // Create a copy of property
44  Property(Property::Ptr);
45 
46  // Create and set value. Derive type from value if semantic is not given.
47  // Throws if
48  template<typename Type>
49  Property(const std::string& name, Type value, proto::Field_semantic sem = proto::FIELD_SEMANTIC_DEFAULT):
50  semantic(sem),
51  name(name)
52  {
53  // First make sure that value of valid type has been passed to us (at compile time)
54  static_assert(
62  "Unsupported value type");
63 
64  // Secondly, try to derive semantic from property name
65  if (semantic == proto::FIELD_SEMANTIC_DEFAULT) {
66  semantic = Get_default_semantic(name);
67  }
68 
69  if (semantic == proto::FIELD_SEMANTIC_DEFAULT) {
70  // Semantic is not given then derive property type from value type.
72  type = VALUE_TYPE_BOOL;
73  semantic = proto::FIELD_SEMANTIC_BOOL;
74  } else if (std::is_integral<Type>::value) {
75  type = VALUE_TYPE_INT;
76  semantic = proto::FIELD_SEMANTIC_NUMERIC;
77  } else if (std::is_enum<Type>::value) {
78  type = VALUE_TYPE_ENUM;
79  semantic = proto::FIELD_SEMANTIC_ENUM;
81  type = VALUE_TYPE_FLOAT;
82  semantic = proto::FIELD_SEMANTIC_NUMERIC;
84  type = VALUE_TYPE_DOUBLE;
85  semantic = proto::FIELD_SEMANTIC_NUMERIC;
87  type = VALUE_TYPE_STRING;
88  semantic = proto::FIELD_SEMANTIC_STRING;
89  }
90  } else {
91  type = Get_type_from_semantic(semantic);
92  }
93  Set_value(value);
94  }
95 
96  void
97  Add_enum(const std::string& name, int value);
98 
99  void
100  Set_value(bool v);
101 
102  void
103  Set_value(double v);
104 
105  void
106  Set_value(const std::string& v);
107 
108  void
109  Set_value(const char* v);
110 
111  void
112  Set_value(int v);
113 
114  void
115  Set_value(unsigned int v);
116 
117  void
118  Set_value(const proto::List_value &v);
119 
120  void
121  Set_value_na();
122 
123  // Set value from incoming message
124  bool
125  Set_value(const proto::Field_value& val);
126 
127  void
128  Register(proto::Register_field* field);
129 
130  void
131  Write_as_property(proto::Property_field* field);
132 
133  void
134  Write_as_parameter(proto::Parameter_field* field);
135 
136  void
137  Write_as_telemetry(proto::Telemetry_field* field);
138 
139  void
140  Set_timeout(int);
141 
143  Min_value();
144 
146  Max_value();
147 
149  Default_value();
150 
151  bool
152  Get_value(bool &v); // NOLINT(runtime/references)
153 
154  bool
155  Get_value(float &v); // NOLINT(runtime/references)
156 
157  bool
158  Get_value(double &v); // NOLINT(runtime/references)
159 
160  bool
161  Get_value(std::string& v); // NOLINT(runtime/references)
162 
163  bool
164  Get_value(int &v); // NOLINT(runtime/references)
165 
166  bool
167  Get_value(int64_t &v); // NOLINT(runtime/references)
168 
169  bool
170  Get_value(proto::List_value &v); // NOLINT(runtime/references)
171 
172  bool
173  Is_value_na();
174 
175  // true if value has been changed.
176  // Checks for timeout and automatically sets value to NA and
177  // returns true if value has timeouted.
178  bool
179  Is_changed();
180 
181  // Force sending telemetry on value update even if value has not changed.
182  void
183  Set_changed();
184 
185  int
186  Get_id() {return field_id;}
187 
188  std::string
189  Get_name() {return name;}
190 
191  proto::Field_semantic
192  Get_semantic() {return semantic;}
193 
194  std::chrono::time_point<std::chrono::system_clock>
195  Get_update_time() {return update_time;}
196 
197  std::string
198  Dump_value();
199 
200  bool
201  Fields_are_equal(const proto::Field_value& val1, const proto::Field_value& val2);
202 
203  bool
204  Is_equal(const Property&);
205 
206 private:
207  void
208  Write_value(proto::Field_value* field);
209 
210  bool is_changed = false; // new value set. reset to false after sending to ucs.
211 
212  Value_type type = VALUE_TYPE_NONE;
213  proto::Field_semantic semantic = proto::FIELD_SEMANTIC_DEFAULT;
214 
215  int field_id = 0;
216  std::string name;
217 
218  std::string string_value;
219  bool bool_value = false;
220  double double_value = 0;
221  int64_t int_value = 0;
222  proto::List_value list_value;
223 
224 
225  Property::Ptr default_value;
226  Property::Ptr min_value;
227  Property::Ptr max_value;
228 
229  std::unordered_map<int, std::string> enum_values;
230  std::chrono::seconds timeout = std::chrono::seconds(0); // timeout in seconds
231  Value_spec value_spec = VALUE_SPEC_NA;
232  std::chrono::time_point<std::chrono::system_clock> update_time;
233 
234  // time when field was last sent to server.
235  // Used to throttle telemetry sending to server.
236  std::chrono::time_point<std::chrono::steady_clock> last_commit_time;
237 
238  // do not send telemetry field to server more than 5 times per second.
239  // TODO: make this configurable
240  static constexpr std::chrono::milliseconds COMMIT_TIMEOUT = std::chrono::milliseconds(200);
241 
242  static proto::Field_semantic
243  Get_default_semantic(const std::string& name);
244 
245  static Value_type
246  Get_type_from_semantic(const proto::Field_semantic sem);
247 };
248 
249 class Property_list : public std::unordered_map<std::string, Property::Ptr>
250 {
251 public:
252  template<typename Type>
253  bool
254  Get_value(const std::string& name, Type& value) const // NOLINT(runtime/references)
255  {
256  auto it = find(name);
257  if (it != end() && !it->second->Is_value_na()) {
258  return it->second->Get_value(value);
259  }
260  return false;
261  }
262 
263  // true if property all values are the same in both lists.
264  bool
265  Is_equal(const Property_list&);
266 };
267 
268 
269 } /* namespace vsm */
270 } /* namespace ugcs */
271 
272 #endif /* _UGCS_VSM_PROPERTY_H_ */
Definition: property.h:249
std::shared_ptr< Property > Ptr
Pointer type.
Definition: property.h:18
Various common utilities.
Definition: property.h:16
#define DEFINE_COMMON_CLASS(__class_name,...)
Use this macro to define some common attributes for a class.
Definition: utils.h:25
T value
Stored value (in wire byte order).
Definition: endian.h:356