Open Lighting Architecture  Latest Git
RDMMessagePrinters.h
Go to the documentation of this file.
1 /*
2  * This library is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU Lesser General Public
4  * License as published by the Free Software Foundation; either
5  * version 2.1 of the License, or (at your option) any later version.
6  *
7  * This library is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10  * Lesser General Public License for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public
13  * License along with this library; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
15  *
16  * RDMMessagePrinters.h
17  * Write out RDM Messages in a human-readable format.
18  * Copyright (C) 2010 Simon Newton
19  */
20 
29 #ifndef INCLUDE_OLA_RDM_RDMMESSAGEPRINTERS_H_
30 #define INCLUDE_OLA_RDM_RDMMESSAGEPRINTERS_H_
31 
32 #include <ola/Logging.h>
33 #include <ola/StringUtils.h>
34 #include <ola/messaging/MessagePrinter.h>
35 #include <ola/rdm/PidStore.h>
36 #include <ola/rdm/RDMHelper.h>
37 #include <ola/rdm/UID.h>
38 #include <ola/strings/Format.h>
39 #include <iomanip>
40 #include <set>
41 #include <string>
42 #include <vector>
43 
44 
45 namespace ola {
46 namespace rdm {
47 
52  public:
53  explicit RDMMessagePrinter(unsigned int initial_ident = 0)
55  ola::messaging::GenericMessagePrinter::DEFAULT_INDENT,
56  initial_ident) {
57  }
58  protected:
59  std::string TransformLabel(const std::string &label) {
60  std::string new_label = label;
61  ola::CustomCapitalizeLabel(&new_label);
62  return new_label;
63  }
64 };
65 
66 
71  public:
72  void Visit(const ola::messaging::UIDMessageField *field) {
73  Stream() << field->Value() << std::endl;
74  }
75 };
76 
77 
82  public:
83  void Visit(const ola::messaging::UInt8MessageField *field) {
84  if (m_messages.empty()) {
85  return;
86  }
87  m_messages.back().status_type = field->Value();
88  m_messages.back().status_type_defined = true;
89  }
90 
91  void Visit(const ola::messaging::Int16MessageField *field) {
92  if (m_messages.empty()) {
93  return;
94  }
95  status_message &message = m_messages.back();
96  if (message.int_offset < MAX_INT_FIELDS) {
97  message.int16_fields[message.int_offset++] = field->Value();
98  }
99  }
100 
101  void Visit(const ola::messaging::UInt16MessageField *field) {
102  if (m_messages.empty()) {
103  return;
104  }
105  status_message &message = m_messages.back();
106  if (message.uint_offset < MAX_UINT_FIELDS) {
107  message.uint16_fields[message.uint_offset++] = field->Value();
108  }
109  }
110 
111  void Visit(const ola::messaging::GroupMessageField*) {
112  status_message message;
113  m_messages.push_back(message);
114  }
115 
116  protected:
117  void PostStringHook() {
118  std::vector<status_message>::const_iterator iter = m_messages.begin();
119  for (; iter != m_messages.end(); ++iter) {
120  if (!iter->status_type_defined ||
121  iter->uint_offset != MAX_UINT_FIELDS ||
122  iter->int_offset != MAX_INT_FIELDS) {
123  OLA_WARN << "Invalid status message";
124  continue;
125  }
126 
127  const std::string message = StatusMessageIdToString(
128  iter->uint16_fields[1],
129  iter->int16_fields[0],
130  iter->int16_fields[1]);
131 
132  Stream() << StatusTypeToString(iter->status_type) << ": ";
133  if (iter->uint16_fields[0]) {
134  Stream() << "Sub-device " << iter->uint16_fields[0] << ": ";
135  }
136 
137  if (message.empty()) {
138  Stream() << " message-id: " << iter->uint16_fields[1] << ", data1: "
139  << iter->int16_fields[0] << ", data2: "
140  << iter->int16_fields[1] << std::endl;
141  } else {
142  Stream() << message << std::endl;
143  }
144  }
145  }
146 
147  private:
148  enum { MAX_INT_FIELDS = 2 };
149  enum { MAX_UINT_FIELDS = 2 };
150  struct status_message {
151  public:
152  uint16_t uint16_fields[MAX_UINT_FIELDS];
153  int16_t int16_fields[MAX_INT_FIELDS];
154  uint8_t uint_offset;
155  uint8_t int_offset;
156  uint8_t status_type;
157  bool status_type_defined;
158 
159  status_message() : uint_offset(0), int_offset(0), status_type(0),
160  status_type_defined(false) {}
161  };
162  std::vector<status_message> m_messages;
163 };
164 
165 
170  public:
171  SupportedParamsPrinter(uint16_t manufacturer_id,
172  const RootPidStore *root_store)
173  : m_manufacturer_id(manufacturer_id),
174  m_root_store(root_store) {}
175 
176  void Visit(const ola::messaging::UInt16MessageField *message) {
177  m_pids.insert(message->Value());
178  }
179 
180  protected:
181  void PostStringHook() {
182  std::set<uint16_t>::const_iterator iter = m_pids.begin();
183  for (; iter != m_pids.end(); ++iter) {
184  Stream() << " " << ola::strings::ToHex(*iter);
185  const PidDescriptor *descriptor = m_root_store->GetDescriptor(
186  *iter, m_manufacturer_id);
187  if (descriptor) {
188  std::string name = descriptor->Name();
189  ola::ToLower(&name);
190  Stream() << " (" << name << ")";
191  }
192  Stream() << std::endl;
193  }
194  }
195 
196  private:
197  std::set<uint16_t> m_pids;
198  uint16_t m_manufacturer_id;
199  const RootPidStore *m_root_store;
200 };
201 
202 
207  public:
208  void Visit(const ola::messaging::UInt16MessageField *message) {
209  const std::string name = message->GetDescriptor()->Name();
210  if (name == "product_category") {
211  Stream() << TransformLabel(name) << ": "
212  << ProductCategoryToString(message->Value()) << std::endl;
213  } else {
214  ola::messaging::GenericMessagePrinter::Visit(message);
215  }
216  }
217 
218  protected:
219  std::string TransformLabel(const std::string &label) {
220  std::string new_label = label;
221  ola::CustomCapitalizeLabel(&new_label);
222  return new_label;
223  }
224 };
225 
226 
231  public:
232  void Visit(const ola::messaging::StringMessageField *message) {
233  Stream() << EncodeString(message->Value()) << std::endl;
234  }
235 };
236 
237 
242  public:
243  void Visit(const ola::messaging::UInt16MessageField *message) {
244  m_product_ids.insert(message->Value());
245  }
246 
247  void PostStringHook() {
248  std::set<uint16_t>::const_iterator iter = m_product_ids.begin();
249  for (; iter != m_product_ids.end(); ++iter) {
250  Stream() << ProductDetailToString(*iter) << std::endl;
251  }
252  }
253 
254  private:
255  std::set<uint16_t> m_product_ids;
256 };
257 
258 
263  public:
264  void Visit(const ola::messaging::StringMessageField *message) {
265  m_languages.insert(message->Value());
266  }
267 
268  void PostStringHook() {
269  std::set<std::string>::const_iterator iter = m_languages.begin();
270  for (; iter != m_languages.end(); ++iter) {
271  Stream() << EncodeString(*iter) << std::endl;
272  }
273  }
274  private:
275  std::set<std::string> m_languages;
276 };
277 
278 
283  public:
284  ClockPrinter()
286  m_year(0),
287  m_offset(0) {}
288  void Visit(const ola::messaging::UInt16MessageField *message) {
289  m_year = message->Value();
290  }
291 
292  void Visit(const ola::messaging::UInt8MessageField *message) {
293  if (m_offset < CLOCK_FIELDS) {
294  m_fields[m_offset] = message->Value();
295  }
296  m_offset++;
297  }
298 
299  void PostStringHook() {
300  if (m_offset != CLOCK_FIELDS) {
301  Stream() << "Malformed packet";
302  }
303  Stream() << std::setfill('0') << std::setw(2)
304  << static_cast<int>(m_fields[1]) << "/"
305  << static_cast<int>(m_fields[0]) << "/"
306  << m_year << " "
307  << static_cast<int>(m_fields[2]) << ":"
308  << static_cast<int>(m_fields[3]) << ":"
309  << static_cast<int>(m_fields[4]) << std::endl;
310  }
311 
312  private:
313  enum { CLOCK_FIELDS = 5};
314  uint16_t m_year;
315  uint8_t m_fields[CLOCK_FIELDS];
316  unsigned int m_offset;
317 };
318 
323  public:
324  void Visit(const ola::messaging::UInt8MessageField *field) {
325  if (m_slot_info.empty()) {
326  return;
327  }
328  m_slot_info.back().type = field->Value();
329  m_slot_info.back().type_defined = true;
330  }
331 
332  void Visit(const ola::messaging::UInt16MessageField *field) {
333  if (m_slot_info.empty()) {
334  return;
335  }
336  if (!m_slot_info.back().offset_defined) {
337  m_slot_info.back().offset = field->Value();
338  m_slot_info.back().offset_defined = true;
339  } else {
340  m_slot_info.back().label = field->Value();
341  m_slot_info.back().label_defined = true;
342  }
343  }
344 
345  void Visit(const ola::messaging::GroupMessageField*) {
346  slot_info slot;
347  m_slot_info.push_back(slot);
348  }
349 
350  protected:
351  void PostStringHook() {
352  std::vector<slot_info>::const_iterator iter = m_slot_info.begin();
353  for (; iter != m_slot_info.end(); ++iter) {
354  if (!iter->offset_defined ||
355  !iter->type_defined ||
356  !iter->label_defined) {
357  OLA_WARN << "Invalid slot info";
358  continue;
359  }
360 
361  const std::string slot = SlotInfoToString(iter->type, iter->label);
362 
363  if (slot.empty()) {
364  Stream() << " offset: " << iter->offset << ", type: " << iter->type
365  << ", label: " << iter->label << std::endl;
366  } else {
367  Stream() << "Slot offset " << iter->offset << ": " << slot << std::endl;
368  }
369  }
370  }
371 
372  private:
373  struct slot_info {
374  public:
375  uint16_t offset;
376  bool offset_defined;
377  uint8_t type;
378  bool type_defined;
379  uint16_t label;
380  bool label_defined;
381 
382  slot_info() : offset(0), offset_defined(false), type(0),
383  type_defined(false), label(0), label_defined(false) {}
384  };
385  std::vector<slot_info> m_slot_info;
386 };
387 
388 
393  public:
394  void Visit(const ola::messaging::UInt8MessageField *message) {
395  const std::string name = message->GetDescriptor()->Name();
396  if (name == "type") {
397  Stream() << TransformLabel(name) << ": "
398  << SensorTypeToString(message->Value()) << std::endl;
399  } else if (name == "unit") {
400  Stream() << TransformLabel(name) << ": ";
401  if (message->Value() == UNITS_NONE) {
402  Stream() << "None";
403  } else {
404  Stream() << UnitToString(message->Value());
405  }
406  Stream() << std::endl;
407  } else if (name == "prefix") {
408  Stream() << TransformLabel(name) << ": ";
409  if (message->Value() == PREFIX_NONE) {
410  Stream() << "None";
411  } else {
412  Stream() << PrefixToString(message->Value());
413  }
414  Stream() << std::endl;
415  } else if (name == "supports_recording") {
416  Stream() << TransformLabel(name) << ": ";
417  std::string supports_recording =
418  SensorSupportsRecordingToString(message->Value());
419  if (supports_recording.empty()) {
420  Stream() << "None";
421  } else {
422  Stream() << supports_recording;
423  }
424  Stream() << std::endl;
425  } else {
426  ola::messaging::GenericMessagePrinter::Visit(message);
427  }
428  }
429 
430  protected:
431  std::string TransformLabel(const std::string &label) {
432  std::string new_label = label;
433  ola::CustomCapitalizeLabel(&new_label);
434  return new_label;
435  }
436 };
437 } // namespace rdm
438 } // namespace ola
439 #endif // INCLUDE_OLA_RDM_RDMMESSAGEPRINTERS_H_
string SensorTypeToString(uint8_t type)
Definition: RDMHelper.cpp:673
Definition: RDMMessagePrinters.h:241
Various misc RDM functions.
Definition: RDMMessagePrinters.h:81
string EncodeString(const string &original)
Encode any unprintable characters in a string as hex, returning a copy.
Definition: StringUtils.cpp:302
Definition: MessagePrinter.h:35
string SensorSupportsRecordingToString(uint8_t supports_recording)
Definition: RDMHelper.cpp:756
Holds information about RDM PIDs.
Formatting functions for basic types.
string StatusTypeToString(uint8_t status_type)
Definition: RDMHelper.cpp:1052
A RDM unique identifier (UID).
#define OLA_WARN
Definition: Logging.h:75
Definition: RDMMessagePrinters.h:282
Definition: RDMMessagePrinters.h:70
Definition: RDMMessagePrinters.h:392
Definition: RDMMessagePrinters.h:262
string SlotInfoToString(uint8_t slot_type, uint16_t slot_label)
Definition: RDMHelper.cpp:773
Definition: MessagePrinter.h:70
string StatusMessageIdToString(uint16_t message_id, int16_t data1, int16_t data2)
Definition: RDMHelper.cpp:910
Definition: RDMMessagePrinters.h:230
Definition: RDMMessagePrinters.h:169
Definition: RDMMessagePrinters.h:206
_ToHex< T > ToHex(T v, bool prefix=true)
Convert a value to a hex string.
Definition: Format.h:68
Definition: Message.h:157
Definition: RDMMessagePrinters.h:51
Various string utility functions.
void CustomCapitalizeLabel(string *s)
Similar to CapitalizeLabel() but this also capitalized known acronyms.
Definition: StringUtils.cpp:437
string ProductDetailToString(uint16_t detail)
Definition: RDMHelper.cpp:464
Definition: Message.h:183
The namespace containing all OLA symbols.
Definition: Credentials.cpp:44
string ProductCategoryToString(uint16_t category)
Definition: RDMHelper.cpp:328
string UnitToString(uint8_t unit)
Definition: RDMHelper.cpp:1083
The root of the RDM parameter descriptor store.
Definition: PidStore.h:68
Header file for OLA Logging.
Definition: Message.h:208
void ToLower(string *s)
Convert a string to lower case.
Definition: StringUtils.cpp:404
Definition: RDMMessagePrinters.h:322
Definition: Message.h:242
string PrefixToString(uint8_t prefix)
Definition: RDMHelper.cpp:271
Definition: PidStore.h:246