当前位置:网站首页>Design and implementation of esp32-cam wireless monitoring intelligent gateway
Design and implementation of esp32-cam wireless monitoring intelligent gateway
2022-06-23 10:59:00 【daodanjishui】
ESP32-CAM ArduinoIDE Development series article catalog
Chapter one :ESP32-CAM High cost performance WIFI Quick start tutorial of image transmission scheme
Second articles :ESP32-CAM The first wireless lighting program
Third articles :ESP32-CAM Design and implementation of intelligent gateway
List of articles
Preface
daodanjishui The core original technology of the Internet of things ESP32 Arduino IDE Development of embedded web server setup 、http Request sending, receiving and parsing 、 Single chip microcomputer IO Oral reading and writing operations and AJAX Technology integration constitutes :ESP32-CAM Realize embedded wireless monitoring intelligent gateway .
One 、ESP32-CAM What is the wireless monitoring intelligent gateway ?
In the second part of the project :ESP32-CAM、ESP8266、WIFI、 bluetooth 、 Camera device realizes embedded server lighting , I demonstrated ESP32 Respond to wireless lighting requests as an Internet of things server , The way to submit forms with a browser lights up ESP32-cam Integrated on the module LED Flash lighting to achieve the functions that an embedded server can achieve , Readers who don't understand it can go to the second .
In this third article , I will add more functions to the official program , That is to add functions on the basis of the second chapter , Program development is a step-by-step process .
The added functions are as follows :
(1) Embedded in the web page of the SCM server AJAX technology , By clicking the button cmd Submit the form request asynchronously to partially refresh the page , Don't worry about the whole page being refreshed , This function is necessary for developing web remote control ! It is also necessary to make a web remote control intelligent car . As shown by the arrow below :
(2) After the server responds to a browser client button request, there will be an asynchronous refresh response , For example, once off After the operation of , The server will return a red “off ok” Go to the back of the feedback column , There will never be a web page Jump , This is a necessary function for human-computer interaction and environment parameter acquisition and display of intelligent gateway , There is also a function of querying instructions , Input check, Click send to query LED Operating state , This function makes a start to query the operation status of the single chip microcomputer . As shown in the figure below :
(3) Add two web page Jump links to the homepage of the server ,“ Turn on the light quickly ” and “ Quick video ”, Clicking the first link will jump to another page and light up ESP32 The lamp of , Click the second link to see ESP32 Video captured by camera module . This is the jump technology and video streaming technology to realize the web page on the server home page , Making advertising gateway and intelligent surveillance camera must not miss the function . As shown in the figure below :
The video image taken while turning on the lights is shown in the following figure :
(4) Will server's IP The address is displayed on the browser of the client , It is believed that many buyers want to realize this function but fail to realize it ? Although I rely on serial port to print this code IP Enter the address into the browser to access the server's home page , But in the next project, I will add the functions of browser distribution and domain name resolution , Enter a fixed domain name to log in to the server's home page , Only then did I realize how important this function is . The technical points involved cannot be expressed in a few words !IP Will change as the network changes , Not a static web page . As shown in the figure below :
watch daodanjishui The Youku video address is :https://v.youku.com/v_show/id_XNTE3ODY4MjYwMA==.html
Watch directly
Two 、 The development process
1. Modification based on official code
There are two ways to submit the source code of this version get and post request , One is asynchronous submission ; One is to refresh the web page submission and get the server response directly , But refreshing the submission form will jump to the web page , A shortcut to submit forms is also presented , There is also a query light status check Function of instruction .
It took me two days to write this program , The difficulty is that the web page is converted to a string , Writing too large a web page will overflow the memory of the MCU , So I also deleted the comments on the web page , Just to reduce space .
Another way is to put html Webpage , course :
https://blog.csdn.net/qq_27114397/article/details/89643232
- First, through gzip take HTML The file is compressed to .gz file
- Use filetoarray Tools will .gz File to header file
- stay ESP32 The program sends out the array in the header file
The code of the official code is just like this , But I think it's too much trouble , Just convert the URL to a string , So the size is limited , Used a string , I would also like to consider String Of html Converts a string to an array of characters , In this way, the incoming function can be sent out . Here is the code :
int length=index_html.length();
char buf[length];
strcpy(buf, index_html.c_str());
return httpd_resp_send(req, buf,sizeof(buf)/sizeof(buf[0]));
Another problem is parsing the original web page , At that time, I always wanted to restore and compress the official source code into 16 Binary web page data source code , Later, it is reduced to garbled code , After that, you can directly run the official source code , Log in directly from the browser to the home page and press F12 Saved URL , Finally, I saw the source code of the web page , I didn't know how happy I was .
After getting the source code, I found , send out get The requested code is not obvious , It looks like a script , It's a mess , Give up... Decisively , There is too much code . But it refers to the source code get Model and number of requested parameters , Finally, it is tested by the browser get Format of request , Successfully sent get request .
send out get There was another problem after the request , There is no way for the server to give a response to the client , Because the source code does not do this , That means you let the server light up , But can we succeed , I don't know yet ! I'll look at the sending get When requesting a series of codes, I see :httpd_resp_set_type(req, “text/html”);
httpd_resp_set_hdr(req, “Content-Encoding”, “gzip”); I can guess how the server responds to the client and returns the client information . This logic was finally smoothed out by me . Now I have written out the logic for checking the light on and off , But it's also simple , Query with fixed syntax pin4 The light on and off status will be known by the high and low level of the lamp , High level is on .
At that time, there was a serious problem with asynchronously submitting requests , There is no way to respond , I don't know what the problem is , Are about to collapse and give up , And I only did the test of this request , But the browser used to open web files to test , The website is dead . Put it on the server to run , You can't send a request , I've been debugging for a long time , Later, it was reduced to changing various parameters at random , Even think that the parameters of the requested URL are wrong , Took a lot of detours . Later, I couldn't help but refer to the non asynchronous request submission method of other netizens , This way I was originally dismissive , Because the difficulty is too small , After joining the request submission method, you can , I found that this method was effective , Request the web page to the server to submit the request , Although it is submitted in the form of refresh , It is inconvenient to jump to the web page , At least the lights are on . Then I thought about , Since there is a possibility of success , Why not try again ? So I clicked on the browser again F12 Grab the source code of the server home page again , Then I saw the light , The browser's debug window displays function checkCmd(cmd) The definition of the function does not exist , I was in a panic , I know there is a play . Take a closer look. , When this function is defined , I wrote a note at the end , This js Comments written in the area , After converting to string, character array and then restoring the output to the browser, the flavor will change , So I decisively deleted all of the homepage js Comments in the area , It did , I'm so happy , Although the source code can't be sold for much , But it took two days to debug .
The upgrade and maintenance of the code in the later stage are natural , Because I understand the logic of the source code , Although many functions cannot find the definition of the source code , But you can guess the general function according to the entry parameters and the name of the function . Making wheels is not something I should do at my age , Making a project is the king . Besides java and c I have used a lot of socket functions in the language , This arduino It doesn't matter whether the socket function of the library function looks at the source code or not .
The official website code is as follows ( Example ):
<!DOCTYPE html>
<!-- saved from url=(0019)http://172.17.14.2/ -->
<html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>ESP32 OV2460</title>
<style> body {
font-family: Arial,Helvetica,sans-serif; background: #181818; color: #EFEFEF; font-size: 16px } h2 {
font-size: 18px } section.main {
display: flex } #menu,section.main {
flex-direction: column } #menu {
display: none; flex-wrap: nowrap; min-width: 340px; background: #363636; padding: 8px; border-radius: 4px; margin-top: -10px; margin-right: 10px; } #content {
display: flex; flex-wrap: wrap; align-items: stretch } figure {
padding: 0px; margin: 0; -webkit-margin-before: 0; margin-block-start: 0; -webkit-margin-after: 0; margin-block-end: 0; -webkit-margin-start: 0; margin-inline-start: 0; -webkit-margin-end: 0; margin-inline-end: 0 } figure img {
display: block; width: 100%; height: auto; border-radius: 4px; margin-top: 8px; } @media (min-width: 800px) and (orientation:landscape) {
#content {
display:flex; flex-wrap: nowrap; align-items: stretch } figure img {
display: block; max-width: 100%; max-height: calc(100vh - 40px); width: auto; height: auto } figure {
padding: 0 0 0 0px; margin: 0; -webkit-margin-before: 0; margin-block-start: 0; -webkit-margin-after: 0; margin-block-end: 0; -webkit-margin-start: 0; margin-inline-start: 0; -webkit-margin-end: 0; margin-inline-end: 0 } } section#buttons {
display: flex; flex-wrap: nowrap; justify-content: space-between } #nav-toggle {
cursor: pointer; display: block } #nav-toggle-cb {
outline: 0; opacity: 0; width: 0; height: 0 } #nav-toggle-cb:checked+#menu {
display: flex } .input-group {
display: flex; flex-wrap: nowrap; line-height: 22px; margin: 5px 0 } .input-group>label {
display: inline-block; padding-right: 10px; min-width: 47% } .input-group input,.input-group select {
flex-grow: 1 } .range-max,.range-min {
display: inline-block; padding: 0 5px } button {
display: block; margin: 5px; padding: 0 12px; border: 0; line-height: 28px; cursor: pointer; color: #fff; background: #ff3034; border-radius: 5px; font-size: 16px; outline: 0 } button:hover {
background: #ff494d } button:active {
background: #f21c21 } button.disabled {
cursor: default; background: #a0a0a0 } input[type=range] {
-webkit-appearance: none; width: 100%; height: 22px; background: #363636; cursor: pointer; margin: 0 } input[type=range]:focus {
outline: 0 } input[type=range]::-webkit-slider-runnable-track {
width: 100%; height: 2px; cursor: pointer; background: #EFEFEF; border-radius: 0; border: 0 solid #EFEFEF } input[type=range]::-webkit-slider-thumb {
border: 1px solid rgba(0,0,30,0); height: 22px; width: 22px; border-radius: 50px; background: #ff3034; cursor: pointer; -webkit-appearance: none; margin-top: -11.5px } input[type=range]:focus::-webkit-slider-runnable-track {
background: #EFEFEF } input[type=range]::-moz-range-track {
width: 100%; height: 2px; cursor: pointer; background: #EFEFEF; border-radius: 0; border: 0 solid #EFEFEF } input[type=range]::-moz-range-thumb {
border: 1px solid rgba(0,0,30,0); height: 22px; width: 22px; border-radius: 50px; background: #ff3034; cursor: pointer } input[type=range]::-ms-track {
width: 100%; height: 2px; cursor: pointer; background: 0 0; border-color: transparent; color: transparent } input[type=range]::-ms-fill-lower {
background: #EFEFEF; border: 0 solid #EFEFEF; border-radius: 0 } input[type=range]::-ms-fill-upper {
background: #EFEFEF; border: 0 solid #EFEFEF; border-radius: 0 } input[type=range]::-ms-thumb {
border: 1px solid rgba(0,0,30,0); height: 22px; width: 22px; border-radius: 50px; background: #ff3034; cursor: pointer; height: 2px } input[type=range]:focus::-ms-fill-lower {
background: #EFEFEF } input[type=range]:focus::-ms-fill-upper {
background: #363636 } .switch {
display: block; position: relative; line-height: 22px; font-size: 16px; height: 22px } .switch input {
outline: 0; opacity: 0; width: 0; height: 0 } .slider {
width: 50px; height: 22px; border-radius: 22px; cursor: pointer; background-color: grey } .slider,.slider:before {
display: inline-block; transition: .4s } .slider:before {
position: relative; content: ""; border-radius: 50%; height: 16px; width: 16px; left: 4px; top: 3px; background-color: #fff } input:checked+.slider {
background-color: #ff3034 } input:checked+.slider:before {
-webkit-transform: translateX(26px); transform: translateX(26px) } select {
border: 1px solid #363636; font-size: 14px; height: 22px; outline: 0; border-radius: 5px } .image-container {
position: relative; min-width: 160px } .close {
position: absolute; right: 5px; top: 5px; background: #ff3034; width: 16px; height: 16px; border-radius: 100px; color: #fff; text-align: center; line-height: 18px; cursor: pointer } .hidden {
display: none } </style>
</head>
<body>
<section class="main">
<div id="logo">
<label for="nav-toggle-cb" id="nav-toggle">* Toggle OV2640 settings</label>
</div>
<div id="content">
<div id="sidebar">
<input type="checkbox" id="nav-toggle-cb" checked="checked">
<nav id="menu">
<div class="input-group" id="framesize-group">
<label for="framesize">Resolution</label>
<select id="framesize" class="default-action">
<option value="10">UXGA(1600x1200)</option>
<option value="9">SXGA(1280x1024)</option>
<option value="8">XGA(1024x768)</option>
<option value="7">SVGA(800x600)</option>
<option value="6">VGA(640x480)</option>
<option value="5" selected="selected">CIF(400x296)</option>
<option value="4">QVGA(320x240)</option>
<option value="3">HQVGA(240x176)</option>
<option value="0">QQVGA(160x120)</option>
</select>
</div>
<div class="input-group" id="quality-group">
<label for="quality">Quality</label>
<div class="range-min">10</div>
<input type="range" id="quality" min="10" max="63" value="10" class="default-action">
<div class="range-max">63</div>
</div>
<div class="input-group" id="brightness-group">
<label for="brightness">Brightness</label>
<div class="range-min">-2</div>
<input type="range" id="brightness" min="-2" max="2" value="0" class="default-action">
<div class="range-max">2</div>
</div>
<div class="input-group" id="contrast-group">
<label for="contrast">Contrast</label>
<div class="range-min">-2</div>
<input type="range" id="contrast" min="-2" max="2" value="0" class="default-action">
<div class="range-max">2</div>
</div>
<div class="input-group" id="saturation-group">
<label for="saturation">Saturation</label>
<div class="range-min">-2</div>
<input type="range" id="saturation" min="-2" max="2" value="0" class="default-action">
<div class="range-max">2</div>
</div>
<div class="input-group" id="special_effect-group">
<label for="special_effect">Special Effect</label>
<select id="special_effect" class="default-action">
<option value="0" selected="selected">No Effect</option>
<option value="1">Negative</option>
<option value="2">Grayscale</option>
<option value="3">Red Tint</option>
<option value="4">Green Tint</option>
<option value="5">Blue Tint</option>
<option value="6">Sepia</option>
</select>
</div>
<div class="input-group" id="awb-group">
<label for="awb">AWB</label>
<div class="switch">
<input id="awb" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="awb"></label>
</div>
</div>
<div class="input-group" id="awb_gain-group">
<label for="awb_gain">AWB Gain</label>
<div class="switch">
<input id="awb_gain" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="awb_gain"></label>
</div>
</div>
<div class="input-group" id="wb_mode-group">
<label for="wb_mode">WB Mode</label>
<select id="wb_mode" class="default-action">
<option value="0" selected="selected">Auto</option>
<option value="1">Sunny</option>
<option value="2">Cloudy</option>
<option value="3">Office</option>
<option value="4">Home</option>
</select>
</div>
<div class="input-group" id="aec-group">
<label for="aec">AEC SENSOR</label>
<div class="switch">
<input id="aec" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="aec"></label>
</div>
</div>
<div class="input-group" id="aec2-group">
<label for="aec2">AEC DSP</label>
<div class="switch">
<input id="aec2" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="aec2"></label>
</div>
</div>
<div class="input-group" id="ae_level-group">
<label for="ae_level">AE Level</label>
<div class="range-min">-2</div>
<input type="range" id="ae_level" min="-2" max="2" value="0" class="default-action">
<div class="range-max">2</div>
</div>
<div class="input-group" id="aec_value-group">
<label for="aec_value">Exposure</label>
<div class="range-min">0</div>
<input type="range" id="aec_value" min="0" max="1200" value="204" class="default-action">
<div class="range-max">1200</div>
</div>
<div class="input-group" id="agc-group">
<label for="agc">AGC</label>
<div class="switch">
<input id="agc" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="agc"></label>
</div>
</div>
<div class="input-group hidden" id="agc_gain-group">
<label for="agc_gain">Gain</label>
<div class="range-min">1x</div>
<input type="range" id="agc_gain" min="0" max="30" value="5" class="default-action">
<div class="range-max">31x</div>
</div>
<div class="input-group" id="gainceiling-group">
<label for="gainceiling">Gain Ceiling</label>
<div class="range-min">2x</div>
<input type="range" id="gainceiling" min="0" max="6" value="0" class="default-action">
<div class="range-max">128x</div>
</div>
<div class="input-group" id="bpc-group">
<label for="bpc">BPC</label>
<div class="switch">
<input id="bpc" type="checkbox" class="default-action">
<label class="slider" for="bpc"></label>
</div>
</div>
<div class="input-group" id="wpc-group">
<label for="wpc">WPC</label>
<div class="switch">
<input id="wpc" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="wpc"></label>
</div>
</div>
<div class="input-group" id="raw_gma-group">
<label for="raw_gma">Raw GMA</label>
<div class="switch">
<input id="raw_gma" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="raw_gma"></label>
</div>
</div>
<div class="input-group" id="lenc-group">
<label for="lenc">Lens Correction</label>
<div class="switch">
<input id="lenc" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="lenc"></label>
</div>
</div>
<div class="input-group" id="hmirror-group">
<label for="hmirror">H-Mirror</label>
<div class="switch">
<input id="hmirror" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="hmirror"></label>
</div>
</div>
<div class="input-group" id="vflip-group">
<label for="vflip">V-Flip</label>
<div class="switch">
<input id="vflip" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="vflip"></label>
</div>
</div>
<div class="input-group" id="dcw-group">
<label for="dcw">DCW (Downsize EN)</label>
<div class="switch">
<input id="dcw" type="checkbox" class="default-action" checked="checked">
<label class="slider" for="dcw"></label>
</div>
</div>
<div class="input-group" id="colorbar-group">
<label for="colorbar">Color Bar</label>
<div class="switch">
<input id="colorbar" type="checkbox" class="default-action">
<label class="slider" for="colorbar"></label>
</div>
</div>
<div class="input-group" id="face_detect-group">
<label for="face_detect">Face Detection</label>
<div class="switch">
<input id="face_detect" type="checkbox" class="default-action">
<label class="slider" for="face_detect"></label>
</div>
</div>
<div class="input-group" id="face_recognize-group">
<label for="face_recognize">Face Recognition</label>
<div class="switch">
<input id="face_recognize" type="checkbox" class="default-action">
<label class="slider" for="face_recognize"></label>
</div>
</div>
<section id="buttons">
<button id="get-still">Get Still</button>
<button id="toggle-stream">Start Stream</button>
<button id="face_enroll" class="disabled" disabled="disabled">Enroll Face</button>
</section>
</nav>
</div>
<figure>
<div id="stream-container" class="image-container hidden">
<div class="close" id="close-stream">×</div>
<img id="stream" src="http://172.17.14.2/">
</div>
</figure>
</div>
</section>
<script> document.addEventListener('DOMContentLoaded', function (event) {
var baseHost = document.location.origin var streamUrl = baseHost + ':81' const hide = el => {
el.classList.add('hidden') } const show = el => {
el.classList.remove('hidden') } const disable = el => {
el.classList.add('disabled') el.disabled = true } const enable = el => {
el.classList.remove('disabled') el.disabled = false } const updateValue = (el, value, updateRemote) => {
updateRemote = updateRemote == null ? true : updateRemote let initialValue if (el.type === 'checkbox') {
initialValue = el.checked value = !!value el.checked = value } else {
initialValue = el.value el.value = value } if (updateRemote && initialValue !== value) {
updateConfig(el); } else if(!updateRemote){
if(el.id === "aec"){
value ? hide(exposure) : show(exposure) } else if(el.id === "agc"){
if (value) {
show(gainCeiling) hide(agcGain) } else {
hide(gainCeiling) show(agcGain) } } else if(el.id === "awb_gain"){
value ? show(wb) : hide(wb) } else if(el.id === "face_recognize"){
value ? enable(enrollButton) : disable(enrollButton) } } } function updateConfig (el) {
let value switch (el.type) {
case 'checkbox': value = el.checked ? 1 : 0 break case 'range': case 'select-one': value = el.value break case 'button': case 'submit': value = '1' break default: return } const query = `${
baseHost}/control?var=${
el.id}&val=${
value}` fetch(query) .then(response => {
console.log(`request to ${
query} finished, status: ${
response.status}`) }) } document .querySelectorAll('.close') .forEach(el => {
el.onclick = () => {
hide(el.parentNode) } }) // read initial values fetch(`${
baseHost}/status`) .then(function (response) {
return response.json() }) .then(function (state) {
document .querySelectorAll('.default-action') .forEach(el => {
updateValue(el, state[el.id], false) }) }) const view = document.getElementById('stream') const viewContainer = document.getElementById('stream-container') const stillButton = document.getElementById('get-still') const streamButton = document.getElementById('toggle-stream') const enrollButton = document.getElementById('face_enroll') const closeButton = document.getElementById('close-stream') const stopStream = () => {
window.stop(); streamButton.innerHTML = 'Start Stream' } const startStream = () => {
view.src = `${
streamUrl}/stream` show(viewContainer) streamButton.innerHTML = 'Stop Stream' } // Attach actions to buttons stillButton.onclick = () => {
stopStream() view.src = `${
baseHost}/capture?_cb=${
Date.now()}` show(viewContainer) } closeButton.onclick = () => {
stopStream() hide(viewContainer) } streamButton.onclick = () => {
const streamEnabled = streamButton.innerHTML === 'Stop Stream' if (streamEnabled) {
stopStream() } else {
startStream() } } enrollButton.onclick = () => {
updateConfig(enrollButton) } // Attach default on change action document .querySelectorAll('.default-action') .forEach(el => {
el.onchange = () => updateConfig(el) }) // Custom actions // Gain const agc = document.getElementById('agc') const agcGain = document.getElementById('agc_gain-group') const gainCeiling = document.getElementById('gainceiling-group') agc.onchange = () => {
updateConfig(agc) if (agc.checked) {
show(gainCeiling) hide(agcGain) } else {
hide(gainCeiling) show(agcGain) } } // Exposure const aec = document.getElementById('aec') const exposure = document.getElementById('aec_value-group') aec.onchange = () => {
updateConfig(aec) aec.checked ? hide(exposure) : show(exposure) } // AWB const awb = document.getElementById('awb_gain') const wb = document.getElementById('wb_mode-group') awb.onchange = () => {
updateConfig(awb) awb.checked ? show(wb) : hide(wb) } // Detection and framesize const detect = document.getElementById('face_detect') const recognize = document.getElementById('face_recognize') const framesize = document.getElementById('framesize') framesize.onchange = () => {
updateConfig(framesize) if (framesize.value > 5) {
updateValue(detect, false) updateValue(recognize, false) } } detect.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!"); updateValue(detect, false) return; } updateConfig(detect) if (!detect.checked) {
disable(enrollButton) updateValue(recognize, false) } } recognize.onchange = () => {
if (framesize.value > 5) {
alert("Please select CIF or lower resolution before enabling this feature!"); updateValue(recognize, false) return; } updateConfig(recognize) if (recognize.checked) {
enable(enrollButton) updateValue(detect, true) } else {
disable(enrollButton) } } }) </script>
</body></html>
data = pd.read_csv(
'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())
2. The server reads get request
The code is as follows ( Example ):
String var = String(variable);// obtain get Requested id
int val = atoi(value);// obtain get The value of the request
// Print out the transmitted instructions here
Serial.printf("var=%s\n",var);
Serial.printf("val=%d\n",val);
sensor_t * s = esp_camera_sensor_get();
int res = 0;
if(!strcmp(variable, "framesize")) {
if(s->pixformat == PIXFORMAT_JPEG) res = s->set_framesize(s, (framesize_t)val);
}
else if(!strcmp(variable, "quality")){
res = s->set_quality(s, val);// This is based on id and value Set it up , The key
}else if(!strcmp(variable, "on")){
// If the received string is "on"
controlLamp(true);// turn on the light
httpd_resp_set_type(req, "text/html");// I joined in
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
return httpd_resp_send(req, "on ok", 5);
}else if(!strcmp(variable, "off")){
controlLamp(false);// Turn off the lights
httpd_resp_set_type(req, "text/html");// I joined in
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
return httpd_resp_send(req, "off ok", 6);
}else if(!strcmp(variable, "check")){
// Check the status of the lamp
int LAMP_flag= digitalRead(LAMP_PIN);// Read the status of the pin , And back to HIGH or LOW
httpd_resp_set_type(req, "text/html");// I joined in
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");
if(LAMP_flag==HIGH){
return httpd_resp_send(req, "LAMP is on", 10);
}else if(LAMP_flag==LOW){
return httpd_resp_send(req, "LAMP is off", 11);
}
}
3. Operation and debugging
The interface starts as follows :
View the video below 
summary
This project is also an attempt to make ESP32 An attempt to become an intelligent gateway , The interface is clean and simple , But the function is not simple , Every step of the logic is carefully designed by me , Although the gateway can only respond to the requests of one client at the same time , But it's only a matter of a few lines of code to change , Although this microcontroller is currently used by few users , Most of them are used by foreign program developers . There is not much information about this module in China , Only by playing slowly can we stimulate the real use of this powerful module , Again , This project is not ESP32-CAM Module evaluation , It is a real open source project . Mobile phones will be added to the next project APP And ESP32 Interaction or JSP Services and ESP32 Interactive projects , Coming soon .
Code download address :https://www.cirmall.com/circuit/19372/
Jump straight to
边栏推荐
- NOI OJ 1.3 13:反向输出一个三位数 C语言
- 开源二进制文件静态漏洞分析工具BinAbsInspector安装使用
- NOI OJ 1.4 05:整数大小比较 C语言
- 技术创造价值,手把手教你薅羊毛篇
- Go zero micro Service Practice Series (VI. cache consistency assurance)
- PHP regular expression
- [use of Matlab graphical user interface controls]
- Data structures and differences between MySQL InnoDB engine and MyISAM
- Noi OJ 1.3 16: calculating segment length C language
- Pycharm installation tutorial, super detailed
猜你喜欢

程序中创建一个子进程,然后父子进程各自独自运行,父进程在标准输入设备上读入小写字母,写入管道。子进程从管道读取字符并转化为大写字母。读到x结束

"Internet +" contest topic hot docking | I figure to understand 38 propositions of Baidu

What is a good quick development framework like?

JVM easy start-02

最简单DIY基于C#和51单片机上下位机一体化的PCA9685舵机控制程序

深潜Kotlin协程(十四):共享状态的问题

长安LUMIN是否有能力成为微电市场的破局产品

最简单DIY基于STM32的远程控制电脑系统②(无线遥杆+按键控制)

安卓安全/逆向面试题

Simplest DIY remote control computer system based on STM32 ① (capacitive touch + key control)
随机推荐
NOI OJ 1.4 05:整数大小比较 C语言
Data structures and differences between MySQL InnoDB engine and MyISAM
JVM简单入门-01
最简单DIY基于STM32的远程控制电脑系统①(电容触摸+按键控制)
一年多时间时移世易,中国芯片不断突破,美国芯片却难以卖出
UART的奇偶校验
Unity technical manual - shape sub module - Sprite, spriterenderer and velocity over lifetime
JVM easy start-01
NOI OJ 1.3 13:反向输出一个三位数 C语言
NOI OJ 1.3 16:计算线段长度 C语言
技术创造价值,手把手教你薅羊毛篇
MySQL基础-笔记
NOI OJ 1.2 10:Hello, World!的大小 C语言
Noi OJ 1.3 13: reverse output of a three digit C language
Description of directory files of TLBB series of Tianlong Babu - netbill server [ultra detailed]
最简单DIY基于蓝牙、51单片机和舵机的钢铁爱国者机关枪控制器
How to solve the problem that easycvr does not display the interface when RTMP streaming is used?
Interview Manual of social recruitment Tencent high P (Senior Product Manager)
php 正则表达式
韦东山设备信息查询例程学习