添加智能灯固件代码

This commit is contained in:
kerwincui
2021-07-13 17:14:51 +08:00
parent 332f74dd17
commit ecc0b91b8b
2568 changed files with 229441 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.5)
# (Not part of the boilerplate)
# This example uses an extra component for common functions such as Wi-Fi and Ethernet connection.
set(EXTRA_COMPONENT_DIRS $ENV{IDF_PATH}/examples/common_components/protocol_examples_common)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(persistent_sockets)

View File

@@ -0,0 +1,11 @@
#
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
# project subdirectory.
#
PROJECT_NAME := persistent_sockets
EXTRA_COMPONENT_DIRS = $(IDF_PATH)/examples/common_components/protocol_examples_common
include $(IDF_PATH)/make/project.mk

View File

@@ -0,0 +1,15 @@
# HTTPD Server Persistent Sockets Example
The Example consists of HTTPD server persistent sockets demo.
This sort of persistency enables the server to have independent sessions/contexts per client.
* Open the project configuration menu (`idf.py menuconfig`) to configure Wi-Fi or Ethernet. See "Establishing Wi-Fi or Ethernet Connection" section in [examples/protocols/README.md](../../README.md) for more details.
* In order to test the HTTPD server persistent sockets demo :
1. compile and burn the firmware `idf.py -p PORT flash`
2. run `idf.py -p PORT monitor` and note down the IP assigned to your ESP module. The default port is 80
3. run the test script "python scripts/adder.py \<IP\> \<port\> \<N\>"
* the provided test script sends (POST) numbers from 1 to N to the server which has a URI POST handler for adding these numbers into an accumulator that is valid throughout the lifetime of the connection socket, hence persistent
* the script does a GET before closing and displays the final value of the accumulator
See the README.md file in the upper level 'examples' directory for more information about examples.

View File

@@ -0,0 +1,129 @@
#!/usr/bin/env python
#
# Copyright 2018 Espressif Systems (Shanghai) PTE LTD
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
from builtins import str
from builtins import range
import re
import os
import random
from tiny_test_fw import Utility
import ttfw_idf
from idf_http_server_test import adder as client
# When running on local machine execute the following before running this script
# > make app bootloader
# > make print_flash_cmd | tail -n 1 > build/download.config
@ttfw_idf.idf_example_test(env_tag="Example_WIFI")
def test_examples_protocol_http_server_persistence(env, extra_data):
# Acquire DUT
dut1 = env.get_dut("http_server", "examples/protocols/http_server/persistent_sockets",
dut_class=ttfw_idf.ESP32DUT)
# Get binary file
binary_file = os.path.join(dut1.app.binary_path, "persistent_sockets.bin")
bin_size = os.path.getsize(binary_file)
ttfw_idf.log_performance("http_server_bin_size", "{}KB".format(bin_size // 1024))
ttfw_idf.check_performance("http_server_bin_size", bin_size // 1024, dut1.TARGET)
# Upload binary and start testing
Utility.console_log("Starting http_server persistance test app")
dut1.start_app()
# Parse IP address of STA
Utility.console_log("Waiting to connect with AP")
got_ip = dut1.expect(re.compile(r"(?:[\s\S]*)IPv4 address: (\d+.\d+.\d+.\d+)"), timeout=30)[0]
got_port = dut1.expect(re.compile(r"(?:[\s\S]*)Starting server on port: '(\d+)'"), timeout=30)[0]
Utility.console_log("Got IP : " + got_ip)
Utility.console_log("Got Port : " + got_port)
# Expected Logs
dut1.expect("Registering URI handlers", timeout=30)
# Run test script
conn = client.start_session(got_ip, got_port)
visitor = 0
adder = 0
# Test PUT request and initialize session context
num = random.randint(0,100)
client.putreq(conn, "/adder", str(num))
visitor += 1
dut1.expect("/adder visitor count = " + str(visitor), timeout=30)
dut1.expect("/adder PUT handler read " + str(num), timeout=30)
dut1.expect("PUT allocating new session", timeout=30)
# Retest PUT request and change session context value
num = random.randint(0,100)
Utility.console_log("Adding: " + str(num))
client.putreq(conn, "/adder", str(num))
visitor += 1
adder += num
dut1.expect("/adder visitor count = " + str(visitor), timeout=30)
dut1.expect("/adder PUT handler read " + str(num), timeout=30)
try:
# Re allocation shouldn't happen
dut1.expect("PUT allocating new session", timeout=30)
# Not expected
raise RuntimeError
except Exception:
# As expected
pass
# Test POST request and session persistence
random_nums = [random.randint(0,100) for _ in range(100)]
for num in random_nums:
Utility.console_log("Adding: " + str(num))
client.postreq(conn, "/adder", str(num))
visitor += 1
adder += num
dut1.expect("/adder visitor count = " + str(visitor), timeout=30)
dut1.expect("/adder handler read " + str(num), timeout=30)
# Test GET request and session persistence
Utility.console_log("Matching final sum: " + str(adder))
if client.getreq(conn, "/adder").decode() != str(adder):
raise RuntimeError
visitor += 1
dut1.expect("/adder visitor count = " + str(visitor), timeout=30)
dut1.expect("/adder GET handler send " + str(adder), timeout=30)
Utility.console_log("Ending session")
# Close connection and check for invocation of context "Free" function
client.end_session(conn)
dut1.expect("/adder Free Context function called", timeout=30)
Utility.console_log("Validating user context data")
# Start another session to check user context data
client.start_session(got_ip, got_port)
num = random.randint(0,100)
client.putreq(conn, "/adder", str(num))
visitor += 1
dut1.expect("/adder visitor count = " + str(visitor), timeout=30)
dut1.expect("/adder PUT handler read " + str(num), timeout=30)
dut1.expect("PUT allocating new session", timeout=30)
client.end_session(conn)
dut1.expect("/adder Free Context function called", timeout=30)
if __name__ == '__main__':
test_examples_protocol_http_server_persistence()

View File

@@ -0,0 +1,2 @@
idf_component_register(SRCS "main.c"
INCLUDE_DIRS ".")

View File

@@ -0,0 +1,5 @@
#
# "main" pseudo-component makefile.
#
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)

View File

@@ -0,0 +1,242 @@
/* Persistent Sockets Example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <esp_wifi.h>
#include <esp_event.h>
#include <esp_log.h>
#include <esp_system.h>
#include <nvs_flash.h>
#include "esp_netif.h"
#include "esp_eth.h"
#include "protocol_examples_common.h"
#include <esp_http_server.h>
/* An example to demonstrate persistent sockets, with context maintained across
* multiple requests on that socket.
*/
static const char *TAG = "example";
/* Function to free context */
static void adder_free_func(void *ctx)
{
ESP_LOGI(TAG, "/adder Free Context function called");
free(ctx);
}
/* This handler keeps accumulating data that is posted to it into a per
* socket/session context. And returns the result.
*/
static esp_err_t adder_post_handler(httpd_req_t *req)
{
/* Log total visitors */
unsigned *visitors = (unsigned *)req->user_ctx;
ESP_LOGI(TAG, "/adder visitor count = %d", ++(*visitors));
char buf[10];
char outbuf[50];
int ret;
/* Read data received in the request */
ret = httpd_req_recv(req, buf, sizeof(buf));
if (ret <= 0) {
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
httpd_resp_send_408(req);
}
return ESP_FAIL;
}
buf[ret] = '\0';
int val = atoi(buf);
ESP_LOGI(TAG, "/adder handler read %d", val);
/* Create session's context if not already available */
if (! req->sess_ctx) {
ESP_LOGI(TAG, "/adder allocating new session");
req->sess_ctx = malloc(sizeof(int));
req->free_ctx = adder_free_func;
*(int *)req->sess_ctx = 0;
}
/* Add the received data to the context */
int *adder = (int *)req->sess_ctx;
*adder += val;
/* Respond with the accumulated value */
snprintf(outbuf, sizeof(outbuf),"%d", *adder);
httpd_resp_send(req, outbuf, strlen(outbuf));
return ESP_OK;
}
/* This handler gets the present value of the accumulator */
static esp_err_t adder_get_handler(httpd_req_t *req)
{
/* Log total visitors */
unsigned *visitors = (unsigned *)req->user_ctx;
ESP_LOGI(TAG, "/adder visitor count = %d", ++(*visitors));
char outbuf[50];
/* Create session's context if not already available */
if (! req->sess_ctx) {
ESP_LOGI(TAG, "/adder GET allocating new session");
req->sess_ctx = malloc(sizeof(int));
req->free_ctx = adder_free_func;
*(int *)req->sess_ctx = 0;
}
ESP_LOGI(TAG, "/adder GET handler send %d", *(int *)req->sess_ctx);
/* Respond with the accumulated value */
snprintf(outbuf, sizeof(outbuf),"%d", *((int *)req->sess_ctx));
httpd_resp_send(req, outbuf, strlen(outbuf));
return ESP_OK;
}
/* This handler resets the value of the accumulator */
static esp_err_t adder_put_handler(httpd_req_t *req)
{
/* Log total visitors */
unsigned *visitors = (unsigned *)req->user_ctx;
ESP_LOGI(TAG, "/adder visitor count = %d", ++(*visitors));
char buf[10];
char outbuf[50];
int ret;
/* Read data received in the request */
ret = httpd_req_recv(req, buf, sizeof(buf));
if (ret <= 0) {
if (ret == HTTPD_SOCK_ERR_TIMEOUT) {
httpd_resp_send_408(req);
}
return ESP_FAIL;
}
buf[ret] = '\0';
int val = atoi(buf);
ESP_LOGI(TAG, "/adder PUT handler read %d", val);
/* Create session's context if not already available */
if (! req->sess_ctx) {
ESP_LOGI(TAG, "/adder PUT allocating new session");
req->sess_ctx = malloc(sizeof(int));
req->free_ctx = adder_free_func;
}
*(int *)req->sess_ctx = val;
/* Respond with the reset value */
snprintf(outbuf, sizeof(outbuf),"%d", *((int *)req->sess_ctx));
httpd_resp_send(req, outbuf, strlen(outbuf));
return ESP_OK;
}
/* Maintain a variable which stores the number of times
* the "/adder" URI has been visited */
static unsigned visitors = 0;
static const httpd_uri_t adder_post = {
.uri = "/adder",
.method = HTTP_POST,
.handler = adder_post_handler,
.user_ctx = &visitors
};
static const httpd_uri_t adder_get = {
.uri = "/adder",
.method = HTTP_GET,
.handler = adder_get_handler,
.user_ctx = &visitors
};
static const httpd_uri_t adder_put = {
.uri = "/adder",
.method = HTTP_PUT,
.handler = adder_put_handler,
.user_ctx = &visitors
};
static httpd_handle_t start_webserver(void)
{
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
// Start the httpd server
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
httpd_handle_t server;
if (httpd_start(&server, &config) == ESP_OK) {
// Set URI handlers
ESP_LOGI(TAG, "Registering URI handlers");
httpd_register_uri_handler(server, &adder_get);
httpd_register_uri_handler(server, &adder_put);
httpd_register_uri_handler(server, &adder_post);
return server;
}
ESP_LOGI(TAG, "Error starting server!");
return NULL;
}
static void stop_webserver(httpd_handle_t server)
{
// Stop the httpd server
httpd_stop(server);
}
static void disconnect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server) {
ESP_LOGI(TAG, "Stopping webserver");
stop_webserver(*server);
*server = NULL;
}
}
static void connect_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
httpd_handle_t* server = (httpd_handle_t*) arg;
if (*server == NULL) {
ESP_LOGI(TAG, "Starting webserver");
*server = start_webserver();
}
}
void app_main(void)
{
static httpd_handle_t server = NULL;
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
/* Register event handlers to stop the server when Wi-Fi or Ethernet is disconnected,
* and re-start it upon connection.
*/
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_DISCONNECTED, &disconnect_handler, &server));
#endif // CONFIG_EXAMPLE_CONNECT_WIFI
#ifdef CONFIG_EXAMPLE_CONNECT_ETHERNET
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP, &connect_handler, &server));
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ETHERNET_EVENT_DISCONNECTED, &disconnect_handler, &server));
#endif // CONFIG_EXAMPLE_CONNECT_ETHERNET
/* Start the server for the first time */
server = start_webserver();
}