当前位置:网站首页>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
边栏推荐
- 智慧园区效果不满意?请收下ThingJS这份秘籍
- 最简单DIY基于51单片机的舵机控制器
- "Internet +" contest topic hot docking | I figure to understand 38 propositions of Baidu
- SPI与IIC异同
- Go zero micro Service Practice Series (VI. cache consistency assurance)
- 1154. 一年中的第几天
- EasyCVR使用RTMP推流时不显示界面如何解决?
- NOI OJ 1.2 06:浮点数向零舍入
- ESP32-CAM高性价比温湿度监控系统配网与上网方案设计与实现
- 分享一个手游脚本源码
猜你喜欢

What does NFTs, Web3 and metauniverse mean for digital marketing?

为什么poll/select在open时要使用非阻塞NONBLOCK

图片存储--引用

Economic common sense

【黄金分割点】与【斐波那契数列】

Step by step introduction to sqlsugar based development framework (9) -- Realizing field permission control with WinForm control

Unity technical manual - limit velocity over lifetime sub module and inherit velocity sub module

技术创造价值,手把手教你薅羊毛篇

Cool photo album code, happy birthday to the object!

Win10 无线网络,系统搜索不到WLAN的,解决办法 (以及 VMnet1,8)
随机推荐
Stockage d'images - référence
Mysql-03. Experience of SQL optimization in work
Simplest DIY remote control computer system based on STM32 ② (wireless remote control + key control)
Noi OJ 1.2 06: round floating point numbers to zero
MySQL-02.工作中对索引的理解
NOI OJ 1.2 10:Hello, World! Size of C language
技术创造价值,手把手教你薅羊毛篇
SPI与IIC异同
Pycharm installation tutorial, super detailed
详解判断大小端的方法
Too helpless! Microsoft stopped selling AI emotion recognition and other technologies, saying frankly: "the law can not keep up with the development of AI"
【MATLAB 图形用户界面控件使用】
证券开户网上安全度高吗
韦东山设备信息查询例程学习
MySQL基础-笔记
一年多时间时移世易,中国芯片不断突破,美国芯片却难以卖出
The problem of C language structure byte alignment
NOI OJ 1.3 13:反向输出一个三位数 C语言
MAUI使用Masa blazor组件库
5次登陆失败,限制登录实践