48 #include "PJONDynamicRouter.h"
54 #ifndef PJON_VIRTUALBUS_MAX_DEVICES
55 #define PJON_VIRTUALBUS_MAX_DEVICES 255
64 #ifndef PJON_VIRTUALBUS_ROUTE_TIMEOUT_S
65 #define PJON_VIRTUALBUS_ROUTE_TIMEOUT_S 0
68 template<
class RouterClass = PJONSwitch>
73 uint8_t virtual_bus = PJON_NOT_ASSIGNED;
74 uint8_t device_via_attached_bus[PJON_VIRTUALBUS_MAX_DEVICES];
75 #if (PJON_VIRTUALBUS_ROUTE_TIMEOUT != 0)
76 uint32_t device_last_activity_time[PJON_VIRTUALBUS_MAX_DEVICES];
80 bool unknown_device_location =
false;
84 for (uint8_t i=0; i<PJON_VIRTUALBUS_MAX_DEVICES; i++) {
85 device_via_attached_bus[i] = PJON_NOT_ASSIGNED;
89 uint8_t find_vbus_with_device(
const uint8_t *bus_id,
const uint8_t device_id)
91 if (!is_vbus(bus_id) || device_id >= PJON_VIRTUALBUS_MAX_DEVICES) {
92 return PJON_NOT_ASSIGNED;
94 #if (PJON_VIRTUALBUS_ROUTE_TIMEOUT != 0)
96 if ((uint32_t)(PJON_MILLIS() - device_last_activity_time[device_id])
97 > (uint32_t)PJON_VIRTUALBUS_ROUTE_TIMEOUT*1000) {
98 device_via_attached_bus[device_id] = PJON_NOT_ASSIGNED;
101 return device_via_attached_bus[device_id];
104 bool is_vbus(
const uint8_t bus_id[])
106 return virtual_bus < RouterClass::bus_count &&
107 memcmp(RouterClass::buses[virtual_bus]->tx.bus_id, bus_id, 4)==0;
110 void register_device_on_vbus(
const uint8_t device_id,
const uint8_t attached_bus)
112 if (device_id < PJON_VIRTUALBUS_MAX_DEVICES) {
114 if (attached_bus != device_via_attached_bus[device_id]) {
115 Serial.print(F(
"Device "));
116 Serial.print(device_id);
117 Serial.print(F(
" on bus "));
118 Serial.println(attached_bus);
121 device_via_attached_bus[device_id] = attached_bus;
122 #if (PJON_VIRTUALBUS_ROUTE_TIMEOUT != 0)
123 device_last_activity_time[device_id] = PJON_MILLIS();
128 virtual void send_packet(
const uint8_t *payload,
const uint16_t length,
129 const uint8_t receiver_bus,
const uint8_t sender_bus,
134 bool disable_ack = unknown_device_location && is_vbus(RouterClass::buses[receiver_bus]->tx.bus_id);
137 info.header &= ~PJON_ACK_REQ_BIT;
139 bool disable_ack =
true;
140 RouterClass::send_packet(payload, length, receiver_bus, sender_bus, disable_ack, info);
141 #ifdef DEBUG_PRINT_PACKETS
142 Serial.print(F(
"FORWARD NOACK "));
143 Serial.print(info.receiver_id);
144 Serial.print(F(
" to bus "));
145 Serial.println(receiver_bus);
148 RouterClass::send_packet(payload, length, receiver_bus, sender_bus, ack_sent, packet_info);
149 #ifdef DEBUG_PRINT_PACKETS
150 Serial.print(F(
"FORWARD "));
151 Serial.print(packet_info.rx.id);
152 Serial.print(F(
" to bus "));
153 Serial.println(receiver_bus);
158 void handle_send_error(uint8_t code, uint8_t packet)
161 if (PJON_CONNECTION_LOST == code &&
162 is_vbus(RouterClass::buses[RouterClass::current_bus]->tx.bus_id) &&
163 (packet < PJON_MAX_PACKETS || PJON_MAX_PACKETS == 0)) {
165 #if PJON_MAX_PACKETS == 0
166 RouterClass::buses[RouterClass::current_bus]->
167 parse((RouterClass::buses[RouterClass::current_bus]->
data), info);
169 RouterClass::buses[RouterClass::current_bus]->
170 parse((RouterClass::buses[RouterClass::current_bus]->packets[packet].content), info);
172 if (info.rx.id < PJON_VIRTUALBUS_MAX_DEVICES && is_vbus(info.rx.bus_id)) {
176 if (device_via_attached_bus[info.rx.id] == RouterClass::current_bus) {
177 device_via_attached_bus[info.rx.id] = PJON_NOT_ASSIGNED;
179 Serial.print(
"Unregister ");
180 Serial.print(info.rx.id);
181 Serial.print(
" from bus ");
182 Serial.println(RouterClass::current_bus);
189 virtual void dynamic_receiver_function(uint8_t *payload, uint16_t length,
196 if (is_vbus(packet_info.tx.bus_id)) {
197 register_device_on_vbus(packet_info.tx.id, RouterClass::current_bus);
201 uint8_t receiver_bus = find_vbus_with_device(packet_info.rx.bus_id, packet_info.rx.id);
204 if (receiver_bus != PJON_NOT_ASSIGNED) {
205 bool ack_sent =
false;
206 if (receiver_bus != RouterClass::current_bus) {
207 RouterClass::forward_packet(payload, length, receiver_bus, RouterClass::current_bus, ack_sent,
211 unknown_device_location =
true;
212 RouterClass::dynamic_receiver_function(payload, length, packet_info);
213 unknown_device_location =
false;
217 virtual void dynamic_error_function(uint8_t code, uint16_t
data)
219 handle_send_error(code,
data);
230 uint8_t default_gateway = PJON_NOT_ASSIGNED)
231 : RouterClass(bus_count, buses, default_gateway)
239 void set_virtual_bus(uint8_t first_bus)
241 virtual_bus = first_bus;
246 template<
class A,
class B,
class RouterClass = PJONSwitch>
257 busA.set_link(&linkA);
258 busB.set_link(&linkB);
261 PJONAny &get_bus(
const uint8_t ix)
263 return ix == 0 ? busA : busB;
268 return linkA.strategy;
272 return linkB.strategy;
277 template<
class A,
class B,
class C,
class RouterClass = PJONSwitch>
287 PJON<Any>* buses[3] = { &busA, &busB, &busC };
289 busA.set_link(&linkA);
290 busB.set_link(&linkB);
291 busC.set_link(&linkC);
294 PJONAny &get_bus(
const uint8_t ix)
296 return ix == 0 ? busA : (ix == 1 ? busB : busC);
301 return linkA.strategy;
305 return linkB.strategy;
309 return linkC.strategy;