Open Lighting Architecture  0.9.0
 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 /*
37  * The base DMPPDU class.
38  * More specific dmp pdus like the SetPropery inherit from this.
39  */
40 class DMPPDU: public PDU {
41  public:
42  DMPPDU(unsigned int vector, const DMPHeader &dmp_header):
43  PDU(vector, ONE_BYTE),
44  m_header(dmp_header) {
45  }
46  ~DMPPDU() {}
47 
48  unsigned int HeaderSize() const { return DMPHeader::DMP_HEADER_SIZE; }
49  bool PackHeader(uint8_t *data, unsigned int *length) const;
50  void PackHeader(ola::io::OutputStream *stream) const;
51 
52  protected:
53  DMPHeader m_header;
54 };
55 
56 
57 /*
58  * A DMPGetPropertyPDU, templatized by the address type.
59  * Don't create these directly, instead use the helper function below which
60  * enforces compile time consistency.
61  */
62 template <typename Address>
63 class DMPGetProperty: public DMPPDU {
64  public:
65  DMPGetProperty(const DMPHeader &header,
66  const std::vector<Address> &addresses):
68  m_addresses(addresses) {}
69 
70  unsigned int DataSize() const {
71  return static_cast<unsigned int>(m_addresses.size() * m_header.Bytes() *
72  (m_header.Type() == NON_RANGE ? 1 : 3));
73  }
74 
75  bool PackData(uint8_t *data, unsigned int *length) const {
76  typename std::vector<Address>::const_iterator iter;
77  unsigned int offset = 0;
78  for (iter = m_addresses.begin(); iter != m_addresses.end(); ++iter) {
79  unsigned int remaining = *length - offset;
80  if (!iter->Pack(data + offset, &remaining))
81  return false;
82  offset += remaining;
83  }
84  *length = offset;
85  return true;
86  }
87 
88  void PackData(ola::io::OutputStream *stream) const {
89  typename std::vector<Address>::const_iterator iter;
90  for (iter = m_addresses.begin(); iter != m_addresses.end(); ++iter)
91  iter->Write(stream);
92  }
93 
94  private:
95  std::vector<Address> m_addresses;
96 };
97 
98 
99 /*
100  * Create a non-ranged GetProperty PDU
101  * @param type uint8_t, uint16_t or uint32_t
102  * @param is_virtual set to true if this is a virtual address
103  * @param is_relative set to true if this is a relative address
104  * @param addresses a vector of DMPAddress objects
105  */
106 template <typename type>
107 const DMPPDU *NewDMPGetProperty(
108  bool is_virtual,
109  bool is_relative,
110  const std::vector<DMPAddress<type> > &addresses) {
111  DMPHeader header(is_virtual,
112  is_relative,
113  NON_RANGE,
114  TypeToDMPSize<type>());
115  return new DMPGetProperty<DMPAddress<type> >(header, addresses);
116 }
117 
118 
119 /*
120  * Create a non-ranged DMP GetProperty PDU
121  * @param type uint8_t, uint16_t, uint32_t
122  */
123 template <typename type>
124 const DMPPDU *_CreateDMPGetProperty(bool is_virtual,
125  bool is_relative,
126  unsigned int start) {
127  DMPAddress<type> address((type) start);
128  std::vector<DMPAddress<type> > addresses;
129  addresses.push_back(address);
130  return NewDMPGetProperty<type>(is_virtual, is_relative, addresses);
131 }
132 
133 
134 /*
135  * A helper to create a new single, non-ranged GetProperty PDU.
136  * @param is_virtual set to true if this is a virtual address
137  * @param is_relative set to true if this is a relative address
138  * @param start the start offset
139  * @return A pointer to a DMPPDU.
140  */
141 const DMPPDU *NewDMPGetProperty(bool is_virtual,
142  bool is_relative,
143  unsigned int start);
144 
145 
146 /*
147  * Create a Ranged DMP GetProperty Message.
148  * @param type uint8_t, uint16_t or uint32_t
149  * @param is_virtual set to true if this is a virtual address
150  * @param is_relative set to true if this is a relative address
151  * @param addresses a vector of addresses that match the type
152  * @return A pointer to a DMPPDU.
153  */
154 template <typename type>
155 const DMPPDU *NewRangeDMPGetProperty(
156  bool is_virtual,
157  bool is_relative,
158  const std::vector<RangeDMPAddress<type> > &addresses) {
159  DMPHeader header(is_virtual,
160  is_relative,
161  RANGE_SINGLE,
162  TypeToDMPSize<type>());
163  return new DMPGetProperty<RangeDMPAddress<type> >(header, addresses);
164 }
165 
166 
167 template <typename type>
168 const DMPPDU *_CreateRangeDMPGetProperty(bool is_virtual,
169  bool is_relative,
170  unsigned int start,
171  unsigned int increment,
172  unsigned int number) {
173  std::vector<RangeDMPAddress<type> > addresses;
174  RangeDMPAddress<type> address((type) start, (type) increment, (type) number);
175  addresses.push_back(address);
176  return NewRangeDMPGetProperty<type>(is_virtual, is_relative, addresses);
177 }
178 
179 
180 /*
181  * A helper to create a new ranged address GetProperty PDU.
182  * @param is_virtual set to true if this is a virtual address
183  * @param is_relative set to true if this is a relative address
184  * @param start the start offset
185  * @param increment the increments between addresses
186  * @param number the number of addresses defined
187  * @return A pointer to a DMPGetProperty.
188  */
189 const DMPPDU *NewRangeDMPGetProperty(
190  bool is_virtual,
191  bool is_relative,
192  unsigned int start,
193  unsigned int increment,
194  unsigned int number);
195 
196 
197 /*
198  * A DMPSetPropertyPDU, templatized by the address type.
199  * Don't create these directly, instead use the helper functions below which
200  * enforce compile time consistency.
201  * @param type either DMPAddress<> or RangeDMPAddress<>
202  */
203 template <typename type>
204 class DMPSetProperty: public DMPPDU {
205  public:
206  typedef std::vector<DMPAddressData<type> > AddressDataChunks;
207 
208  DMPSetProperty(const DMPHeader &header, const AddressDataChunks &chunks):
210  m_chunks(chunks) {}
211 
212  unsigned int DataSize() const {
213  typename AddressDataChunks::const_iterator iter;
214  unsigned int length = 0;
215  for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter)
216  length += iter->Size();
217  return length;
218  }
219 
220  bool PackData(uint8_t *data, unsigned int *length) const {
221  typename AddressDataChunks::const_iterator iter;
222  unsigned int offset = 0;
223  for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter) {
224  unsigned int remaining = *length - offset;
225  if (!iter->Pack(data + offset, &remaining))
226  return false;
227  offset += remaining;
228  }
229  *length = offset;
230  return true;
231  }
232 
233  void PackData(ola::io::OutputStream *stream) const {
234  typename AddressDataChunks::const_iterator iter;
235  for (iter = m_chunks.begin(); iter != m_chunks.end(); ++iter)
236  iter->Write(stream);
237  }
238 
239  private:
240  AddressDataChunks m_chunks;
241 };
242 
243 
244 /*
245  * Create a new DMP SetProperty Message
246  */
247 template <typename type>
248 const DMPPDU *NewDMPSetProperty(
249  bool is_virtual,
250  bool is_relative,
251  const std::vector<DMPAddressData<DMPAddress<type> > > &chunks) {
252 
253  DMPHeader header(is_virtual,
254  is_relative,
255  NON_RANGE,
256  TypeToDMPSize<type>());
257  return new DMPSetProperty<DMPAddress<type> >(header, chunks);
258 }
259 
260 
261 /*
262  * Create a new DMP SetProperty PDU
263  * @param type either DMPAddress or RangeDMPAddress
264  * @param is_virtual set to true if this is a virtual address
265  * @param is_relative set to true if this is a relative address
266  * @param chunks a vector of DMPAddressData<type> objects
267  */
268 template <typename type>
269 const DMPPDU *NewRangeDMPSetProperty(
270  bool is_virtual,
271  bool is_relative,
272  const std::vector<DMPAddressData<RangeDMPAddress<type> > > &chunks,
273  bool multiple_elements = true,
274  bool equal_size_elements = true) {
275 
276  dmp_address_type address_type;
277  if (multiple_elements) {
278  if (equal_size_elements)
279  address_type = RANGE_EQUAL;
280  else
281  address_type = RANGE_MIXED;
282  } else {
283  address_type = RANGE_SINGLE;
284  }
285 
286  DMPHeader header(is_virtual,
287  is_relative,
288  address_type,
289  TypeToDMPSize<type>());
290  return new DMPSetProperty<RangeDMPAddress<type> >(header, chunks);
291 }
292 } // namespace e131
293 } // namespace plugin
294 } // namespace ola
295 #endif // PLUGINS_E131_E131_DMPPDU_H_