Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
U
uni_ete_hepialight_mqtt
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
jonas.stirnema
uni_ete_hepialight_mqtt
Commits
23ce6d6e
Commit
23ce6d6e
authored
1 year ago
by
abivarma.kandiah
Browse files
Options
Downloads
Plain Diff
Merge branch 'mqtt_receive' into 'master'
Merge ESP code to master See merge request
!2
parents
e12f38aa
db046456
Branches
Branches containing commit
No related tags found
1 merge request
!2
Merge ESP code to master
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/mqtt_esp32/mqtt_esp32.ino
+466
-0
466 additions, 0 deletions
src/mqtt_esp32/mqtt_esp32.ino
with
466 additions
and
0 deletions
src/mqtt_esp32/mqtt_esp32.ino
0 → 100644
+
466
−
0
View file @
23ce6d6e
#include
<WiFi.h>
#include
<PubSubClient.h>
#include
<HardwareSerial.h>
#define MATRIX_SIZE 10 // 10x10
#define IMG_DATA_SIZE MATRIX_SIZE * MATRIX_SIZE * 3 //DATA SIZE FOR ONE MATRIX = RGB * MATRIX_SIZE
#define BUFFER_SIZE 128
#define CLUSTER "cluster1"
// WiFi
const
char
*
ssid
=
"uni-ete2"
;
// Enter your WiFi name
const
char
*
password
=
"uni-ete2-esp32"
;
// Enter WiFi password
// MQTT Broker
const
char
*
mqtt_broker
=
"192.168.1.101"
;
const
char
*
topic_send
=
"fromesp"
;
const
char
*
topic_img
=
CLUSTER
"/image"
;
const
char
*
topic_txt
=
CLUSTER
"/text"
;
const
char
*
topic_size
=
CLUSTER
"/size"
;
const
int
mqtt_port
=
1883
;
// WIFI & MQTT
WiFiClient
espClient
;
PubSubClient
client
(
espClient
);
// UART2
HardwareSerial
SerialPort
(
2
);
// use UART2
char
rcv_buffer
[
BUFFER_SIZE
]
=
{
0
};
// MATRIX CLUSTER SIZE
uint8_t
cluster_size_x
=
1
;
uint8_t
cluster_size_y
=
1
;
/**
*@brief
Setup all the peripherals of the ESP32 (UART2 & Software serial).
It will connect automatically to an Hardcoded wifi router,
then it will connect with the MQTT broker.
Finally it will publish a message to the topic,
and will subscribe to the needed sub-topic.
*@params
void
*@return
void
*/
void
setup
()
{
// Set software serial baud to 115200;
Serial
.
begin
(
115200
);
// Set UART2 serial
SerialPort
.
begin
(
115200
,
SERIAL_8N1
,
16
,
17
);
// RX pin: 16, TX pin: 17
// Connecting to a WiFi network
WiFi
.
begin
(
ssid
,
password
);
while
(
WiFi
.
status
()
!=
WL_CONNECTED
)
{
delay
(
500
);
Serial
.
println
(
"Connecting to WiFi.."
);
}
Serial
.
println
(
"Connected to the Wi-Fi network"
);
// Connecting to a mqtt broker
client
.
setServer
(
mqtt_broker
,
mqtt_port
);
client
.
setCallback
(
callback
);
client
.
setBufferSize
(
2000
);
while
(
!
client
.
connected
())
{
String
client_id
=
"esp32-client-"
;
client_id
+=
String
(
WiFi
.
macAddress
());
Serial
.
printf
(
"The client %s connects to the public MQTT broker
\n
"
,
client_id
.
c_str
());
if
(
client
.
connect
(
client_id
.
c_str
()))
{
Serial
.
println
(
"Public EMQX MQTT broker connected"
);
}
else
{
Serial
.
print
(
"failed with state "
);
Serial
.
print
(
client
.
state
());
delay
(
2000
);
}
}
// Publish and subscribe
client
.
publish
(
topic_send
,
"Hi, I'm ESP32 ^^"
);
client
.
subscribe
(
topic_img
);
client
.
subscribe
(
topic_txt
);
}
/**
*@brief
Send an UART message in Pin TX 17 from UART2.
The message will follow the Hepialight2 custom UART format.
Format :
Header : [0x77]
Len : [0x01-0xFF]
Data[0] : [0x00-0xFF]
Data[n] : [0x00-0xFF]
Crc : [0x00-0xFF] = Data[0] ^ Data[1] ^ Data[n] ^ Len
Footer : [0xAA]
*@params
data : data to send to the Hepialight2
length : length of the data
*@return
void
*/
void
send_uart_data
(
const
char
*
data
,
uint8_t
lenght
)
{
// SEND UART PACKET HEADER
SerialPort
.
print
((
char
)
0x77
);
SerialPort
.
print
((
char
)
lenght
);
// SEND DATA AND COMPUTE CRC
uint8_t
crc
=
0
;
for
(
int
i
=
0
;
i
<
lenght
;
i
++
)
{
if
(
data
[
i
]
==
0x77
||
data
[
i
]
==
0x10
||
data
[
i
]
==
0xAA
)
{
crc
=
crc
^
0x10
;
SerialPort
.
print
((
char
)
0x10
);
}
crc
=
crc
^
data
[
i
];
SerialPort
.
print
((
char
)
data
[
i
]);
}
// SEND UART PACKET FOOTER
SerialPort
.
print
((
char
)(
crc
^
lenght
));
SerialPort
.
print
((
char
)
0xAA
);
}
/**
*@brief
Receive an UART message in Pin RX 17 from UART2.
The received message should follow the Hepialight2 custom UART format.
Format :
Header : [0x77]
Len : [0x01-0xFF]
Data[0] : [0x00-0xFF]
Data[n] : [0x00-0xFF]
Crc : [0x00-0xFF] = Data[0] ^ Data[1] ^ Data[n] ^ Len
Footer : [0xAA]
*@params
received_buffer : Will fill the bufeer with
a null-terminated string with the received data
*@return
void
*/
void
receive_uart_data
(
char
*
received_buffer
)
{
static
bool
receiving_data
=
false
;
// Indicator for data reception
static
uint8_t
buffer
[
BUFFER_SIZE
];
// Receive buffer
static
int
buffer_index
=
0
;
// Current buffer index
static
int
message_length
=
0
;
// Length of the currently received message
static
uint8_t
expected_crc
=
0
;
// Expected CRC
uint8_t
received_crc
=
0
;
bool
ctrl_byte
=
false
;
while
(
SerialPort
.
available
())
{
uint8_t
received_byte
=
SerialPort
.
read
();
switch
(
received_byte
)
{
case
0x77
:
// IF 0x10 just before
if
(
ctrl_byte
)
{
buffer
[
buffer_index
++
]
=
received_byte
;
ctrl_byte
=
false
;
continue
;
}
// UART HEADER
buffer_index
=
0
;
receiving_data
=
false
;
break
;
case
0xAA
:
// IF 0x10 just before
if
(
ctrl_byte
)
{
buffer
[
buffer_index
++
]
=
received_byte
;
ctrl_byte
=
false
;
continue
;
}
// UART HEADER
receiving_data
=
false
;
if
(
expected_crc
==
received_crc
)
{
memcpy
(
received_buffer
,
buffer
,
message_length
);
buffer
[
buffer_index
]
=
0
;
return
;
}
break
;
case
0x10
:
// IF 0x10 just before
if
(
!
ctrl_byte
)
{
ctrl_byte
=
true
;
continue
;
}
// DATA
buffer
[
buffer_index
++
]
=
received_byte
;
ctrl_byte
=
false
;
break
;
default
:
// DATA LEN
if
(
!
receiving_data
)
{
message_length
=
received_byte
;
expected_crc
=
received_byte
;
// Expected CRC is initialized with the message length
receiving_data
=
true
;
continue
;
}
// DATA
// GET MESSAGE CRC
if
(
buffer_index
==
message_length
)
{
received_crc
=
received_byte
;
continue
;
}
// Store message bytes in the buffer
buffer
[
buffer_index
++
]
=
received_byte
;
expected_crc
^=
received_byte
;
// Calculate expected CRC
break
;
}
}
}
/**
*@brief
Convert the 2d index to a 1d index.
*@params
x : x index on a 2d space.
x : y index on a 2d space.
pitch : the lenght of the 2d space.
*@return
int : 1d array index
*/
int
d2_to_flat
(
uint8_t
x
,
uint8_t
y
,
uint32_t
pitch
)
{
return
(
x
*
pitch
)
+
y
;
}
/**
*@brief
Remove the header from the ppm image received from
a mqtt message.
*@params
packet : mqtt packet data that contains the ppm image.
lenght : length of the packet data.
*@return
uint8_t* : returns the mqtt packet pointer offset by the header.
*/
uint8_t
*
remove_header_from_ppm
(
uint8_t
*
packet
,
unsigned
int
*
length
)
{
int
cnt
=
0
;
for
(
int
i
=
0
;
i
<
*
length
;
i
++
)
{
if
(
packet
[
i
]
==
'\n'
)
{
cnt
++
;
}
if
(
cnt
>=
3
)
{
*
length
-=
i
-
1
;
return
packet
+
i
+
1
;
}
}
return
NULL
;
}
/**
*@brief
Send the received ppm image to the Hepialight 2 by UART2.
The hepialight2 is adressed by his ID on a 2d space (Example : (0, 0)).
The 24 bits RGB data are refactored in 16 bits data (Hepialigt2 buffer size is limited).
R : 8 bits -> 5 bits
G : 8 bits -> 6 bits
B : 8 bits -> 5 bits
*@params
idx : Hepialight matrix ID-x.
idy : Hepialight matrix ID-y.
data : PPM image data (without PPM header).
lenght : length of the data.
*@return
void
*/
void
send_data_to_matrix
(
uint8_t
idx
,
uint8_t
idy
,
uint8_t
*
data
,
uint32_t
length
)
{
uint8_t
raw_data
[
220
];
char
header
[]
=
"PT;x,y;IMAGE;"
;
strcpy
((
char
*
)
raw_data
,
header
);
raw_data
[
3
]
=
'0'
+
idx
;
raw_data
[
5
]
=
'0'
+
idy
;
uint8_t
send_len
=
13
;
// RGB DATA PROCESS
// HARDCODED
for
(
int
x
=
(
cluster_size_y
-
1
-
idy
)
*
10
;
x
<
(
cluster_size_y
-
idy
)
*
10
;
x
+=
1
)
{
for
(
int
y
=
idx
*
30
;
y
<
(
idx
+
1
)
*
30
;
y
+=
3
)
{
// Serial.println()
int
i
=
d2_to_flat
(
x
,
y
,
30
*
cluster_size_y
);
// COMPUTE COLOR IN 16 BITS
uint8_t
r
=
data
[
i
]
&
0x1F
;
uint8_t
g
=
data
[
i
+
1
]
&
0x3F
;
uint8_t
b
=
data
[
i
+
2
]
&
0x1F
;
uint16_t
rgb
=
r
<<
11
|
g
<<
5
|
b
;
// SPLIT ON 8 BITS
uint8_t
rgb_0
=
rgb
>>
8
;
uint8_t
rgb_1
=
rgb
&
0xFF
;
// SEND RGB
raw_data
[
send_len
++
]
=
rgb_0
;
raw_data
[
send_len
++
]
=
rgb_1
;
}
}
// SEND UART PACKET HEADER
send_uart_data
((
char
*
)
raw_data
,
send_len
);
}
/**
*@brief
Callback function called when the ESP32 receive a mqtt packet.
Only when the ESP32 is subscribed to the right topic.
*@params
topic : The concerned topic.
payload : Received packet.
data : length of the received packet.
*@return
void
*/
void
callback
(
char
*
topic
,
byte
*
payload
,
unsigned
int
length
)
{
// TERMINAL SERIAL
Serial
.
print
(
"Message arrived in topic: "
);
Serial
.
println
(
topic
);
if
(
strcmp
(
topic
,
topic_txt
)
==
0
)
{
char
data
[
100
];
char
header
[]
=
"PT;0,0;MOVING;16711680;0.1;"
;
memcpy
(
data
,
header
,
strlen
(
header
)
+
1
);
// MATRIX ID
data
[
3
]
=
'0'
+
cluster_size_x
-
1
;
data
[
5
]
=
'0'
;
strncat
(
data
,
(
char
*
)
payload
,
length
);
uint32_t
len
=
strlen
(
data
);
// SEND UART PACKET HEADER
SerialPort
.
print
((
char
)
0x77
);
SerialPort
.
print
((
char
)
len
);
uint8_t
crc
=
0
;
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
if
(
data
[
i
]
==
0x77
||
data
[
i
]
==
0x10
||
data
[
i
]
==
0xAA
)
{
crc
=
crc
^
0x10
;
SerialPort
.
print
((
char
)
0x10
);
}
crc
=
crc
^
data
[
i
];
SerialPort
.
print
((
char
)
data
[
i
]);
}
// SEND UART PACKET FOOTER
SerialPort
.
print
((
char
)(
crc
^
len
));
SerialPort
.
print
((
char
)
0xAA
);
return
;
}
// GET RAW DATA
uint8_t
*
raw_data
=
remove_header_from_ppm
(
payload
,
&
length
);
if
(
raw_data
==
NULL
)
{
return
;
}
// SEND UART PACKET FOR EACH MATRIX
for
(
int
x_mat
=
0
;
x_mat
<
cluster_size_x
;
x_mat
++
)
{
for
(
int
y_mat
=
cluster_size_y
-
1
;
y_mat
>=
0
;
y_mat
--
)
{
// SEND UART PACKET
send_data_to_matrix
(
x_mat
,
y_mat
,
raw_data
,
IMG_DATA_SIZE
);
}
}
}
/**
*@brief
Main loop. Handle the mqtt callback function.
When the ESP32 receive a "ESP" UART message, it will respond "OK".
When the ESP32 receive a "MATSIZE" message,
it will update the hepialight2 cluster size
and will publish to the /size subtopic to signal the broker.
*@params
idx : Hepialight matrix ID-x
idy : Hepialight matrix ID-y
data : PPM image data (without PPM header)
lenght : length of the data.
*@return
void
*/
void
loop
()
{
client
.
loop
();
receive_uart_data
(
rcv_buffer
);
// READ UART BUFFER
// CHECK PRESENCE FROM HEPIALIGHT
if
(
strcmp
(
rcv_buffer
,
"ESP"
)
==
0
)
{
Serial
.
println
(
rcv_buffer
);
rcv_buffer
[
0
]
=
0
;
// CLEAR BUFFER
send_uart_data
(
"OK"
,
2
);
// SEND OK
}
// SET MATRIX SIZE
if
(
strncmp
(
rcv_buffer
,
"MATSIZE"
,
7
)
==
0
)
{
Serial
.
println
(
rcv_buffer
);
// GET CLUSTER SIZE
cluster_size_x
=
(
rcv_buffer
[
8
]
+
1
)
-
'0'
;
cluster_size_y
=
(
rcv_buffer
[
10
]
+
1
)
-
'0'
;
rcv_buffer
[
0
]
=
0
;
// CLEAR BUFFER
// PUBLISH NEW CLUSTER SIZE
char
clust_size
[
20
];
char
clust_y
[
10
];
itoa
(
cluster_size_x
*
10
,
clust_size
,
10
);
int
i_0
=
strlen
(
clust_size
);
clust_size
[
i_0
]
=
'x'
;
clust_size
[
i_0
+
1
]
=
0
;
itoa
(
cluster_size_y
*
10
,
clust_y
,
10
);
strcat
(
clust_size
,
clust_y
);
client
.
publish
(
topic_size
,
clust_size
);
}
}
\ No newline at end of file
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment