AskSin++
Channel.h
1 //- -----------------------------------------------------------------------------------------------------------------------
2 // AskSin++
3 // 2016-10-31 papa Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
4 //- -----------------------------------------------------------------------------------------------------------------------
5 
6 #ifndef __CHANNEL_H__
7 #define __CHANNEL_H__
8 
9 #include "Peer.h"
10 #include "Storage.h"
11 
12 namespace as {
13 
14 template <class HalType,class List0Type> class Device;
15 class ActionSetMsg;
16 class ActionCommandMsg;
17 class RemoteEventMsg;
18 class SensorEventMsg;
19 
20 template<class HalType,class List1Type,class List3Type,class List4Type,int PeerCount,class List0Type=List0, class List2Type=EmptyList>
21 class Channel {
23  bool change : 1; // the status is changed, we may need to send a status
24  bool inhi : 1;
25  uint8_t num ; // channels per device
26  uint16_t addr ; // start address in eeprom
27 
28 public:
29  typedef List1Type List1;
30  typedef List2Type List2;
31  typedef List3Type List3;
32  typedef List4Type List4;
34 
35  public:
36  Channel () : dev(0), change(false), inhi(false), num(0), addr(0) {}
37 
38  DeviceType& device () { return *dev; }
39 
40  const DeviceType& device () const { return *dev; }
41 
42  uint8_t number () const { return num; }
43 
44  uint16_t address () const { return addr; }
45 
46  uint8_t peers () const { return PeerCount; }
47 
48  bool changed () const { return change; }
49 
50  void changed (bool c) { change = c; }
51 
52  void inhibit (bool value) { inhi = value; }
53 
54  bool inhibit () const { return inhi; }
55 
56  bool aesActive () const { return getList1().aesActive(); }
57 
58  void setup(Device<HalType,List0Type>* dev,uint8_t number,uint16_t addr) {
59  this->dev = dev;
60  this->num = number;
61  this->addr = addr;
62  }
63 
64  uint16_t size () const {
65  uint16_t size = sizeof(Peer);
66  size += List3::size() + List4::size();
67  size *= PeerCount;
68  size += List1::size();
69  return size;
70  }
71 
72  bool has (const Peer& p) const {
73  for( uint8_t i=0; i<peers(); ++i ) {
74  if( p == peer(i) ) {
75  return true;
76  }
77  }
78  return false;
79  }
80 
81  uint8_t peerfor (const HMID& hmid) const {
82  for( uint8_t i=0; i<peers(); ++i ) {
83  if( hmid == peer(i) ) {
84  return i;
85  }
86  }
87  return 0xff;
88  }
89 
90  Peer peer (uint8_t idx) const {
91  Peer result;
92  uint16_t paddr = peerAddress(idx);
93  if( paddr != 0 ) {
94  storage().getData(paddr,&result);
95  }
96  return result;
97  }
98 
99 
100  bool peer (const Peer& p) {
101  deletepeer(p);
102  uint8_t pidx = findpeer();
103  if( pidx != 0xff ) {
104  storage().setData(peerAddress(pidx),p);
105  getList3(pidx).single();
106  return true;
107  }
108  return false;
109  }
110 
111  bool peer (const Peer& p1,const Peer& p2) const {
112  deletepeer(p1);
113  deletepeer(p2);
114  uint8_t pidx1 = findpeer();
115  if( pidx1 != 0xff ) {
116  storage().setData(peerAddress(pidx1),p1);
117  uint8_t pidx2 = findpeer();
118  if( pidx2 != 0xff ) {
119  storage().setData(peerAddress(pidx2),p2);
120  if( p1.odd() == true ) {
121  getList3(pidx1).odd();
122  getList3(pidx2).even();
123  }
124  else {
125  getList3(pidx2).odd();
126  getList3(pidx1).even();
127  }
128  return true;
129  }
130  else {
131  // free already stored data
132  deletepeer(p1);
133  }
134  }
135  return false;
136  }
137 
138  bool deletepeer (uint8_t idx) const {
139  return storage().setData(peerAddress(idx),Peer());
140  }
141 
142  uint8_t findpeer () const {
143  for( int i=0; i<peers(); ++i ) {
144  if( peer(i).valid()==false ) {
145  return i;
146  }
147  }
148  return 0xff;
149  }
150 
151  bool deletepeer (const Peer& p) const {
152  for( uint8_t i=0; i<peers(); ++i ) {
153  if( peer(i) == p ) {
154  deletepeer(i);
155  }
156  }
157  return true;
158  }
159 
160  void firstinit () {
161  storage().clearData(address(),size());
162  List1Type cl1 = getList1();
163  List2Type cl2 = getList2();
164  cl1.defaults();
165  cl2.defaults();
166  }
167 
168  List1Type getList1 () const {
169  // we start always with list1
170  return List1Type(address());
171  }
172 
173  List2Type getList2 () const {
174  return List2Type(address()+List1::size());
175  }
176 
177  List3Type getList3 (const Peer& p) const {
178  uint16_t liststart = 0x00;
179  if( hasList3() == true ) {
180  for( uint8_t i=0; i<peers(); ++i ) {
181  if( peer(i) == p ) {
182  liststart = peerAddress(i) + sizeof(Peer);
183  break;
184  }
185  }
186  }
187  return List3Type(liststart);
188  }
189 
190  List4Type getList4 (const Peer& p) const {
191  uint16_t liststart = 0x00;
192  if( hasList4() == true ) {
193  for( uint8_t i=0; i<peers(); ++i ) {
194  if( peer(i) == p ) {
195  liststart = peerAddress(i) + sizeof(Peer) + List3::size();
196  break;
197  }
198  }
199  }
200  return List4Type(liststart);
201  }
202 
203  List3Type getList3 (uint8_t pidx) const {
204  uint16_t liststart = 0x00;
205  if( hasList3() == true && pidx < peers() ) {
206  liststart = peerAddress(pidx) + sizeof(Peer);
207  }
208  return List3Type(liststart);
209  }
210 
211  List4Type getList4 (uint8_t pidx) const {
212  uint16_t liststart = 0x00;
213  if( hasList4() == true && pidx < peers() ) {
214  liststart = peerAddress(pidx) + sizeof(Peer) + List3::size();
215  }
216  return List4Type(liststart);
217  }
218 
219  static bool hasList3 () {
220  return List3Type::size() > 0;
221  }
222 
223  static bool hasList4 () {
224  return List4Type::size() > 0;
225  }
226 
227  void stop () {}
228 
229  bool process (__attribute__((unused)) const ActionSetMsg& msg) {
230  return false;
231  }
232 
233  bool process (__attribute__((unused)) const ActionCommandMsg& msg) {
234  return false;
235  }
236 
237  bool process (__attribute__((unused)) const RemoteEventMsg& msg) {
238  return false;
239  }
240 
241  bool process (__attribute__((unused)) const SensorEventMsg& msg) {
242  return false;
243  }
244 
245  void patchStatus (__attribute__((unused)) Message& msg) {}
246 
247  void configChanged () {}
248 
249  protected:
250  uint16_t peerAddress (uint8_t pidx) const {
251  if( pidx < PeerCount ) {
252  uint16_t offset = sizeof(Peer);
253  offset += List3::size() + List4::size();
254  offset *= pidx;
255  offset += List1::size() + List2::size();
256  return addr + offset;
257  }
258  return 0x00;
259  }
260 };
261 
262 template <class HalType,class List1Type,class List3Type,int PeerCount,class List0Type, class StateMachine, class List2Type=EmptyList>
263 class ActorChannel : public Channel<HalType,List1Type, List3Type,EmptyList,PeerCount,List0Type, List2Type >, public StateMachine {
264 public:
266  uint8_t lastmsgcnt;
267 
268 public:
269  ActorChannel () : BaseChannel(), lastmsgcnt(0xff) {}
270  ~ActorChannel() {}
271 
272  bool changed () const { return StateMachine::changed(); }
273  void changed (bool c) { StateMachine::changed(c); }
274 
275  void setup(Device<HalType,List0Type>* dev,uint8_t number,uint16_t addr) {
276  BaseChannel::setup(dev,number,addr);
277  StateMachine::setup(this->getList1());
278  }
279 
280  uint8_t status () const {
281  return StateMachine::status();
282  }
283 
284  uint8_t flags () const {
285  uint8_t flags = StateMachine::flags();
286  if( this->device().battery().low() == true ) {
287  flags |= 0x80;
288  }
289  return flags;
290  }
291 
292  void status (uint8_t stat, uint16_t delay) {
293  StateMachine::status(stat,delay);
294  }
295 
296 
297  void stop () {
298  StateMachine::stop();
299  }
300 
301  bool process (__attribute__((unused)) const ActionCommandMsg& msg) {
302  return true;
303  }
304 
305  bool process (const ActionSetMsg& msg) {
306  StateMachine::set( msg.value(), msg.ramp(), msg.delay() );
307  return true;
308  }
309 
310  bool process (const RemoteEventMsg& msg) {
311  bool lg = msg.isLong();
312  Peer p(msg.peer());
313  uint8_t cnt = msg.counter();
314  List3Type l3 = BaseChannel::getList3(p);
315  if( l3.valid() == true ) {
316  // l3.dump();
317  typename List3Type::PeerList pl = lg ? l3.lg() : l3.sh();
318  // pl.dump();
319  if( lg == false || cnt != lastmsgcnt || pl.multiExec() == true ) {
320  lastmsgcnt = cnt;
321  StateMachine::remote(pl,cnt);
322  }
323  return true;
324  }
325  return false;
326  }
327 
328  bool process (const SensorEventMsg& msg) {
329  bool lg = msg.isLong();
330  Peer p(msg.peer());
331  uint8_t cnt = msg.counter();
332  uint8_t value = msg.value();
333  List3Type l3 = BaseChannel::getList3(p);
334  if( l3.valid() == true ) {
335  // l3.dump();
336  typename List3Type::PeerList pl = lg ? l3.lg() : l3.sh();
337  // pl.dump();
338  StateMachine::sensor(pl,cnt,value);
339  return true;
340  }
341  return false;
342  }
343 };
344 
345 
346 template <class HalType,class List0Type=List0>
348 public:
349  VirtBaseChannel () {}
350  virtual ~VirtBaseChannel () {}
351 
352  virtual void setup(Device<HalType,List0Type>* dev,uint8_t number,uint16_t addr) = 0;
353  virtual uint16_t size () const = 0;
354  virtual uint8_t number () const = 0;
355  virtual uint16_t address () const = 0;
356  virtual uint8_t peers () const = 0;
357  virtual bool changed () const = 0;
358  virtual void changed (bool c) = 0;
359  virtual void inhibit (bool value) = 0;
360  virtual bool inhibit () const = 0;
361  virtual bool aesActive () const = 0;
362  virtual bool has (const Peer& p) const = 0;
363  virtual Peer peer (uint8_t idx) const = 0;
364  virtual bool peer (const Peer& p) = 0;
365  virtual bool peer (const Peer& p1,const Peer& p2) = 0;
366  virtual bool deletepeer (const Peer& p) = 0;
367  virtual void firstinit () = 0;
368 
369 #ifndef SENSOR_ONLY
370  virtual void stop () = 0;
371  virtual bool process (const ActionSetMsg& msg) = 0;
372  virtual bool process (const ActionCommandMsg& msg) = 0;
373  virtual bool process (const RemoteEventMsg& msg) = 0;
374  virtual bool process (const SensorEventMsg& msg) = 0;
375 #endif
376  virtual uint8_t status () = 0;
377  virtual uint8_t flags () = 0;
378 
379  virtual void patchStatus (Message& msg) = 0;
380  virtual void configChanged () = 0;
381 
382  virtual GenericList getList1 () const = 0;
383  virtual GenericList getList2 () const = 0;
384  virtual GenericList getList3 (const Peer& p) const = 0;
385  virtual GenericList getList4 (const Peer& p) const = 0;
386  virtual bool hasList3 () const = 0;
387  virtual bool hasList4 () const = 0;
388 
389 };
390 
391 template <class HalType,class ChannelType,class List0Type=List0>
392 class VirtChannel : public VirtBaseChannel<HalType,List0Type> {
393  ChannelType ch;
394 public:
395  VirtChannel () {}
396  virtual ~VirtChannel () {}
397 
398  operator ChannelType& () { return ch; }
399 
400  virtual void setup(Device<HalType,List0Type>* dev,uint8_t number,uint16_t addr) { ch.setup(dev,number,addr); }
401  virtual uint16_t size () const { return ch.size(); }
402  virtual uint8_t number () const { return ch.number(); }
403  virtual uint16_t address () const { return ch.address(); }
404  virtual uint8_t peers () const { return ch.peers(); }
405  virtual bool changed () const { return ch.changed(); }
406  virtual void changed (bool c) { ch.changed(c); }
407  virtual void inhibit (bool value) { ch.inhibit(value); }
408  virtual bool inhibit () const { return ch.inhibit(); }
409  virtual bool aesActive () const { return ch.aesActive(); }
410  virtual bool has (const Peer& p) const { return ch.has(p); };
411  virtual Peer peer (uint8_t idx) const { return ch.peer(idx); }
412  virtual bool peer (const Peer& p) { return ch.peer(p); }
413  virtual bool peer (const Peer& p1,const Peer& p2) { return ch.peer(p1,p2); }
414  virtual bool deletepeer (const Peer& p) { return ch.deletepeer(p); }
415  virtual void firstinit () { ch.firstinit(); }
416 
417 #ifndef SENSOR_ONLY
418  virtual void stop () { ch.stop(); };
419  virtual bool process (const ActionSetMsg& msg) { return ch.process(msg); }
420  virtual bool process (const ActionCommandMsg& msg) { return ch.process(msg); }
421  virtual bool process (const RemoteEventMsg& msg) { return ch.process(msg); }
422  virtual bool process (const SensorEventMsg& msg) { return ch.process(msg); }
423 #endif
424  virtual uint8_t status () { return ch.status(); }
425  virtual uint8_t flags () { return ch.flags(); }
426 
427  virtual void patchStatus (Message& msg) { ch.patchStatus(msg); }
428  virtual void configChanged () { ch.configChanged(); }
429 
430  virtual GenericList getList1 () const { return ch.getList1(); }
431  virtual GenericList getList2 () const { return ch.getList2(); }
432  virtual GenericList getList3 (const Peer& p) const { return ch.getList3(p); }
433  virtual GenericList getList4 (const Peer& p) const { return ch.getList4(p); }
434  virtual bool hasList3 () const { return ChannelType::hasList3(); }
435  virtual bool hasList4 () const { return ChannelType::hasList4(); }
436 };
437 
438 #define channelISR(chan,pin,mode,type) class __##pin##ISRHandler { \
439  public: \
440  static void isr () { chan.handleISR(); } \
441  }; \
442  pinMode(pin,mode); \
443  enableInterrupt(pin,__##pin##ISRHandler::isr,type);
444 
445 
446 }
447 
448 #endif
as::VirtBaseChannel
Definition: Channel.h:347
as::Channel
Definition: Channel.h:21
as::ActionSetMsg
Definition: Message.h:505
as::VirtChannel
Definition: Channel.h:392
as::Message
Definition: Message.h:51
as::Peer
Definition: Peer.h:14
as::Device
Definition: Device.h:80
as::RemoteEventMsg
Definition: Message.h:463
as::SensorEventMsg
Definition: Message.h:480
as::ActionCommandMsg
Definition: Message.h:528
as::StateMachine
Definition: StateMachine.h:14
as::GenericList
Definition: ChannelList.h:72
as::ActorChannel
Definition: Channel.h:263
as::HMID
Definition: HMID.h:14