Open Lighting Architecture
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DMPPDU.h
1 /*
2  * This program is free software; you can redistribute it and/or modify
3  * it under the terms of the GNU General Public License as published by
4  * the Free Software Foundation; either version 2 of the License, or
5  * (at your option) any later version.
6  *
7  * This program 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
10  * GNU Library General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software
14  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15  *
16  * DMPPDU.h
17  * Interface for the DMP PDU
18  * Copyright (C) 2007-2009 Simon Newton
19  */
20 
21 #ifndef PLUGINS_E131_E131_DMPPDU_H_
22 #define PLUGINS_E131_E131_DMPPDU_H_
23 
24 #include <stdint.h>
25 #include <vector>
26 
27 #include "ola/acn/ACNVectors.h"
28 #include "plugins/e131/e131/DMPAddress.h"
29 #include "plugins/e131/e131/DMPHeader.h"
30 #include "plugins/e131/e131/PDU.h"
31 
32 namespace ola {
33 namespace plugin {
34 namespace e131 {
35 
36 using std::vector;
37 
38 /*
39  * The base DMPPDU class.
40  * More specific dmp pdus like the SetPropery inherit from this.
41  */
42 class DMPPDU: public PDU {
43  public:
44  DMPPDU(unsigned int vector, const DMPHeader &dmp_header):
45  PDU(vector, ONE_BYTE),
46  m_header(dmp_header) {
47  }
48  ~DMPPDU() {}
49 
50  unsigned int HeaderSize() const { return DMPHeader::DMP_HEADER_SIZE; }
51  bool PackHeader(uint8_t *data, unsigned int *length) const;
52  void PackHeader(OutputStream *stream) const;
53 
54  protected:
55  DMPHeader m_header;
56 };
57 
58 
59 /*
60  * A DMPGetPropertyPDU, templatized by the address type.
61  * Don't create these directly, instead use the helper function below which
62  * enforces compile time consistency.
63  */
64 template <typename Address>
65 class DMPGetProperty: public DMPPDU {
66  public:
67  DMPGetProperty(const DMPHeader &header,
68  const vector<Address> &addresses):
70  m_addresses(addresses) {}
71 
72  unsigned int DataSize() const {
73  return static_cast<unsigned int>(m_addresses.size() * m_header.Bytes() *
74  (m_header.Type() == NON_RANGE ? 1 : 3));
75  }
76 
77  bool PackData(uint8_t *data, unsigned int *length) const {
78  typename vector<Address>::const_iterator iter;
79  unsigned int offset = 0;
80  for (iter = m_addresses.begin(); iter != m_addresses.end(); ++iter) {
81  unsigned int remaining = *length - offset;
82  if (!iter->Pack(data + offset, &remaining))
83  return false;
84  offset += remaining;
85  }
86  *length = offset;
87  return true;
88  }
89 
90  void PackData(OutputStream *stream) const {
91  typename vector<Address>::const_iterator iter;
92  for (iter = m_addresses.begin(); iter != m_addresses.end(); ++iter)
93  iter->Write(stream);
94  }
95 
96  private:
97  vector<Address> m_addresses;
98 };
99 
100 
101 /*
102  * Create a non-ranged GetProperty PDU
103  * @param type uint8_t, uint16_t or uint32_t
104  * @param is_virtual set to true if this is a virtual address
105  * @param is_relative set to true if this is a relative address
106  * @param addresses a vector of DMPAddress objects
107  */
108 template <typename type>
109 const DMPPDU *NewDMPGetProperty(
110  bool is_virtual,
111  bool is_relative,
112  const vector<DMPAddress<type> > &addresses) {
113  DMPHeader header(is_virtual,
114  is_relative,
115  NON_RANGE,
116  TypeToDMPSize<type>());
117  return new DMPGetProperty<DMPAddress<type> >(header, addresses);
118 }
119 
120 
121 /*
122  * Create a non-ranged DMP GetProperty PDU
123  * @param type uint8_t, uint16_t, uint32_t
124  */
125 template <typename type>
126 const DMPPDU *_CreateDMPGetProperty(bool is_virtual,
127  bool is_relative,
128  unsigned int start) {
129  DMPAddress<type> address((type) start);
130  vector<DMPAddress<type> > addresses;
131  addresses.push_back(address);
132  return NewDMPGetProperty<type>(is_virtual, is_relative, addresses);
133 }
134 
135 
136 /*
137  * A helper to create a new single, non-ranged GetProperty PDU.
138  * @param is_virtual set to true if this is a virtual address
139  * @param is_relative set to true if this is a relative address
140  * @param start the start offset
141  * @return A pointer to a DMPPDU.
142  */
143 const DMPPDU *NewDMPGetProperty(bool is_virtual,
144  bool is_relative,
145  unsigned int start);
146 
147 
148 /*
149  * Create a Ranged DMP GetProperty Message.
150  * @param type uint8_t, uint16_t or uint32_t
151  * @param is_virtual set to true if this is a virtual address
152  * @param is_relative set to true if this is a relative address
153  * @param addresses a vector of addresses that match the type
154  * @return A pointer to a DMPPDU.
155  */
156 template <typename type>
157 const DMPPDU *NewRangeDMPGetProperty(
158  bool is_virtual,
159  bool is_relative,
160  const vector<RangeDMPAddress<type> > &addresses) {
161  DMPHeader header(is_virtual,
162  is_relative,
163  RANGE_SINGLE,
164  TypeToDMPSize<type>());
165  return new DMPGetProperty<RangeDMPAddress<type> >(header, addresses);
166 }
167 
168 
169 template <typename type>
170 const DMPPDU *_CreateRangeDMPGetProperty(bool is_virtual,
171  bool is_relative,
172  unsigned int start,
173  unsigned int increment,
174  unsigned int number) {
175  vector<RangeDMPAddress<type> > addresses;
176  RangeDMPAddress<type> address((type) start, (type) increment, (type) number);
177  addresses.push_back(address);
178  return NewRangeDMPGetProperty<type>(is_virtual, is_relative, addresses);
179 }
180 
181 
182 /*
183  * A helper to create a new ranged address GetProperty PDU.
184  * @param is_virtual set to true if this is a virtual address
185  * @param is_relative set to true if this is a relative address
186  * @param start the start offset
187  * @param increment the increments between addresses
188  * @param number the number of addresses defined
189  * @return A pointer to a DMPGetProperty.
190  */
191 const DMPPDU *NewRangeDMPGetProperty(
192  bool is_virtual,
193  bool is_relative,
194  unsigned int start,
195  unsigned int increment,
196  unsigned int number);
197 
198 
199 /*
200  * A DMPSetPropertyPDU, templatized by the address type.
201  * Don't create these directly, instead use the helper functions below which
202  * enforce compile time consistency.
203  * @param type either DMPAddress<> or RangeDMPAddress<>
204  */
205 template <typename type>
206 class DMPSetProperty: public DMPPDU {
207  public:
208  typedef vector<DMPAddressData<type> > AddressDataChunks;
209 
210  DMPSetProperty(const DMPHeader &header, const AddressDataChunks &chunks):
212  m_chunks(chunks) {}
213 
214  unsigned int DataSize() const {
215  typename AddressDataChunks::const_iterator iter;
216  unsigned int length = 0;
217  for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter)
218  length += iter->Size();
219  return length;
220  }
221 
222  bool PackData(uint8_t *data, unsigned int *length) const {
223  typename AddressDataChunks::const_iterator iter;
224  unsigned int offset = 0;
225  for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter) {
226  unsigned int remaining = *length - offset;
227  if (!iter->Pack(data + offset, &remaining))
228  return false;
229  offset += remaining;
230  }
231  *length = offset;
232  return true;
233  }
234 
235  void PackData(OutputStream *stream) const {
236  typename AddressDataChunks::const_iterator iter;
237  for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter)
238  iter->Write(stream);
239  }
240 
241  private:
242  AddressDataChunks m_chunks;
243 };
244 
245 
246 /*
247  * Create a new DMP SetProperty Message
248  */
249 template <typename type>
250 const DMPPDU *NewDMPSetProperty(
251  bool is_virtual,
252  bool is_relative,
253  const vector<DMPAddressData<DMPAddress<type> > > &chunks) {
254 
255  DMPHeader header(is_virtual,
256  is_relative,
257  NON_RANGE,
258  TypeToDMPSize<type>());
259  return new DMPSetProperty<DMPAddress<type> >(header, chunks);
260 }
261 
262 
263 /*
264  * Create a new DMP SetProperty PDU
265  * @param type either DMPAddress or RangeDMPAddress
266  * @param is_virtual set to true if this is a virtual address
267  * @param is_relative set to true if this is a relative address
268  * @param chunks a vector of DMPAddressData<type> objects
269  */
270 template <typename type>
271 const DMPPDU *NewRangeDMPSetProperty(
272  bool is_virtual,
273  bool is_relative,
274  const vector<DMPAddressData<RangeDMPAddress<type> > > &chunks,
275  bool multiple_elements = true,
276  bool equal_size_elements = true) {
277 
278  dmp_address_type address_type;
279  if (multiple_elements) {
280  if (equal_size_elements)
281  address_type = RANGE_EQUAL;
282  else
283  address_type = RANGE_MIXED;
284  } else {
285  address_type = RANGE_SINGLE;
286  }
287 
288  DMPHeader header(is_virtual,
289  is_relative,
290  address_type,
291  TypeToDMPSize<type>());
292  return new DMPSetProperty<RangeDMPAddress<type> >(header, chunks);
293 }
294 } // namespace e131
295 } // namespace plugin
296 } // namespace ola
297 #endif // PLUGINS_E131_E131_DMPPDU_H_