小成開發日記----物聯網專案LoveTv實現web網頁傳輸資料到微控制器(技術棧涉及web前端,php後端,c/c++ socket,嵌入式前後端)
作者:小成Charles
原創作品
轉載請標註原創文章地址:http://blog.csdn.net/weixin_42999453/article/details/113502220
一、前言
因為看了B站上稚暉君的嵌入式開發視訊,搞得我這個軟體開發的也想弄一弄嵌入式,然後就設計了一下,做了我這個第一個物聯網專案,我稱之為LoveTV
,這個是做了送給女朋友的,為了方便控制它以及傳輸資料,這裡想到就直接用網頁傳輸資料,這樣很方便!伺服器是要搭建在我的騰訊雲
伺服器,也就是理論上來說,可以在任何地方實現資料傳輸。話不多說,上專案圖!
二、設計思路
上面只是雛形,後期會新增和美化更多功能!這裡我實現網頁控制換頁的方法是網頁通過點選按鈕會執行相應的PHP
檔案,php後端會建立一個udp
協議,然後將資料傳送給用C++
建立的Udp服務端
,服務端收到訊息後會把訊息再轉發給微控制器建立的Udp客戶端
,微控制器客戶端收到資料後會做相應的處理。這就是大致的思路,為了方便理解,我大致的流程畫個圖。
三、核心程式碼(非完整程式碼)
(1)php後端
這裡就是建立socket,指定為udpsocket
,然後直接將資料傳輸給指定的伺服器IP
和埠
,注意php使用socket要到php.ini檔案裡面把extension=sockets
前面的分號去掉,這樣才能使用socket。
<?php
$sock = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP);
$msg = '1';
$len = strlen($msg);
socket_sendto($sock, $msg, $len, 0, serverIp,serverPort);
header("Location: http://lovetv/index.html");
socket_close($sock);
?>
(2)c++後端
這裡主要就是實現資料的轉發,基於C++的框架Qt寫得
tvServer.h
#ifndef TVSERVER_H
#define TVSERVER_H
#include <QUdpSocket>
#include <QObject>
#include <QList>
class tvServer : public QObject
{
Q_OBJECT
public:
explicit tvServer(QObject *parent = nullptr);
QUdpSocket *udpServer;
void bindServer(quint16 port);
quint16 port;
QHostAddress tvAddr;
quint16 tvPort;
QHostAddress webAddr;
quint16 webPort;
bool enter;
signals:
public slots:
void onReadyRead();
};
#endif // TVSERVER_H
tvServer.cpp
#include "tvserver.h"
tvServer::tvServer(QObject *parent) : QObject(parent)
{
udpServer=new QUdpSocket ();
//test ip
tvAddr.setAddress("192.168.1.91");
tvPort=1520;
enter=false;
bindServer(1520);
connect(udpServer,&QUdpSocket::readyRead,this,&tvServer::onReadyRead);
}
void tvServer::bindServer(quint16 port)
{
//bind value
// QHostAddress addr;
// addr.setAddress("192.168.1.110");
if(udpServer->bind(port))
{
qDebug()<<"successful bind!";
}else {
qDebug()<<"falied to bind!";
}
}
void tvServer::onReadyRead()
{
//server to revecive
QByteArray datagram;
datagram.resize(udpServer->pendingDatagramSize());
QHostAddress peerAddr;
quint16 peerPort;
udpServer->readDatagram(datagram.data(),datagram.size(),&peerAddr,&peerPort);
if(QString(datagram.data()) =="tv"&&enter==false)
{
qDebug()<<datagram.data()<<peerAddr<<peerPort;
tvAddr=peerAddr;
tvPort=peerPort;
udpServer->writeDatagram("replay tv",peerAddr,peerPort);
enter=true;
}
if(QString(datagram.data()) =="web"){
webAddr=peerAddr;
webPort=peerPort;
qDebug()<<datagram.data()<<peerAddr<<peerPort;
}
//send msg to tv;
qDebug()<<datagram.data()<<peerAddr<<peerPort;
udpServer->writeDatagram(datagram.data(),tvAddr,tvPort);
}
(3)嵌入式c後端
程式設計IDE用的是Arduino
,然後主機板用的是ESp32
,螢幕就是透明的OLED
螢幕,前端不多說了,主要是利用u8g2
這個圖形框架寫得,後端先連線wifi
,然後利用WiFiUDP
這個庫建立客戶端,一直迴圈去監聽訊息,收到訊息後做出相應的判斷;
這裡是開啟udp
//開啟udp工具
if(udp.begin(WiFi.localIP(),udpLocalPort))
{
Serial.printf("現在收聽IP:%s, UDP埠:%d\n", WiFi.localIP().toString().c_str(), udpLocalPort);
//將wifi資訊傳輸給伺服器
udp.beginPacket(udpServerAddr, udpServerPort);//配置遠端ip地址和埠
udp.print("tv");//把資料寫入傳送緩衝區
udp.endPacket();//傳送資料
}else{
Serial.println("監聽失敗");
}
getUdpMsg()這裡就是一直獲得解析包,可以在loop裡面去一直呼叫這個函式獲得返回資料。
String Network::getUdpMsg()
{
// udp.beginPacket(udpServerAddr, udpServerPort);//配置遠端ip地址和埠
// udp.print("mesg!");//把資料寫入傳送緩衝區
// udp.endPacket();//傳送資料
int packetSize = udp.parsePacket();//獲得解析包
if (packetSize)//解析包不為空
{
//收到Udp資料包
//Udp.remoteIP().toString().c_str()用於將獲取的遠端IP地址轉化為字串
Serial.printf("收到來自遠端IP:%s(遠端埠:%d)的資料包位元組數:%d\n", udp.remoteIP().toString().c_str(), udp.remotePort(), packetSize);
// 解析UDP資料包中的所以資料,以字串格式返回
String udpStringVal = udp.readString();
// 然後向串列埠列印返回的字串
Serial.print("開發板接收到UDP資料中的字串 "); Serial.println(udpStringVal);
return udpStringVal;
}
}
這裡用了一個Chrono
執行緒庫,讓這個函式一直處於一個單獨的執行緒執行
hasPassed()
裡面給的引數越小,延遲就越小,單位為毫秒
if (timeChrono.hasPassed(10) ) {
// elapsed(1000) returns 1 if 1000ms have passed.
timeChrono.restart(); // restart the Chrono
String msgVal= wifi.getUdpMsg();
if(msgVal.toInt()!=0){
nowPage=msgVal.toInt();
Serial.println(nowPage);
}
四、總結和擴充套件
目前還處於雛形階段,就是理論已經成型了,接下來就是完善和優化了,需要改進的就是Udp協議雖然面型無連線但是由於微控制器的效能太低,網路訊號差,特別容易丟包,導致資料接收不到,那麼改進就是換成TCP
協議或者對UDP
協議做一個類似於TCp
三次握手的資料是否接受的檢測來保證資料傳輸到了。
作者:小成Charles
原創作品
轉載請標註原創文章地址:http://blog.csdn.net/weixin_42999453/article/details/113502220
- 小成開發日記----物聯網專案LoveTv實現web網頁傳輸資料到微控制器(技術棧涉及web前端,php後端,c/c socket,嵌入式前後端)
- STM32學習筆記(二十)
- mybatis中:returned more than one row, where no more than one was expected.異常
- SpringBoot SpringSecurity JWT實現認證和授權
- 引燃AI社群,不用跨界也能從文字生成影象,OpenAI新模型打破自然語言與視覺次元壁2 - 知乎
- 手遊作弊(二)-記憶體讀寫例項
- [上海]景慄 (天使輪 A輪A B輪)CDP/MA 35-50K 年終獎
- idea控制檯亂碼(tomcat日誌亂碼)的解決辦法
- 【Linux】硬連結和軟連結
- Nginx負載均衡
- 他本碩博連跨3大專業,畢業後沒多久被破格聘為985高校教授!
- 真漲工資了:多所高校博士生資助標準大幅度提升
- ”12306“秒殺系統的設計藝術
- 實戰排查|為什麼遮擋推流攝像頭,會導致播放綠屏?
- 社群團購是騰訊的電商大賽馬,美團、京東、拼多多合圍買菜:戰無不勝的“流量 資本” - 知乎
- Covetrus完成與原母公司的分離
- 贈書 | 在Python領域,你與專家之間的距離只差這兩本書
- Adam真的是最好的優化器嗎?有人認為不過是神經網路進化的結果 - 知乎
- Spring Cloud Alibaba 新一代微服務解決方案
- 深入解析 C# 的 String.Create 方法