Skip to content

Commit f46888e

Browse files
committed
upd
1 parent fda6371 commit f46888e

File tree

3 files changed

+168
-101
lines changed

3 files changed

+168
-101
lines changed

README.md

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ bool endPacket();
106106
```
107107

108108
### StreamPacket::Reader
109-
Асинхронный парсер
109+
Асинхронный парсер, работает на буфере Stream (пакеты до 64 байт AVR, 128 байт ESP)
110110

111111
```cpp
112112
// коллбэк вида f(uint8_t type, void* data, size_t len)
@@ -119,6 +119,20 @@ void onData(ParseCallback cb);
119119
void tick();
120120
```
121121
122+
### StreamPacket::ReaderBuf
123+
Асинхронный парсер со своим буфером на любой размер
124+
125+
```cpp
126+
// коллбэк вида f(uint8_t type, void* data, size_t len)
127+
ReaderBuf(Stream& s, ParseCallback cb = nullptr);
128+
129+
// коллбэк вида f(uint8_t type, void* data, size_t len)
130+
void onData(ParseCallback cb);
131+
132+
// тикер, вызывать в loop
133+
void tick();
134+
```
135+
122136
## Примеры
123137
### Отправка
124138
```cpp

library.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name=StreamPacket
2-
version=1.0.1
2+
version=1.0.2
33
author=AlexGyver <[email protected]>
44
maintainer=AlexGyver <[email protected]>
55
sentence=Simple and universal binary protocol for Stream interface

src/StreamPacket.h

Lines changed: 152 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -13,105 +13,9 @@ class StreamPacket {
1313
};
1414

1515
public:
16-
// ================= Sender =================
17-
18-
// chunked отправщик
19-
class Sender {
20-
public:
21-
Sender(Print& s) : _s(s) {}
22-
23-
// начать пакет
24-
template <typename Tp>
25-
bool beginPacket(Tp type, size_t len) {
26-
return StreamPacket::_beginSend(_s, (uint8_t)type, len);
27-
}
28-
29-
// отправить чанк
30-
template <typename Td>
31-
bool send(const Td& data) {
32-
return send(&data, sizeof(Td));
33-
}
34-
35-
// отправить чанк
36-
bool send(const void* data, size_t len) {
37-
_crc = StreamPacket::_crc8(data, len, _crc);
38-
return _s.write((uint8_t*)data, len) == len;
39-
}
40-
41-
// завершить отправку
42-
bool endPacket() {
43-
return _s.write(_crc);
44-
}
45-
46-
private:
47-
Print& _s;
48-
uint8_t _crc = 0;
49-
};
50-
51-
// ================= READER =================
52-
53-
// асинхронный парсер
54-
class Reader {
55-
public:
56-
Reader(Stream& s, ParseCallback cb = nullptr) : _s(s), _cb(cb) {}
57-
58-
// коллбэк вида f(uint8_t type, void* data, size_t len)
59-
void onData(ParseCallback cb) {
60-
_cb = cb;
61-
}
62-
63-
// тикер, вызывать в loop
64-
void tick() {
65-
if (_data) {
66-
if (_s.available()) {
67-
_tmr = millis();
68-
size_t rlen = min(int(_p.length + 1 - _idx), _s.available());
69-
70-
if (_s.readBytes(_data + _idx, rlen) != rlen) {
71-
delete _data;
72-
_data = nullptr;
73-
return;
74-
}
75-
76-
_p.crc = _crc8(_data + _idx, rlen, _p.crc);
77-
_idx += rlen;
78-
79-
if (_idx == _p.length + 1) {
80-
if (!_p.crc) _cb(_p.type, _data, _p.length);
81-
delete _data;
82-
_data = nullptr;
83-
}
84-
85-
} else {
86-
if (millis() - _tmr >= SP_TOUT) {
87-
delete _data;
88-
_data = nullptr;
89-
}
90-
}
91-
92-
} else {
93-
if ((size_t)_s.available() < sizeof(_p) + 1 ||
94-
_s.read() != SP_START ||
95-
_s.readBytes((uint8_t*)&_p, sizeof(_p)) != sizeof(_p) ||
96-
_crc8(&_p, sizeof(_p))) return;
97-
98-
_data = new uint8_t[_p.length + 1];
99-
if (!_data) return;
100-
101-
_idx = 0;
102-
_p.crc = 0;
103-
_tmr = millis();
104-
}
105-
}
106-
107-
private:
108-
Stream& _s;
109-
uint8_t* _data = nullptr;
110-
ParseCallback _cb = nullptr;
111-
Packet _p;
112-
uint32_t _tmr = 0;
113-
uint16_t _idx = 0;
114-
};
16+
class Sender;
17+
class Reader;
18+
class ReaderBuf;
11519

11620
// ================= STATIC =================
11721

@@ -190,4 +94,153 @@ class StreamPacket {
19094
p.crc = _crc8(&p, sizeof(p) - 1);
19195
return s.write((uint8_t)SP_START) == 1 && s.write((uint8_t*)&p, sizeof(p)) == sizeof(p);
19296
}
97+
};
98+
99+
// ================= Sender =================
100+
101+
// chunked отправщик
102+
class StreamPacket::Sender {
103+
public:
104+
Sender(Print& s) : _s(s) {}
105+
106+
// начать пакет
107+
template <typename Tp>
108+
bool beginPacket(Tp type, size_t len) {
109+
return StreamPacket::_beginSend(_s, (uint8_t)type, len);
110+
}
111+
112+
// отправить чанк
113+
template <typename Td>
114+
bool send(const Td& data) {
115+
return send(&data, sizeof(Td));
116+
}
117+
118+
// отправить чанк
119+
bool send(const void* data, size_t len) {
120+
_crc = StreamPacket::_crc8(data, len, _crc);
121+
return _s.write((uint8_t*)data, len) == len;
122+
}
123+
124+
// завершить отправку
125+
bool endPacket() {
126+
return _s.write(_crc);
127+
}
128+
129+
private:
130+
Print& _s;
131+
uint8_t _crc = 0;
132+
};
133+
134+
// ================= READER BUF =================
135+
136+
// асинхронный парсер со своим буфером
137+
class StreamPacket::ReaderBuf {
138+
public:
139+
ReaderBuf(Stream& s, ParseCallback cb = nullptr) : _s(s), _cb(cb) {}
140+
141+
// коллбэк вида f(uint8_t type, void* data, size_t len)
142+
void onData(ParseCallback cb) {
143+
_cb = cb;
144+
}
145+
146+
// тикер, вызывать в loop
147+
void tick() {
148+
if (_data) {
149+
if (_s.available()) {
150+
_tmr = millis();
151+
size_t rlen = min(int(_p.length + 1 - _idx), _s.available());
152+
153+
if (_s.readBytes(_data + _idx, rlen) != rlen) {
154+
delete _data;
155+
_data = nullptr;
156+
return;
157+
}
158+
159+
_p.crc = _crc8(_data + _idx, rlen, _p.crc);
160+
_idx += rlen;
161+
162+
if (_idx == _p.length + 1) {
163+
if (!_p.crc && _cb) _cb(_p.type, _data, _p.length);
164+
delete _data;
165+
_data = nullptr;
166+
}
167+
168+
} else {
169+
if (millis() - _tmr >= SP_TOUT) {
170+
delete _data;
171+
_data = nullptr;
172+
}
173+
}
174+
175+
} else {
176+
if ((size_t)_s.available() < sizeof(_p) + 1 ||
177+
_s.read() != SP_START ||
178+
_s.readBytes((uint8_t*)&_p, sizeof(_p)) != sizeof(_p) ||
179+
_crc8(&_p, sizeof(_p))) return;
180+
181+
_data = new uint8_t[_p.length + 1];
182+
if (!_data) return;
183+
184+
_idx = 0;
185+
_p.crc = 0;
186+
_tmr = millis();
187+
}
188+
}
189+
190+
private:
191+
Stream& _s;
192+
uint8_t* _data = nullptr;
193+
ParseCallback _cb = nullptr;
194+
Packet _p;
195+
uint32_t _tmr = 0;
196+
uint16_t _idx = 0;
197+
};
198+
199+
// ================= READER =================
200+
201+
// асинхронный парсер
202+
class StreamPacket::Reader {
203+
public:
204+
Reader(Stream& s, ParseCallback cb = nullptr) : _s(s), _cb(cb) {}
205+
206+
// коллбэк вида f(uint8_t type, void* data, size_t len)
207+
void onData(ParseCallback cb) {
208+
_cb = cb;
209+
}
210+
211+
// тикер, вызывать в loop
212+
void tick() {
213+
if (_p.length) {
214+
if ((uint16_t)_s.available() >= _p.length) {
215+
uint8_t buf[_p.length];
216+
if (_s.readBytes(buf, _p.length) == _p.length && _cb && !_crc8(buf, _p.length)) {
217+
_cb(_p.type, buf, _p.length - 1);
218+
}
219+
_p.length = 0;
220+
} else if (_pAv != (uint16_t)_s.available()) {
221+
_pAv = _s.available();
222+
_tmr = millis();
223+
} else if (uint16_t(uint16_t(millis()) - _tmr) >= SP_TOUT) {
224+
_p.length = 0;
225+
}
226+
} else {
227+
if ((size_t)_s.available() < sizeof(_p) + 1 ||
228+
_s.read() != SP_START ||
229+
_s.readBytes((uint8_t*)&_p, sizeof(_p)) != sizeof(_p) ||
230+
_crc8(&_p, sizeof(_p))) {
231+
_p.length = 0;
232+
return;
233+
}
234+
++_p.length;
235+
_tmr = millis();
236+
_pAv = 0;
237+
}
238+
}
239+
240+
private:
241+
Stream& _s;
242+
ParseCallback _cb = nullptr;
243+
Packet _p;
244+
uint16_t _pAv = 0;
245+
uint16_t _tmr = 0;
193246
};

0 commit comments

Comments
 (0)