MySensors Library & Examples  2.3.2-62-ge298769
PJONRouter.h
1 
2 /*-O//\ __ __
3  |-gfo\ |__| | | | |\ | ®
4  |!y°o:\ | __| |__| | \| 13.0
5  |y"s§+`\ multi-master, multi-media bus network protocol
6  /so+:-..`\ Copyright 2010-2020 by Giovanni Blu Mitolo [email protected]
7  |+/:ngr-*.`\
8  |5/:%&-a3f.:;\
9  \+//u/+g%{osv,,\
10  \=+&/osw+olds.\\
11  \:/+-.-°-:+oss\
12  | | \oy\\
13  > <
14 ______-| |-__________________________________________________________________
15 
16 PJONRouter has been contributed by Fred Larsen.
17 
18 It performs the same routing as the PJONSwitch for locally attached buses,
19 but supports a static routing table to enable traversing multiple levels of
20 buses.
21 _____________________________________________________________________________
22 
23 This software is experimental and it is distributed "AS IS" without any
24 warranty, use it at your own risk.
25 
26 Copyright 2010-2020 by Giovanni Blu Mitolo [email protected]
27 
28 Licensed under the Apache License, Version 2.0 (the "License");
29 you may not use this file except in compliance with the License.
30 You may obtain a copy of the License at
31 
32  http://www.apache.org/licenses/LICENSE-2.0
33 
34 Unless required by applicable law or agreed to in writing, software
35 distributed under the License is distributed on an "AS IS" BASIS,
36 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
37 See the License for the specific language governing permissions and
38 limitations under the License. */
39 
40 #pragma once
41 
42 // Add virtual keyword to PJONSimpleSwitch functions
43 #define PJON_ROUTER_NEED_INHERITANCE
44 
45 #include "PJONSwitch.h"
46 
47 #ifndef PJON_ROUTER_TABLE_SIZE
48 #define PJON_ROUTER_TABLE_SIZE 10
49 #endif
50 
51 class PJONRouter : public PJONSwitch
52 {
53 protected:
54  uint8_t remote_bus_ids[PJON_ROUTER_TABLE_SIZE][4];
55  uint8_t remote_bus_via_attached_bus[PJON_ROUTER_TABLE_SIZE];
56  uint8_t table_size = 0;
57 
58  uint8_t find_bus_in_table(
59  const uint8_t *bus_id,
60  const uint8_t /* device_id */,
61  uint8_t &start_bus
62  )
63  {
64  uint8_t start = start_bus - bus_count;
65  for(uint8_t i = start; i < table_size; i++) {
66  if(memcmp(bus_id, remote_bus_ids[i], 4) == 0) {
67  start_bus = bus_count + i + 1; // Continue searching for matches
68  return remote_bus_via_attached_bus[i]; // Explicit bus id match
69  }
70  }
71  start_bus = PJON_NOT_ASSIGNED;
72  return PJON_NOT_ASSIGNED;
73  };
74 
75  virtual uint8_t find_bus_with_id(
76  const uint8_t *bus_id,
77  const uint8_t device_id,
78  uint8_t &start_bus
79  )
80  {
81  // Search for a locally attached bus first
82  uint8_t receiver_bus = PJON_NOT_ASSIGNED;
83  if(start_bus < bus_count) {
84  receiver_bus = find_attached_bus_with_id(bus_id, device_id, start_bus);
85  if(receiver_bus == PJON_NOT_ASSIGNED) {
86  start_bus = bus_count; // Not found among attached
87  }
88  }
89  // Search in the routing table
90  if(
91  (receiver_bus == PJON_NOT_ASSIGNED) &&
92  (start_bus >= bus_count) &&
93  (start_bus != PJON_NOT_ASSIGNED)
94  ) {
95  receiver_bus = find_bus_in_table(bus_id, device_id, start_bus);
96  }
97  if(receiver_bus == PJON_NOT_ASSIGNED) {
98  start_bus = PJON_NOT_ASSIGNED;
99  }
100  return receiver_bus;
101  };
102 
103 public:
104  PJONRouter() {};
105  PJONRouter(
106  uint8_t bus_count,
107  PJONAny * const buses[],
108  uint8_t default_gateway = PJON_NOT_ASSIGNED
109  ) : PJONSwitch(bus_count, buses, default_gateway) { };
110 
111  void add(const uint8_t bus_id[], uint8_t via_attached_bus)
112  {
113  if(table_size < PJON_ROUTER_TABLE_SIZE) {
114  memcpy(remote_bus_ids[table_size], bus_id, 4);
115  remote_bus_via_attached_bus[table_size] = via_attached_bus;
116  table_size++;
117  }
118  };
119 };
120 
121 
122 // Specialized class to simplify declaration when using 2 buses
123 template<class A, class B>
124 class PJONRouter2 : public PJONRouter
125 {
126  StrategyLink<A> linkA;
127  StrategyLink<B> linkB;
128  PJONAny busA, busB;
129 public:
130  PJONRouter2(uint8_t default_gateway = PJON_NOT_ASSIGNED)
131  {
132  PJON<Any>* buses[2] = { &busA, &busB };
133  PJONSimpleSwitch<Any>::connect_buses(2, buses, default_gateway);
134  busA.set_link(&linkA);
135  busB.set_link(&linkB);
136  };
137 
138  PJONAny &get_bus(const uint8_t ix)
139  {
140  return ix == 0 ? busA : busB;
141  }
142 
143  A &get_strategy_0()
144  {
145  return linkA.strategy;
146  }
147  B &get_strategy_1()
148  {
149  return linkB.strategy;
150  }
151 };
152 
153 // Specialized class to simplify declaration when using 3 buses
154 template<class A, class B, class C>
155 class PJONRouter3 : public PJONRouter
156 {
157  StrategyLink<A> linkA;
158  StrategyLink<B> linkB;
159  StrategyLink<C> linkC;
160  PJONAny busA, busB, busC;
161 public:
162  PJONRouter3(uint8_t default_gateway = PJON_NOT_ASSIGNED)
163  {
164  PJON<Any> *buses[3] = { &busA, &busB, &busC };
165  PJONSimpleSwitch<Any>::connect_buses(3, buses, default_gateway);
166  busA.set_link(&linkA);
167  busB.set_link(&linkB);
168  busC.set_link(&linkC);
169  };
170 
171  PJONAny &get_bus(const uint8_t ix)
172  {
173  return ix == 0 ? busA : (ix == 1 ? busB : busC);
174  }
175 
176  A &get_strategy_0()
177  {
178  return linkA.strategy;
179  }
180  B &get_strategy_1()
181  {
182  return linkB.strategy;
183  }
184  C &get_strategy_2()
185  {
186  return linkC.strategy;
187  }
188 };
PJONSwitch
Definition: PJONSwitch.h:77
PJONRouter
Definition: PJONRouter.h:51
PJONAny
Definition: PJONSwitch.h:44
PJONRouter3
Definition: PJONRouter.h:155
PJON< Any >
PJONSimpleSwitch
Definition: PJONSimpleSwitch.h:63
PJONRouter2
Definition: PJONRouter.h:124