Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
15  *
16  *
17  * A command line based RDM controller
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 <iomanip>
39 #include <set>
40 #include <string>
41 #include <vector>
42 
43 
44 namespace ola {
45 namespace rdm {
46 
59 using std::endl;
60 using std::set;
61 using std::string;
62 
63 
68  public:
69  explicit RDMMessagePrinter(unsigned int initial_ident = 0)
70  : GenericMessagePrinter(GenericMessagePrinter::DEFAULT_INDENT,
71  initial_ident) {
72  }
73  protected:
74  string TransformLabel(const string &label) {
75  string new_label = label;
76  ola::CustomCapitalizeLabel(&new_label);
77  return new_label;
78  }
79 };
80 
81 
86  public:
87  void Visit(const UIDMessageField *field) {
88  Stream() << field->Value() << endl;
89  }
90 };
91 
92 
97  public:
98  void Visit(const UInt8MessageField *field) {
99  if (m_messages.empty())
100  return;
101  m_messages.back().status_type = field->Value();
102  m_messages.back().status_type_defined = true;
103  }
104 
105  void Visit(const Int16MessageField *field) {
106  if (m_messages.empty())
107  return;
108  status_message &message = m_messages.back();
109  if (message.int_offset < MAX_INT_FIELDS)
110  message.int16_fields[message.int_offset++] = field->Value();
111  }
112 
113  void Visit(const UInt16MessageField *field) {
114  if (m_messages.empty())
115  return;
116  status_message &message = m_messages.back();
117  if (message.uint_offset < MAX_UINT_FIELDS)
118  message.uint16_fields[message.uint_offset++] = field->Value();
119  }
120 
121  void Visit(const GroupMessageField*) {
122  status_message message;
123  m_messages.push_back(message);
124  }
125 
126  protected:
127  void PostStringHook() {
128  vector<status_message>::const_iterator iter = m_messages.begin();
129  for (; iter != m_messages.end(); ++iter) {
130  if (!iter->status_type_defined ||
131  iter->uint_offset != MAX_UINT_FIELDS ||
132  iter->int_offset != MAX_INT_FIELDS) {
133  OLA_WARN << "Invalid status message";
134  continue;
135  }
136 
137  const string message = StatusMessageIdToString(
138  iter->uint16_fields[1],
139  iter->int16_fields[0],
140  iter->int16_fields[1]);
141 
142  Stream() << StatusTypeToString(iter->status_type) << ": ";
143  if (iter->uint16_fields[0])
144  Stream() << "Sub-device " << iter->uint16_fields[0] << ": ";
145 
146  if (message.empty()) {
147  Stream() << " message-id: " <<
148  iter->uint16_fields[1] << ", data1: " << iter->int16_fields[0] <<
149  ", data2: " << iter->int16_fields[1] << endl;
150  } else {
151  Stream() << message << endl;
152  }
153  }
154  }
155 
156  private:
157  enum { MAX_INT_FIELDS = 2 };
158  enum { MAX_UINT_FIELDS = 2 };
159  struct status_message {
160  public:
161  uint16_t uint16_fields[MAX_UINT_FIELDS];
162  int16_t int16_fields[MAX_INT_FIELDS];
163  uint8_t uint_offset;
164  uint8_t int_offset;
165  uint8_t status_type;
166  bool status_type_defined;
167 
168  status_message() : uint_offset(0), int_offset(0), status_type(0),
169  status_type_defined(false) {}
170  };
171  vector<status_message> m_messages;
172 };
173 
174 
179  public:
180  SupportedParamsPrinter(uint16_t manufacturer_id,
181  const RootPidStore *root_store)
182  : m_manufacturer_id(manufacturer_id),
183  m_root_store(root_store) {}
184 
185  void Visit(const UInt16MessageField *message) {
186  m_pids.insert(message->Value());
187  }
188 
189  protected:
190  void PostStringHook() {
191  set<uint16_t>::const_iterator iter = m_pids.begin();
192  for (; iter != m_pids.end(); ++iter) {
193  Stream() << " 0x" << std::hex << *iter;
194  const PidDescriptor *descriptor = m_root_store->GetDescriptor(
195  *iter, m_manufacturer_id);
196  if (descriptor) {
197  string name = descriptor->Name();
198  ola::ToLower(&name);
199  Stream() << " (" << name << ")";
200  }
201  Stream() << endl;
202  }
203  }
204 
205  private:
206  set<uint16_t> m_pids;
207  uint16_t m_manufacturer_id;
208  const RootPidStore *m_root_store;
209 };
210 
211 
216  public:
217  void Visit(const UInt16MessageField *message) {
218  const string name = message->GetDescriptor()->Name();
219  if (name == "product_category")
220  Stream() << TransformLabel(name) << ": " <<
221  ProductCategoryToString(message->Value()) << endl;
222  else
223  GenericMessagePrinter::Visit(message);
224  }
225 
226  protected:
227  string TransformLabel(const string &label) {
228  string new_label = label;
229  ola::CustomCapitalizeLabel(&new_label);
230  return new_label;
231  }
232 };
233 
234 
239  public:
240  void Visit(const StringMessageField *message) {
241  Stream() << message->Value() << endl;
242  }
243 };
244 
245 
250  public:
251  void Visit(const UInt16MessageField *message) {
252  m_product_ids.insert(message->Value());
253  }
254 
255  void PostStringHook() {
256  set<uint16_t>::const_iterator iter = m_product_ids.begin();
257  for (; iter != m_product_ids.end(); ++iter) {
258  Stream() << ProductDetailToString(*iter) << endl;
259  }
260  }
261  private:
262  set<uint16_t> m_product_ids;
263 };
264 
265 
270  public:
271  void Visit(const StringMessageField *message) {
272  m_languages.insert(message->Value());
273  }
274 
275  void PostStringHook() {
276  set<string>::const_iterator iter = m_languages.begin();
277  for (; iter != m_languages.end(); ++iter) {
278  Stream() << *iter << endl;
279  }
280  }
281  private:
282  set<string> m_languages;
283 };
284 
285 
290  public:
291  ClockPrinter() : MessagePrinter(), m_offset(0) {}
292  void Visit(const UInt16MessageField *message) {
293  m_year = message->Value();
294  }
295 
296  void Visit(const UInt8MessageField *message) {
297  if (m_offset < CLOCK_FIELDS)
298  m_fields[m_offset] = message->Value();
299  m_offset++;
300  }
301 
302  void PostStringHook() {
303  if (m_offset != CLOCK_FIELDS) {
304  Stream() << "Malformed packet";
305  }
306  Stream() << std::setfill('0') << std::setw(2) <<
307  static_cast<int>(m_fields[1]) << "/" <<
308  static_cast<int>(m_fields[0]) << "/" <<
309  m_year << " " <<
310  static_cast<int>(m_fields[2]) << ":" <<
311  static_cast<int>(m_fields[3]) << ":" <<
312  static_cast<int>(m_fields[4]) << endl;
313  }
314 
315  private:
316  enum { CLOCK_FIELDS = 5};
317  uint16_t m_year;
318  uint8_t m_fields[CLOCK_FIELDS];
319  unsigned int m_offset;
320 };
321 
326  public:
327  void Visit(const UInt8MessageField *field) {
328  if (m_slot_info.empty())
329  return;
330  m_slot_info.back().type = field->Value();
331  m_slot_info.back().type_defined = true;
332  }
333 
334  void Visit(const UInt16MessageField *field) {
335  if (m_slot_info.empty())
336  return;
337  if (!m_slot_info.back().offset_defined) {
338  m_slot_info.back().offset = field->Value();
339  m_slot_info.back().offset_defined = true;
340  } else {
341  m_slot_info.back().label = field->Value();
342  m_slot_info.back().label_defined = true;
343  }
344  }
345 
346  void Visit(const GroupMessageField*) {
347  slot_info slot;
348  m_slot_info.push_back(slot);
349  }
350 
351  protected:
352  void PostStringHook() {
353  vector<slot_info>::const_iterator iter = m_slot_info.begin();
354  for (; iter != m_slot_info.end(); ++iter) {
355  if (!iter->offset_defined ||
356  !iter->type_defined ||
357  !iter->label_defined) {
358  OLA_WARN << "Invalid slot info";
359  continue;
360  }
361 
362  const string slot = SlotInfoToString(iter->type, iter->label);
363 
364  if (slot.empty()) {
365  Stream() << " offset: " <<
366  iter->offset << ", type: " << iter->type <<
367  ", label: " << iter->label << endl;
368  } else {
369  Stream() << "Slot offset " << iter->offset << ": " << slot << endl;
370  }
371  }
372  }
373 
374  private:
375  struct slot_info {
376  public:
377  uint16_t offset;
378  bool offset_defined;
379  uint8_t type;
380  bool type_defined;
381  uint16_t label;
382  bool label_defined;
383 
384  slot_info() : offset(0), offset_defined(false), type(0),
385  type_defined(false), label(0), label_defined(false) {}
386  };
387  vector<slot_info> m_slot_info;
388 };
389 } // namespace rdm
390 } // namespace ola
391 #endif // INCLUDE_OLA_RDM_RDMMESSAGEPRINTERS_H_