Skip to content

Commit b00e7e1

Browse files
committed
initial version
0 parents  commit b00e7e1

File tree

7 files changed

+376
-0
lines changed

7 files changed

+376
-0
lines changed

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2022 Guilherme Henrique Gregorini Oliveira (Guihgo)
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
# IoT Procotol
2+
3+
IoT Protocol is a protocol over TCP based on HTTP for light data traffic.
4+
5+
## Preamble Version 1
6+
7+
```js
8+
VERSION\n
9+
METHOD+ID\n
10+
PATH\n
11+
[HEADERS\n]
12+
[B\n BODY]
13+
```
14+
15+
### VERSION
16+
17+
Version is the version of iot protocol. Used for compatibility.
18+
19+
- Type: `byte` | `uint8_t`. **REQUIRED**
20+
- Example: `1`
21+
22+
### METHOD_ID
23+
24+
Method ID: METHOD+ID.
25+
26+
Methods:
27+
28+
* Type: `char`. **REQUIRED**
29+
* Example: `R`
30+
31+
- `R` | `0x82`: *Request* method used to do calls needs a response
32+
- `S` | `0x83`: *Signal* method used to send signals like events
33+
34+
35+
ID:
36+
37+
Ramdom number with up to 2^16
38+
39+
* Type: `uint16_t` as Big Endian format. **REQUIRED**
40+
* Example: `1822`
41+
42+
### PATH
43+
44+
The path component contains data, usually organized in hierarchical
45+
form, that, serves to identify a resource [URI > 3.3 Path](https://www.rfc-editor.org/info/rfc3986).
46+
47+
* Type: `uint8_t[]`. **REQUIRED**
48+
* Example:
49+
* `0xA` (10)
50+
* `/foo/bar`
51+
* Default: `/`
52+
53+
### HEADERS
54+
55+
Key Value Pair joined by `:` char, that, serves to set an attribute value for the request. Multiple headers must be separate para SEPARATOR char (`\n`).
56+
57+
* Type: `Map<string, string>`. **OPTIONAL**
58+
* Example:
59+
* Single header: `foo:bar`
60+
* Multiple headers: `foo:bar\nlorem:ipsum`
61+
62+
### BODY
63+
64+
The final data to be used for request receiver. Starts with `B\n`.
65+
66+
* Type: `uint8_t[]`
67+
* Example:
68+
* Message: `B\nlorem ipsum message`
69+
* Buffer: `['B', '\n', 0x1, 0x2, 0x3, 0x4]`
70+
71+
72+
## Middlewares
73+
74+
@TODO Explains what is a middleware and how its works
75+
76+
## Listen
77+
78+
@TODO Explains what listener method does
79+
80+
## Examples
81+
82+
@TODO List of examples on `/examples`
83+
84+
## References
85+
86+
- `HTTP/1.1` Fielding, R., Ed., Nottingham, M., Ed., and J. Reschke, Ed., "HTTP/1.1", STD 99, RFC 9112, DOI 10.17487/RFC9112, June 2022, <https://www.rfc-editor.org/info/rfc9112>.
87+
88+
- `URI` Berners-Lee, T. Fielding, R. L. Masinter "Uniform Resource Identifier (URI): Generic Syntax" STD 66 RFC 3986 DOI 10.17487/RFC3986 <https://www.rfc-editor.org/info/rfc3986>.
89+

iot_helpers.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#include "iot_helpers.h"
2+
3+
4+
int indexOf(uint8_t * buffer, size_t bufLen, char c, size_t start) {
5+
int index = -1;
6+
7+
for(size_t i = start; (i<bufLen && index == -1); i++) {
8+
if(buffer[i] == c) {
9+
index = i;
10+
}
11+
}
12+
13+
return index;
14+
}

iot_helpers.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#pragma once
2+
3+
#ifndef __IOT_HELPERS_H__
4+
#define __IOT_HELPERS_H__
5+
6+
#include "Arduino.h"
7+
8+
int indexOf(uint8_t * buffer, size_t bufLen, char find, size_t start = (size_t)0);
9+
10+
#endif

iot_protocol.cpp

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#include "iot_protocol.h"
2+
3+
void IoTApp::use(IoTMiddleware middleware)
4+
{
5+
this->middlewares.push_back(middleware);
6+
}
7+
8+
void IoTApp::runMiddleware(IoTRequest *request, int index = 0)
9+
{
10+
if (index >= this->middlewares.size())
11+
{
12+
return;
13+
}
14+
15+
Next _next = [this, request, index]()
16+
{
17+
this->runMiddleware(request, (index + 1));
18+
};
19+
20+
this->middlewares.at(index)(request, &_next);
21+
22+
/* If is the last middleware */
23+
if(index == this->middlewares.size()-1) {
24+
/* Free memory */
25+
free(request->path);
26+
free(request->body);
27+
}
28+
}
29+
30+
void IoTApp::listen(Client *client)
31+
{
32+
this->clients.push_back(client);
33+
}
34+
35+
void IoTApp::resetClients() {
36+
this->clients.clear();
37+
}
38+
39+
void IoTApp::onData(Client *client, uint8_t *buffer, size_t bufLen)
40+
{
41+
42+
IoTRequest request = {
43+
1,
44+
EIoTMethod::SIGNAL,
45+
NULL,
46+
std::map<String, String>(),
47+
std::map<String, String>(),
48+
NULL,
49+
0,
50+
client};
51+
52+
int foundN = 0;
53+
int indexStart = 0; // 9
54+
int indexN = -1;
55+
bool isBody = false;
56+
57+
bool invalidRequest = false;
58+
59+
do
60+
{
61+
indexN = indexOf(buffer, bufLen, '\n', indexStart);
62+
63+
uint8_t *bufferPartStart = buffer + indexStart;
64+
size_t bufferPartLength = ((indexN == -1 || isBody) ? (bufLen + 1) : indexN) - indexStart;
65+
66+
uint8_t bufferPart[bufferPartLength];
67+
for (size_t i = 0; i < bufferPartLength; i++)
68+
{
69+
bufferPart[i] = bufferPartStart[i];
70+
}
71+
72+
// [ 0 \n 1 2 \n 3 4 5 \n 6 7 8 9]
73+
switch (foundN)
74+
{
75+
case 0:
76+
if(bufferPartLength > 1) {
77+
invalidRequest = true;
78+
continue;
79+
}
80+
request.version = static_cast<byte>((char)bufferPart[0]);
81+
break;
82+
case 1:
83+
request.method = static_cast<EIoTMethod>((char)bufferPart[0]);
84+
break;
85+
case 2:
86+
request.path = static_cast<char *>(malloc(bufferPartLength * sizeof(char) + 1));
87+
memcpy(request.path, bufferPartStart, bufferPartLength);
88+
request.path[bufferPartLength] = '\0';
89+
/* @TODO: define params */
90+
break;
91+
default:
92+
93+
/* Headers */
94+
// const indexKeyValue = bufferPart.indexOf(":");
95+
int indexKeyValue = indexOf(bufferPart, bufferPartLength, ':');
96+
if (indexKeyValue > 0 && isBody == false)
97+
{
98+
char cBufferPart[bufferPartLength];
99+
memcpy(cBufferPart, bufferPart, bufferPartLength);
100+
101+
String allHeader = String(cBufferPart, bufferPartLength);
102+
103+
String key = allHeader.substring(0, indexKeyValue);
104+
key.trim();
105+
String value = allHeader.substring(indexKeyValue + 1);
106+
value.trim();
107+
108+
request.headers.insert(std::make_pair(key, value));
109+
110+
break;
111+
}
112+
113+
/* Body */
114+
if (isBody == false && bufferPartLength == 1 && static_cast<EIoTRequestPart>((char)bufferPart[0]) == EIoTRequestPart::BODY)
115+
{
116+
isBody = true;
117+
break;
118+
}
119+
120+
if (isBody)
121+
{
122+
request.body = (uint8_t *)(malloc(bufferPartLength * sizeof(uint8_t) + 1));
123+
memcpy(request.body, bufferPartStart, bufferPartLength);
124+
request.body[bufferPartLength] = '\0';
125+
request.bodyLength = bufferPartLength;
126+
isBody = false;
127+
break;
128+
}
129+
}
130+
131+
foundN++;
132+
indexStart = indexN + 1;
133+
134+
} while (indexN >= 0 && invalidRequest == false);
135+
136+
if (invalidRequest) return;
137+
138+
139+
this->runMiddleware(&request);
140+
}
141+
142+
void IoTApp::loop()
143+
{
144+
145+
for (auto client : this->clients)
146+
{
147+
uint8_t buffer[IOT_PROTOCOL_MAX_READ_LENGTH];
148+
int indexBuffer = 0;
149+
while (client->available())
150+
{
151+
buffer[indexBuffer] = client->read();
152+
indexBuffer++;
153+
}
154+
155+
if (indexBuffer > 0)
156+
{
157+
buffer[indexBuffer] = '\0';
158+
this->onData(client, buffer, (indexBuffer - 1));
159+
}
160+
}
161+
}

iot_protocol.h

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#pragma once
2+
3+
#ifndef __IOT_PROTOCOL_H__
4+
#define __IOT_PROTOCOL_H__
5+
6+
// #ifdef __cplusplus
7+
// extern "C"
8+
// {
9+
// #endif
10+
11+
#include "Arduino.h"
12+
#include <vector>
13+
#include <functional>
14+
#include <map>
15+
#include <algorithm>
16+
17+
#include "iot_helpers.h"
18+
19+
#define IOT_PROTOCOL_MAX_READ_LENGTH 1024
20+
21+
enum class EIoTMethod : char
22+
{
23+
SIGNAL = 'S',
24+
REQUEST = 'R'
25+
};
26+
27+
enum class EIoTRequestPart : char
28+
{
29+
BODY = 'B',
30+
};
31+
32+
struct IoTRequest
33+
{
34+
byte version;
35+
EIoTMethod method;
36+
char* path;
37+
std::map<String, String> params;
38+
std::map<String, String> headers;
39+
uint8_t * body;
40+
size_t bodyLength;
41+
Client * client;
42+
};
43+
44+
typedef std::function<void(void)> Next;
45+
46+
typedef void (*IoTMiddleware)(IoTRequest *, Next*);
47+
48+
class IoTApp
49+
{
50+
private:
51+
std::vector<Client *> clients;
52+
void onData(Client* client, uint8_t* buffer, size_t bufLen);
53+
public:
54+
std::vector<IoTMiddleware> middlewares;
55+
56+
void use(IoTMiddleware middleware);
57+
58+
void runMiddleware(IoTRequest *request, int index);
59+
60+
void listen(Client *client);
61+
62+
void resetClients();
63+
64+
void loop();
65+
66+
};
67+
68+
// #ifdef __cplusplus
69+
// }
70+
// #endif
71+
72+
#endif

library.properties

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
name=iot_protocol
2+
version=1.0.0
3+
author=Guihgo
4+
maintainer=Guihgo <guihgo100milha@gmail.com>
5+
sentence=IoT Protocol is a protocol over TCP based on HTTP for light data traffic.
6+
paragraph=IoT Protocol is a protocol over TCP based on HTTP for light data traffic.
7+
category=iot protocol http tcp
8+
url=
9+
architectures=*

0 commit comments

Comments
 (0)