Hướng dẫn mqtt to mysql

Hiện nay, MQTT và HTTP là hai giao thức phổ biến bậc nhất dùng cho các thiết bị Internet of Things [IoT], mỗi giao thức được thiết kế sử dụng phù hợp trong các ngữ cảnh khác nhau sẽ giúp hệ thống IoT trở nên linh hoạt và hiệu quả.

Đối với các ứng dụng cần lưu trữ dữ liệu lâu dài và hiển thị website, ngôn ngữ phổ biến mà mình nhận thấy các bạn thường xuyên sử dụng là PHP kết hợp với cơ sở dữ liệu quan hệ MySQL. Phương pháp phổ biến khi kết hợp vào hệ thống IoT là dữ liệu được thiết bị gửi đến máy chủ qua giao thức HTTP theo các phương thức GET, POST,… Tại máy chủ, ngôn ngữ PHP được lập trình sẵn thực hiện đọc dữ liệu gửi đến từ thiết bị và thực thi các câu lệnh truy vấn SQL để lưu trữ vào cơ sở dữ liệu MySQL. Tương tự, trong trường hợp cần hiển thị ra website, ngôn ngữ PHP cũng có thể đọc dữ liệu từ cơ sở dữ liệu MySQL sau đó dữ liệu trả về kết hợp với các ngôn ngữ HTML, CSS, Javascript để hiển thị số liệu cho người dùng giúp giám sát, vận hành hệ thống. Các quá trình trên hoạt động theo mô hình request/response phù hợp để sử dụng ngôn ngữ PHP vốn chạy trên môi trường máy chủ website. Tuy nhiên, việc sử dụng ngôn ngữ PHP cho giao thức MQTT lại không đơn giản như vậy, MQTT hoạt động theo cơ chế publish/subscribe, nghĩa là client cần giữ kết nối liên tục với broker để thực hiện gửi/nhận gói tin liên tục mà không cần kết nối lại, đặc biệt tính chất này rất cần thiết đối với tính năng subscribe để đảm bảo không bị mất dữ liệu. Hiện nay có một số thư viện PHP hỗ trợ thực thi MQTT client bằng cách kết hợp thêm một số cơ chế giữ kết nối với broker tuy nhiên việc sử dụng cũng thường gặp nhiều khó khăn, vì vậy có một cách tốt hơn và cũng dễ thực hiện là có thể kết hợp với một ngôn ngữ khác như Node.js đóng vai trò là MQTT client kết nối giữa thiết bị với cơ sở dữ liệu MySQL và máy chủ website dùng PHP.

Trong bài viết này, mình sẽ hướng dẫn các bạn cách thiết kế kiến trúc máy chủ đơn giản cho hệ thống IoT dùng để quản lý các thiết bị sử dụng giao thức MQTT kết hợp các ngôn ngữ Node.js, PHP và cơ sở dữ liệu MySQL. Trong khuôn khổ bài viết, mình sẽ hướng dẫn cụ thể về chương trình ứng dụng Node.js, còn các nội dung về giao thức MQTT, ngôn ngữ PHP kết hợp MySQL hay thiết kế giao diện website nếu có thời gian mình sẽ hướng dẫn ở những bài viết khác.

Giả sử chúng ta cần thiết kế một hệ thống IoT đơn giản để quản lý thiết bị với các tính năng như sau:
– Thiết bị thu thập dữ liệu cảm biến nhiệt độ, độ ẩm và gửi đến máy chủ định kỳ qua giao thức MQTT [Sensor update]

– Trạng thái Relay sau khi được điều khiển sẽ được thiết bị cập nhật lên máy chủ qua giao thức MQTT [Relay state]

– Tất cả dữ liệu gửi lên từ thiết bị sẽ được lưu trữ vào cơ sơ dữ liệu MySQL [Saving data]

– Từ giao diện website có thể đọc dữ liệu từ cơ sở dữ liệu để hiển thị giám sát [Read data] và gửi dữ liệu điều khiển Relay xuống thiết bị [Relay command]

Chúng ta có thể thiết kế kiến trúc hệ thống như sau:

Giải thích:

Device [Thiết bị]: có thể là một board ESP8266/ESP32, một module sim, một máy tính nhúng,… sao cho có thể kết nối kết nối Internet và giao tiếp với máy chủ qua giao thức MQTT. Nếu các bạn sử dụng board ESP8266 hoặc ESP32 trên nền Arduino IDE thì có thể xem qua các bài hướng dẫn lập trình Internet of Things được nhóm TAPIT IoTs chia sẻ tại đây

– Server [Máy chủ]: 

  • MQTT broker: đây là dịch vụ trung tâm không thể thiếu khi triển khai giao thức MQTT, có nhiệm vụ kết nối các client, lọc và phân phối các gói tin qua cơ chế publish/subscribe. Broker có thể là Mosquitto, Hivemq, EMX, RabbitMQ,..

Các bạn có thể cài đặt broker Mosquitto miễn phí tại đây:

  • app.js: đây là ứng dụng sử dụng ngôn ngữ Node.js đóng vai trò là MQTT client trên máy chủ, là thành phần trung gian để giúp thiết bị với các thành phần khác trên máy chủ [MySQL, dashboard.php] có thể tương tác gửi dữ liệu với nhau. Để chạy được chương trình này, yêu cầu đầu tiên cần phải cài đặt dịch vụ Node.js để làm môi trường cho file thực thi, có thể tải về và cài đặt tại đây. Bên trong chương trình sẽ thực hiện một số tác vụ chính sau [mình sẽ trích dẫn các đoạn chương trình mẫu các bạn có thể sử dụng để tham khảo]:

Kết nối MQTT Broker và xử lý gói tin Subscribe

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

//////////Khai báo module mqtt

varmqtt=require['mqtt'];

//Khai báo tham số kết nối đến Broker

varoptions={clientId: 'ESP32',port:1883,keepalive:60};

//Kết nối đến MQTT Broker với tham số biến option đã khai báo

varclient= mqtt.connect['mqtt://localhost',options]

//Khai báo Connect callback handler [nếu kết nối thành công sẽ thực thi hàm này]

client.on['connect',function[]{

//Subscribe đến topic sensor/update để nhận dữ liệu cảm biến

client.subscribe['sensor/update',function[err]{

console.log["Subscribed to sensor/update topic"];

if [err]{console.log[err];}

}]

//Subscribe đến topic relay/state để nhận dữ liệu cập nhật trạng thái relay

client.subscribe['relay/state',function [err]{

console.log["Subscribed to relay/state topic"];

if[err]{console.log[err];}

}]

}]

//Khai báo Subscribe Callback Handler [Khi nhận được dữ liệu từ các topic đã subscribe sẽ thực thi

//hàm này]

client.on['message',function[topic,message]{

//Nhận dữ liệu và lưu vào biến msg_str

var msg_str=message.toString[];

//In ra console để debug

console.log["[Topic arrived] "+topic];

console.log["[Message arrived] "+msg_str];

if[topic=="sensor/update"]{

//Xử lý dữ liệu

.....

//Lưu trữ vào MySQL

INSERT_SENSOR_DATA[temperature, humidity];

}

elseif[topic=="relay/state"]{

//Xử lý dữ liệu

......

//Lưu trữ vào MySQL

INSERT_RELAY_DATA[relay, state];

}

}]

Kết nối MySQL và viết hàm truy vấn

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

//Khai báo module

vardateTime=require['node-datetime'];

varmysql=require['mysql'];

//Định nghĩa tham số CSDL

var db_config={

host:".....",

user:"....",

password:"....",

database:"....."

}

//Tạo kết nối và xử lý kết nối lại nếu bị mất kết nối đến CSDL

varsql_con;

functionhandleMySQLDisconnect[]{

sql_con=mysql.createConnection[db_config];

sql_con.connect[function[err] {

if[err]{

console.log['Error when connecting to database:',err];

setTimeout[handleDisconnect,2000];

}

console.log["Connected to database!"];

}];

sql_con.on['error',function[err]{

console.log['db error',err];

if[err.code ==='PROTOCOL_CONNECTION_LOST']{

handleMySQLDisconnect[];

}else{

throwerr;

}

}];

}

handleMySQLDisconnect[]; //Thực thi lần đầu tiên

//Viết hàm truy vấn INSERT dữ liệu vào CSDL

functionINSERT_SENSOR_DATA[temperature,humidity]{//Hàm Insert giá trị cảm biến

vardt= dateTime.create[];

vartime_formatted=dt.format['Y-m-d H:M:S'];

varsql="INSERT INTO sensor [datetime, temperature, humidity]"

."VALUES ['"+time_formatted+"', '"+temperature+"', '"+humidity+"']";

sql_con.query[sql, function[err,result]{

if[err]throwerr;

console.log["Insert sensor data successfull!"];

}];

}

functionINSERT_RELAY_DATA[relay,state]{  //Hàm Insert giá trị relay

vardt=dateTime.create[];

var time_formatted=dt.format['Y-m-d H:M:S'];

varsql="INSERT INTO relay"+relay+"[datetime, state]".

"VALUES ['" +time_formatted+"', '"+state+"']";

sql_con.query[sql,function[err,result] {

if[err]throwerr;

console.log["Insert relay data successfull!"];

}];

}

Tạo HTTP server để giao tiếp với website

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

//Khai báo module

constexpress=require['express'];

varcors=require['cors'];

//Tạo HTTP server listening ở port 3001

const server=app.listen[3001,[]=>{

console.log[`ExpressrunningPORT ${server.address[].port}`];

}];

//Xử lý route phương thức GET khi nhận dữ liệu điều khiển từ website với URL

//có dạng là: //localhost:3001/control?RL={relay}&val={state}

//với {relay} là số thứ tự hoặc tên relay và {state} là trạng thái relay

app.get['/control',function[req,res]{

varrl=req.query.RL;

var val=req.query.VAL;

//Tạo chuỗi dữ liệu

varcmd_str="RL"+rl+val;

//Publish đến thiết bị

client.publish['relay/command', cmd_str,function[err]{

if[err]{

res.send["FAILED"];

}

else{

res.send["OK"];

}

}];

}]

  • dashboard.php: trang quản lý hệ thống, có chức năng đọc dữ liệu cảm biến và trạng thái relay trong cơ sở dữ liệu để hiển thị ra website, mặt khác có thể gửi tín hiệu điều khiển đến thiết bị bằng cách gửi HTTP request đến webserver port 3001 được tạo bởi chương trình app.js. Request điều khiển có định dạng là:

//farming.tapit.vn:3001/control?RL={relay}&VAL={state}

Ngoài ra, để dữ liệu hiển theo thời gian thực, có thể kết hợp thêm ngôn ngữ Javascript với kỹ thuật AJAX và hàm setInterval[] để định kỳ request đến một trang PHP đọc dữ liệu từ cơ sở dữ liệu MySQL. Trong khuôn khổ bài viết này mình sẽ không đi sâu vào các kỹ thuật này.

  • MySQL:  là cơ sở dữ liệu lưu trữ dữ liệu gửi lên từ thiết bị gồm giá trị cảm biến và trạng thái relay.

Ví dụ table sensor lưu trữ giá trị cảm biến:

Ví dụ table relay lưu trữ giá trị điều khiển relay: 

Trên đây mình đã hướng dẫn các bạn cách thiết kế một hệ thống IoT để quản lý, điều khiển các thiết kết nối và tương tác với máy chủ qua giao thức MQTT. Hy vọng qua các ví dụ đơn giản trong bài viết sẽ giúp các bạn có thể hiểu và tự mình tạo ra các ứng dụng IoT thật tuyệt vời nhé.
Chúc các bạn thành công.

Xem thêm:

  • [HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]
  • Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32
  • Tổng hợp các bài hướng dẫn Internet of Things với NodeMCU ESP8266 và ESP32

Nhóm TAPIT IoTs

Chủ Đề