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