-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathPjonHlBus.hpp
209 lines (174 loc) · 7.03 KB
/
PjonHlBus.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
// Copyright 2021 Rainer Schoenberger
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include <chrono>
#include <inttypes.h>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <future>
#include <vector>
#include <queue>
#include <list>
#include <iostream>
#include <functional>
#include <cstdlib>
#include "Expect.hpp"
#include "Address.hpp"
#include "Connection.hpp"
#include "BusConfig.hpp"
#include "PJONDefines.h"
template<class Strategy>
class PJON;
namespace PjonHL
{
/// Converts error information (given in PJON Error callback) to a human
/// readable form.
/// @param f_errorCode first argument of error callback function containing error code.
/// @param f_data second argument of error callback function giving context for the error.
std::string PjonErrorToString(uint8_t f_errorCode, uint8_t f_data);
template<class Strategy>
class Connection;
class Logger
{
public:
enum LogLevel
{
Debug,
Info,
Error
};
virtual void log(LogLevel f_level, std::string f_message) = 0;
};
class DefaultLogger : public Logger
{
public:
virtual inline void log(LogLevel f_level, std::string f_message) override
{
std::cout << "PjonHl: " << f_message << std::endl;
}
};
template<class Strategy>
class Bus
{
public:
~Bus();
/// Constructs an instance of Bus.
/// @param f_localAddress address which will be used in outgoing packets,
/// if no local address was explicitly specified for the connection.
/// It will also be used to filter incoming packets.
/// @param f_strategy the underlying physical bus strategy to use.
/// e.g. an instance of ThroughSerial
/// @param f_config optional bus configuration, used to set up the bus.
// see BusConfig struct for default config values used, as
// well as additional details.
Bus(
Address f_localAddress,
Strategy f_strategy,
BusConfig f_config = BusConfig{},
std::unique_ptr<Logger> = std::make_unique<DefaultLogger>()
);
/// Handle which will be returned by createConnection() calls.
/// Holds ownership of a connection and can be used to send/receive packets.
using ConnectionHandle = std::unique_ptr<Connection<Strategy>, std::function<void(Connection<Strategy>*)> >;
/// Creates a connection which can be used to send/receive packets to/from
/// a remote counterpart.
/// - Packets will be sent from the local Address passed in the
/// constructor to the given f_remoteAddress.
/// - Packets are received from this connection only, if both
/// 1. The sender address matches the given f_remoteAddress masked by
/// f_remoteMask.
/// 2. The target address (without port) exactly matches the local address given in
/// the constructor
/// @param f_remoteAddress Address of the remote counterpart.
/// @param f_remoteMask Incoming packets have to match f_remoteAddress
/// combined with f_remoteMask
ConnectionHandle createConnection(
Address f_remoteAddress,
Address f_remoteMask = Address::createAllOneAddress()
);
/// Creates a connection which can be used to send/receive packets to/from
/// a remote counterpart. The local address passed in the constructor
/// of bus has no effect for this connection.
/// It is useful to react to broadcasts or forward packets (routing).
/// - Packets will be sent from f_localAddress to the given
/// f_remoteAddress.
/// - Packets are received from this connection only, if both
/// 1. The sender address matches the given f_remoteAddress masked by
/// f_remoteMask.
/// 2. The target address matches matches the given f_localAddress
/// masked by f_localMask.
ConnectionHandle createDetachedConnection(
Address f_remoteAddress,
Address f_localAddress,
Address f_remoteMask = Address::createAllOneAddress(),
Address f_localMask = Address::createAllOneAddress()
);
/// Stops processing PJON traffic on this Bus.
/// This can be used to prevent any trafic on the bus.
/// NOTE: This might cause packet loss.
/// E.g. - Sensitive devices, which need silence on the bus to prevent noise.
/// - Bus shared with other protocols
void pause();
/// Resumes processing PJON traffic on this Bus.
void resume();
/// Sends a packet without a connection. Should not be used in normal
/// operation.
/// Prefer using connections for sending/receiving instead of this
/// send() function.
std::future<Result> send(
Address f_localAddress,
Address f_remoteAddress,
const std::vector<uint8_t> & f_payload,
uint32_t f_timeout_milliseconds,
bool f_enableRetransmit = true
);
inline Logger & getLogger()
{
return *m_logger;
}
private:
struct TxRequest
{
std::promise<Result> m_successPromise;
std::vector<uint8_t> m_payload;
Address m_localAddress;
Address m_remoteAddress;
uint32_t m_timeoutMilliseconds;
bool m_retransmitEnabled;
size_t m_pjonPacketBufferIndex;
bool m_dispatched = false;
};
void pjonErrorHandler(uint8_t code, uint16_t data, void *custom_pointer);
void pjonReceiveFunction(
uint8_t *payload,
uint16_t length,
const PJON_Packet_Info &packet_info
);
void pjonEventLoop();
void dispatchTxRequest(TxRequest & f_request);
std::recursive_mutex m_txQueueMutex;
std::queue< TxRequest > m_txQueue;
Address m_localAddress;
PJON<Strategy> m_pjon;
std::mutex m_connections_mutex;
std::list<Connection<Strategy>*> m_connections;
std::thread m_eventLoopThread;
std::atomic<bool> m_eventLoopRunning = true;
std::atomic<std::chrono::steady_clock::time_point> m_lastRxTxActivity{std::chrono::steady_clock::now()};
std::unique_ptr<Logger> m_logger;
};
}
#include "PjonHlBus.inl"