ESP-IDF:在客户端网页上实现拍照按钮功能,并跳转新页面显示图片

news2024/11/26 11:37:29

ESP-IDF:在客户网页上实现拍照按钮功能,并跳转新页面显示图片

核心代码:

/* Send response with custom headers and body set as the
 * string passed in user context*/
//const char* resp_str = (const char*) req->user_ctx;
const char *resp_str_head = "<!doctype html><html><body>";
const char *resp_str_body = "<strong><font color=\"red\">Hello World!</font></strong><br/>";
//const char *resp_str_button = "<input type=\"button\" value=\"capture button\" onclick=\"javascrtpt:window.location.href='192.168.4.1/capture'\" ";
const char *resp_str_button = "<a href = \"http:\/\/192.168.4.1/capture\" target=\"_blank\"> <button>capture</button></a>";
const char *resp_str_end = "</body></html>";

char *bufmichael;
size_t buf_len_michael = 512;
bufmichael = malloc(buf_len_michael);
snprintf(bufmichael,buf_len_michael,resp_str_head);
snprintf(bufmichael+strlen(bufmichael),buf_len_michael,resp_str_body);
snprintf(bufmichael+strlen(bufmichael),buf_len_michael,resp_str_button);
snprintf(bufmichael+strlen(bufmichael),buf_len_michael,resp_str_end);

httpd_resp_send(req, bufmichael, HTTPD_RESP_USE_STRLEN);
free(bufmichael);
![在这里插入图片描述](https://img-blog.csdnimg.cn/145a4190a82e4a16aa1251c862d8f316.png)

功能实现:

地址栏输入192.168.4.1/hello进入hello World!页面
点击capture按钮会跳转到capture页面,启动摄像头抓拍一个图片显示出来。
在这里插入图片描述
在这里插入图片描述

完整代码:

首先app_wifi_main();app_camera_main();这两个组件要先编译通过。
在这里插入图片描述

/* Simple HTTP Server 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 <sys/param.h>
#include “nvs_flash.h”
#include “esp_netif.h”
#include “esp_eth.h”
#include “protocol_examples_common.h”
#include “esp_tls_crypto.h”
#include <esp_http_server.h>
// #include “app_wifi.h”
#include “esp_camera.h” //michael add
#include “app_camera.h”
#include “app_wifi.h”
#include “app_httpd.h”
#include “app_mdns.h”

/* A simple example that demonstrates how to create GET and POST

  • handlers for the web server.
    */

static const char *TAG = “example”;

#if CONFIG_EXAMPLE_BASIC_AUTH

typedef struct
{
char *username;
char *password;
} basic_auth_info_t;

#define HTTPD_401 “401 UNAUTHORIZED” /*!< HTTP Response 401 */

static char *http_auth_basic(const char *username, const char *password)
{
int out;
char *user_info = NULL;
char *digest = NULL;
size_t n = 0;
asprintf(&user_info, “%s:%s”, username, password);
if (!user_info)
{
ESP_LOGE(TAG, “No enough memory for user information”);
return NULL;
}
esp_crypto_base64_encode(NULL, 0, &n, (const unsigned char *)user_info, strlen(user_info));

/* 6: The length of the "Basic " string
 * n: Number of bytes for a base64 encode format
 * 1: Number of bytes for a reserved which be used to fill zero
 */
digest = calloc(1, 6 + n + 1);
if (digest)
{
    strcpy(digest, "Basic ");
    esp_crypto_base64_encode((unsigned char *)digest + 6, n, (size_t *)&out, (const unsigned char *)user_info, strlen(user_info));
}
free(user_info);
return digest;

}

/* An HTTP GET handler */
static esp_err_t basic_auth_get_handler(httpd_req_t *req)
{
char *buf = NULL;
size_t buf_len = 0;
basic_auth_info_t *basic_auth_info = req->user_ctx;

buf_len = httpd_req_get_hdr_value_len(req, "Authorization") + 1;
if (buf_len > 1)
{
    buf = calloc(1, buf_len);
    if (!buf)
    {
        ESP_LOGE(TAG, "No enough memory for basic authorization");
        return ESP_ERR_NO_MEM;
    }

    if (httpd_req_get_hdr_value_str(req, "Authorization", buf, buf_len) == ESP_OK)
    {
        ESP_LOGI(TAG, "Found header => Authorization: %s", buf);
    }
    else
    {
        ESP_LOGE(TAG, "No auth value received");
    }

    char *auth_credentials = http_auth_basic(basic_auth_info->username, basic_auth_info->password);
    if (!auth_credentials)
    {
        ESP_LOGE(TAG, "No enough memory for basic authorization credentials");
        free(buf);
        return ESP_ERR_NO_MEM;
    }

    if (strncmp(auth_credentials, buf, buf_len))
    {
        ESP_LOGE(TAG, "Not authenticated");
        httpd_resp_set_status(req, HTTPD_401);
        httpd_resp_set_type(req, "application/json");
        httpd_resp_set_hdr(req, "Connection", "keep-alive");
        httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello\"");
        httpd_resp_send(req, NULL, 0);
    }
    else
    {
        ESP_LOGI(TAG, "Authenticated!");
        char *basic_auth_resp = NULL;
        httpd_resp_set_status(req, HTTPD_200);
        httpd_resp_set_type(req, "application/json");
        httpd_resp_set_hdr(req, "Connection", "keep-alive");
        asprintf(&basic_auth_resp, "{\"authenticated\": true,\"user\": \"%s\"}", basic_auth_info->username);
        if (!basic_auth_resp)
        {
            ESP_LOGE(TAG, "No enough memory for basic authorization response");
            free(auth_credentials);
            free(buf);
            return ESP_ERR_NO_MEM;
        }
        httpd_resp_send(req, basic_auth_resp, strlen(basic_auth_resp));
        free(basic_auth_resp);
    }
    free(auth_credentials);
    free(buf);
}
else
{
    ESP_LOGE(TAG, "No auth header received");
    httpd_resp_set_status(req, HTTPD_401);
    httpd_resp_set_type(req, "application/json");
    httpd_resp_set_hdr(req, "Connection", "keep-alive");
    httpd_resp_set_hdr(req, "WWW-Authenticate", "Basic realm=\"Hello\"");
    httpd_resp_send(req, NULL, 0);
}

return ESP_OK;

}

static httpd_uri_t basic_auth = {
.uri = “/basic_auth”,
.method = HTTP_GET,
.handler = basic_auth_get_handler,
};

static void httpd_register_basic_auth(httpd_handle_t server)
{
basic_auth_info_t *basic_auth_info = calloc(1, sizeof(basic_auth_info_t));
if (basic_auth_info)
{
basic_auth_info->username = CONFIG_EXAMPLE_BASIC_AUTH_USERNAME;
basic_auth_info->password = CONFIG_EXAMPLE_BASIC_AUTH_PASSWORD;

    basic_auth.user_ctx = basic_auth_info;
    httpd_register_uri_handler(server, &basic_auth);
}

}
#endif

/* An HTTP GET handler */
static esp_err_t hello_get_handler(httpd_req_t *req)
{
char *buf;
size_t buf_len;

/* Get header value string length and allocate memory for length + 1,
 * extra byte for null termination */
buf_len = httpd_req_get_hdr_value_len(req, "Host") + 1;
if (buf_len > 1)
{
    buf = malloc(buf_len);
    /* Copy null terminated value string into buffer */
    if (httpd_req_get_hdr_value_str(req, "Host", buf, buf_len) == ESP_OK)
    {
        ESP_LOGI(TAG, "Found header => Host: %s", buf);
    }
    free(buf);
}

buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-2") + 1;
if (buf_len > 1)
{
    buf = malloc(buf_len);
    if (httpd_req_get_hdr_value_str(req, "Test-Header-2", buf, buf_len) == ESP_OK)
    {
        ESP_LOGI(TAG, "Found header => Test-Header-2: %s", buf);
    }
    free(buf);
}

buf_len = httpd_req_get_hdr_value_len(req, "Test-Header-1") + 1;
if (buf_len > 1)
{
    buf = malloc(buf_len);
    if (httpd_req_get_hdr_value_str(req, "Test-Header-1", buf, buf_len) == ESP_OK)
    {
        ESP_LOGI(TAG, "Found header => Test-Header-1: %s", buf);
    }
    free(buf);
}

/* Read URL query string length and allocate memory for length + 1,
 * extra byte for null termination */
buf_len = httpd_req_get_url_query_len(req) + 1;
if (buf_len > 1)
{
    buf = malloc(buf_len);
    if (httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK)
    {
        ESP_LOGI(TAG, "Found URL query => %s", buf);
        char param[32];
        /* Get value of expected key from query string */
        if (httpd_query_key_value(buf, "query1", param, sizeof(param)) == ESP_OK)
        {
            ESP_LOGI(TAG, "Found URL query parameter => query1=%s", param);
        }
        if (httpd_query_key_value(buf, "query3", param, sizeof(param)) == ESP_OK)
        {
            ESP_LOGI(TAG, "Found URL query parameter => query3=%s", param);
        }
        if (httpd_query_key_value(buf, "query2", param, sizeof(param)) == ESP_OK)
        {
            ESP_LOGI(TAG, "Found URL query parameter => query2=%s", param);
        }
    }
    free(buf);
}

/* Set some custom headers */
httpd_resp_set_hdr(req, "Custom-Header-1", "Custom-Value-1");
httpd_resp_set_hdr(req, "Custom-Header-2", "Custom-Value-2");

/* Send response with custom headers and body set as the
 * string passed in user context*/
//const char* resp_str = (const char*) req->user_ctx;
const char *resp_str_head = "<!doctype html><html><body>";
const char *resp_str_body = "<strong><font color=\"red\">Hello World!</font></strong><br/>";
//const char *resp_str_button = "<input type=\"button\" value=\"capture button\" onclick=\"javascrtpt:window.location.href='192.168.4.1/capture'\" ";
const char *resp_str_button = "<a href = \"http:\/\/192.168.4.1/capture\" target=\"_blank\"> <button>capture</button></a>";
const char *resp_str_end = "</body></html>";

char *bufmichael;
size_t buf_len_michael = 512;
bufmichael = malloc(buf_len_michael);
snprintf(bufmichael,buf_len_michael,resp_str_head);
snprintf(bufmichael+strlen(bufmichael),buf_len_michael,resp_str_body);
snprintf(bufmichael+strlen(bufmichael),buf_len_michael,resp_str_button);
snprintf(bufmichael+strlen(bufmichael),buf_len_michael,resp_str_end);

httpd_resp_send(req, bufmichael, HTTPD_RESP_USE_STRLEN);

free(bufmichael);
/* After sending the HTTP response the old HTTP request
 * headers are lost. Check if HTTP request headers can be read now. */
if (httpd_req_get_hdr_value_len(req, "Host") == 0)
{
    ESP_LOGI(TAG, "Request headers lost");
}
return ESP_OK;

}

static const httpd_uri_t hello = {
.uri = “/hello”,
.method = HTTP_GET,
.handler = hello_get_handler,
/* Let’s pass response string in user
* context to demonstrate it’s usage */
.user_ctx = “Hello World!”};

static esp_err_t capture_handler(httpd_req_t *req) // michael add
{
ESP_LOGI(TAG, “in main.c capture start, michael add”); // michael add
camera_fb_t *fb = NULL;
esp_err_t res = ESP_OK;

fb = esp_camera_fb_get();

if (!fb)
{
    ESP_LOGE(TAG, "Camera capture failed");
    httpd_resp_send_500(req);
    return ESP_FAIL;
}

ESP_LOGI(TAG, "capture : httpd_resp_set_type , michael add"); // michael add
httpd_resp_set_type(req, "image/jpeg");
httpd_resp_set_hdr(req, "Content-Disposition", "inline; filename=capture.jpg");
httpd_resp_set_hdr(req, "Access-Control-Allow-Origin", "*");

ESP_LOGI(TAG, "capture : fb->width is: %d , michael add", fb->width); // michael add
size_t fb_len = 0;
if (fb->format == PIXFORMAT_JPEG)
{
    fb_len = fb->len;
    res = httpd_resp_send(req, (const char *)fb->buf, fb->len);
}

esp_camera_fb_return(fb);

return res;

}

static const httpd_uri_t capture = { // michael add
.uri = “/capture”,
.method = HTTP_GET,
.handler = capture_handler,
.user_ctx = NULL};

/* An HTTP POST handler */
static esp_err_t echo_post_handler(httpd_req_t *req)
{
char buf[100];
int ret, remaining = req->content_len;

while (remaining > 0)
{
    /* Read the data for the request */
    if ((ret = httpd_req_recv(req, buf,
                              MIN(remaining, sizeof(buf)))) <= 0)
    {
        if (ret == HTTPD_SOCK_ERR_TIMEOUT)
        {
            /* Retry receiving if timeout occurred */
            continue;
        }
        return ESP_FAIL;
    }

    /* Send back the same data */
    httpd_resp_send_chunk(req, buf, ret);
    remaining -= ret;

    /* Log data received */
    ESP_LOGI(TAG, "=========== RECEIVED DATA ==========");
    ESP_LOGI(TAG, "%.*s", ret, buf);
    ESP_LOGI(TAG, "====================================");
}

// End response
httpd_resp_send_chunk(req, NULL, 0);
return ESP_OK;

}

static const httpd_uri_t echo = {
.uri = “/echo”,
.method = HTTP_POST,
.handler = echo_post_handler,
.user_ctx = NULL};

/* This handler allows the custom error handling functionality to be

  • tested from client side. For that, when a PUT request 0 is sent to
  • URI /ctrl, the /hello and /echo URIs are unregistered and following
  • custom error handler http_404_error_handler() is registered.
  • Afterwards, when /hello or /echo is requested, this custom error
  • handler is invoked which, after sending an error message to client,
  • either closes the underlying socket (when requested URI is /echo)
  • or keeps it open (when requested URI is /hello). This allows the
  • client to infer if the custom error handler is functioning as expected
  • by observing the socket state.
    */
    esp_err_t http_404_error_handler(httpd_req_t req, httpd_err_code_t err)
    {
    if (strcmp(“/hello”, req->uri) == 0)
    {
    httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, “/hello URI is not available”);
    /
    Return ESP_OK to keep underlying socket open /
    return ESP_OK;
    }
    else if (strcmp(“/echo”, req->uri) == 0)
    {
    httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, “/echo URI is not available”);
    /
    Return ESP_FAIL to close underlying socket /
    return ESP_FAIL;
    }
    /
    For any other URI send 404 and close socket */
    httpd_resp_send_err(req, HTTPD_404_NOT_FOUND, “Some 404 error message”);
    return ESP_FAIL;
    }

/* An HTTP PUT handler. This demonstrates realtime

  • registration and deregistration of URI handlers
    */
    static esp_err_t ctrl_put_handler(httpd_req_t *req)
    {
    char buf;
    int ret;

    if ((ret = httpd_req_recv(req, &buf, 1)) <= 0)
    {
    if (ret == HTTPD_SOCK_ERR_TIMEOUT)
    {
    httpd_resp_send_408(req);
    }
    return ESP_FAIL;
    }

    if (buf == ‘0’)
    {
    /* URI handlers can be unregistered using the uri string /
    ESP_LOGI(TAG, “Unregistering /hello and /echo URIs”);
    httpd_unregister_uri(req->handle, “/hello”);
    httpd_unregister_uri(req->handle, “/echo”);
    // httpd_unregister_uri(req->handle, “/capture”); // michael add
    /
    Register the custom error handler /
    httpd_register_err_handler(req->handle, HTTPD_404_NOT_FOUND, http_404_error_handler);
    }
    else
    {
    ESP_LOGI(TAG, “Registering /hello and /echo URIs”);
    httpd_register_uri_handler(req->handle, &hello);
    httpd_register_uri_handler(req->handle, &echo);
    // httpd_register_uri_handler(req->handle, &capture); // michael add
    /
    Unregister custom error handler */
    httpd_register_err_handler(req->handle, HTTPD_404_NOT_FOUND, NULL);
    }

    /* Respond with empty body */
    httpd_resp_send(req, NULL, 0);
    return ESP_OK;
    }

static const httpd_uri_t ctrl = {
.uri = “/ctrl”,
.method = HTTP_PUT,
.handler = ctrl_put_handler,
.user_ctx = NULL};

static httpd_handle_t start_webserver(void)
{
httpd_handle_t server = NULL;
httpd_config_t config = HTTPD_DEFAULT_CONFIG();
config.lru_purge_enable = true;

// Start the httpd server
ESP_LOGI(TAG, "Starting server on port: '%d'", config.server_port);
if (httpd_start(&server, &config) == ESP_OK)
{
    // Set URI handlers
    ESP_LOGI(TAG, "Registering URI handlers");
    httpd_register_uri_handler(server, &hello);
    httpd_register_uri_handler(server, &echo);
    httpd_register_uri_handler(server, &ctrl);
    httpd_register_uri_handler(server, &capture); // michael add

#if CONFIG_EXAMPLE_BASIC_AUTH
httpd_register_basic_auth(server);
#endif
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());
app_wifi_main();
// app_wifi_main();
app_camera_main();
 //app_httpd_main();
// app_mdns_main();

/* 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();

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/336350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MASA Stack 1.0 发布会讲稿——实践篇

MASA Stack 1.0 实践篇 产品智能化 产品智能化的改造怎么做&#xff1f; 我们以采用运营商网络场景的物联网架构举例&#xff0c;如图从左到右&#xff0c;在设备端我们研发了一款净水行业通用的物联网盒子&#xff0c;它带有各种传感器&#xff0c;如TDS、温度、流量、漏水检…

80%的代码AI帮你写?还没这么夸张,不过也快了

兔年春节一过&#xff0c;APIcat进入到云服务版本的开发阶段&#xff0c;过年前发生了一件大事&#xff0c;Chatgpt横空出世&#xff0c;不少人预测Chatgpt会替代的10大行业&#xff0c;其中就有程序员。 这时&#xff0c;一位特斯拉的老哥出来说&#xff0c;GitHub Copilot帮…

Redis简介

Redis是一款开源的、高性能的键-值存储&#xff08;key-value store&#xff09;。它常被称作是一款数据结构服务器&#xff08;data structure server&#xff09;。 Redis的键值可以包括字符串&#xff08;strings&#xff09;类型&#xff0c;同时它还包括哈希&#xff08;h…

Netty 中的 Channel执行完close之后, 还能进行write吗?

问题来源&#xff1a;项目中出现顶号操作的时候&#xff0c;正常情况下被顶掉的连接应该收到一个 “同一账号登录&#xff0c;请退出重登” 的错误消息&#xff0c; 但是偶现客户端接收不到消息的情况&#xff08;连接实际上已经被服务器干掉了&#xff0c;客户端就呆呆的&…

word和wps添加mathtype选项卡

word或wps添加mathtype选项卡 前提 安装好word或wps安装好mathtype 步骤 确认word或wps具体安装位置确认word或wps位数为32位还是64位复制mathtype中的MathPage.wll文件和MathType Commands 2016.dotm文件到STARTUP位置添加受信任位置添加加载项 安装位置 通过开始页面&a…

三套大厂网络安全工程师面试题(附答案解析)冲刺金三银四

2023年已经开始了&#xff0c;先来灵魂三连问&#xff0c;年初定的目标是多少&#xff1f;薪资能涨吗&#xff1f;女朋友能找到吗&#xff1f; 好了&#xff0c;不扎大家的心了&#xff0c;接下来进入正文。 由于我之前写了不少网络安全技术相关的文章和回答&#xff0c;不少…

亿级高并发电商项目---万达商城项目搭建(二)

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是小童&#xff0c;Java开发工程师&#xff0c;CSDN博客博主&#xff0c;Java领域新星创作者 &#x1f4d5;系列专栏&#xff1a;前端、Java、Java中间件大全、微信小程序、微信支付、若依框架、Spring全家桶 &#x1f4…

【iOS-系统框架】

文章目录前言47.熟悉系统框架CoreFoundation框架其他框架要点48. 多用块枚举&#xff0c;少用for循环for循环NSEnumerator遍历快速遍历基于块的遍历方式要点49.对自定义其内存管理语义的collection使用无缝桥接要点50.构建缓存时选用NSCache而非NSDictionaryNSCacheNSCache实例…

bgp综合实验2

目录实验要求子网划分ip以及各个环回的配置ospf配置及接口网络类型更改bgp的配置路由反射器小知识联邦的小知识bgp宣告实验要求 如图 实验要求&#xff1a; 1&#xff0c;R2-7每台路由器都存在一个环回接口用于建立邻居&#xff0c;同时存在一个环回代表连接用户的接口&…

安全—06day

负载均衡反向代理下的webshell上传负载均衡负载均衡下webshell上传的四大难点难点一&#xff1a;需要在每一台节点的相同位置上传相同内容的webshell难点二&#xff1a;无法预测下一次请求是哪一台机器去执行难点三&#xff1a;当我们需要上传一些工具时&#xff0c;麻烦来了&a…

解决方案 | 亚洲诚信助力互联网行业网络安全建设

行业背景当前&#xff0c;世界正处在从工业经济向数字经济转型过渡的大变革时代&#xff0c;互联网作为工业社会向数字时代迁移的驱动力&#xff0c;是推进新一轮科技革命与产业变革的中坚力量。随着数字化进程的加剧&#xff0c;企业所面临的网络安全形势也日趋多变复杂。尤其…

玩具全球各地检测标准整理

玩具检测认证&#xff1a;REACH法规、ROHS指令、EN 71测试、ASTM F963、GB 6675、CE认证、儿童用品CPC认证等其他认证。测试标准&#xff1a;CPSC 总共公布了 38 个标准&#xff0c;主要涉及的检测内容有&#xff1a;1). CPSIA 总铅和邻苯&#xff1b;2). 美国玩具标准 ASTMF96…

springboot整合单机缓存ehcache

区别于redis的分布式缓存&#xff0c;ehcache是纯java进程内的单机缓存&#xff0c;根据不同的场景可选择使用&#xff0c;以下内容主要为springboot整合ehcache以及注意事项添加pom引用<dependency><groupId>net.sf.ehcache</groupId><artifactId>ehc…

PTA L1-044 稳赢(详解)

前言&#xff1a;内容包括四大模块&#xff1a;题目&#xff0c;代码实习&#xff0c;大致思路&#xff0c;代码解读 题目&#xff1a; 大家应该都会玩“锤子剪刀布”的游戏&#xff1a;两人同时给出手势&#xff0c;胜负规则如图所示&#xff1a; 现要求你编写一个稳赢不输的…

计算机组成结构之数据传输控制方式、总线、CISC和RISC

数据传输控制方式 输入输出控制方式 程序控制&#xff08;查询&#xff09;方式&#xff1a;cpu一直持续不断在查询I/O是否准备好了&#xff0c;准备好就会调用I/O&#xff1b;I/O没有准备好&#xff0c;CPU会持续等待I/O&#xff1b;&#xff08;软件实现&#xff09;程序中…

vcruntime140_1.dll无法继续执行代码,怎么解决这种问题?

经常使用电脑的人&#xff0c;可能对于这个弹出框应该不陌生&#xff0c;“vcruntime140_1.dll无法继续执行代码”&#xff0c;其实会出现这种情况&#xff0c;主要是因为缺少一个动态链接库 (DLL) 文件导致的。这个文件是 Visual C 2015 库的一部分&#xff0c;某些程序需要这…

第五节 字符设备驱动——点亮LED 灯

通过字符设备章节的学习&#xff0c;我们已经了解了字符设备驱动程序的基本框架&#xff0c;主要是掌握如何申请及释放设备号、添加以及注销设备&#xff0c;初始化、添加与删除cdev 结构体&#xff0c;并通过cdev_init 函数建立cdev 和file_operations 之间的关联&#xff0c;…

阿里云ecs服务器搭建CTFd(ubuntu20)

1.更新apt包索引 sudo apt-get update更新源 1、使用快捷键【ctrlaltt】打开终端。 2、输入以下命令备份原有软件源文件。 cp /etc/apt/sources.list /etc/apt/sources.list.bak_yyyymmdd 3、再输入以下命令打开sources.list文件并添加新的软件源地址。 vim /etc/apt/sources.…

本质安全设备标准(IEC60079-11)的理解(四)

本质安全设备标准&#xff08;IEC60079-11&#xff09;的理解&#xff08;四&#xff09; 对于标准中“Separation”的理解 IEC60079-11使用了较长的篇幅来说明设计中需要考虑到的各种间距&#xff0c; 这也从一定程度上说明了间距比较重要&#xff0c;在设计中是需要认真考虑…

VBA提高篇_ 21 随机数 / 模运算

文章目录1. 模Mod运算2. 随机数及其运算2.1 Rnd()函数调用Excel公式: Rand() / RandBetween()使用VBA函数: Rnd()函数2.2 随机小数化整数公式2.3 伪随机数(过程是随机的,但是实际上不是,随机数算法)2.3.1 随机数初始化2.3.2 随机小数被当做下标时会被自动四舍五入VBA的默认属性…