ESP32项目增加Menuconfig

ESP32使用Kconfig管理配置,想要在menuconfig中添加配置项需要如下操作 在main目录下创建Kconfig.projbuild 在里面编辑类似内容 menu "自定义菜单名称" config YOUR_CONFIG_NAME # 会生成CONFIG_YOUR_CONFIG_NAME的配置项 bool "布尔选项描述" # 布尔类型(是/否) default y # 默认值 help # 帮助信息 "详细说明" config LED_GPIO_NUM # 示例:整数型配置 int "LED的GPIO引脚号" range 0 39 # 取值范围 default 10 # 默认值 choice # 单选选项 prompt "选择模式" default MODE_A config MODE_A #如果选择这个则会生成CONFIG_MODE_A这个配置 bool "模式A" config MODE_B #没选择的不会生成CONFIG_MODE_B bool "模式B" endchoice endmenu 在代码中引用#include "sdkconfig.h"就可以使用生成的相关配置了

2025-07-01 11:09:03    |    1 分钟    |    57 字    |    Fengbin

Spi

spi使用步骤 1.配置总线 #include "driver/spi_master.h" // 1. 配置总线参数 spi_bus_config_t buscfg = { .mosi_io_num = 13, // MOSI 引脚 .miso_io_num = 12, // MISO 引脚 .sclk_io_num = 14, // SCLK 引脚 .quadwp_io_num = -1, // 未使用(保留 -1) .quadhd_io_num = -1, // 未使用(保留 -1) .max_transfer_sz = 4096 // 最大传输字节数 }; // 初始化 SPI 总线(如 SPI2_HOST) ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO)); 2.添加设备到总线 spi_device_interface_config_t devcfg = { .clock_speed_hz = 10 * 1000 * 1000, // 时钟频率 (10 MHz) .mode = 0, // SPI 模式 0 .spics_io_num = 15, // 片选引脚 (CS) .queue_size = 7, // 传输队列大小 }; spi_device_handle_t spi; // 设备句柄 ESP_ERROR_CHECK(spi_bus_add_device(SPI2_HOST, &devcfg, &spi)); 3.传输数据 uint8_t send_buf[4] = {0x01, 0x02, 0x03, 0x04}; uint8_t recv_buf[4] = {0}; // 接收缓冲区 spi_transaction_t t = { .tx_buffer = send_buf, // 发送数据指针 .rx_buffer = recv_buf, // 接收数据指针 .length = 32, // 总位数 (4字节 * 8 = 32位) }; // 执行传输(阻塞模式) ESP_ERROR_CHECK(spi_device_transmit(spi, &t)); 4.释放资源(不使用spi后) spi_bus_remove_device(spi); // 移除设备 spi_bus_free(SPI2_HOST); // 释放总线 理解SPI SPI2_HOST 是SPI控制器标识符,根据总线配置和设备配置进行收发数据和DMA启动等, SPI1_HOST一般是不使用的,这个控制器一般用来内部flash使用 不管是spi_bus_config_t总线配置,还是spi_device_interface_config_t设备配置,都是在配置SPI控制器如何收发数据,拆分开成两个配置是为了通用性,总线是一组设备公用的配置,同一个总线上可以有多个设备,而设备配置是和具体设备紧密关联的配置比如片选信由那个GPIO发送 总线配置是物理层设定(线路怎么接); 设备配置是协议层设定(信号怎么发)

2025-06-30 10:53:45    |    1 分钟    |    154 字    |    Fengbin

无损滚动更新机制

想要进行无损滚动更新需要保证一下3点 应用支持优雅退出(收到退出信号时不接收新请求并且要处理完已经接收到的请求) k8s正确配置readnessProbe就绪探针 添加生命周期函数preStop添加一定的延时, 比如preStop.exec.commend: ["/bin/sh", “-c”, “sleep 10”] 主要原因为Kubernetes 在终止 Pod 时的操作顺序是 标记 Pod 为 Terminating 状态:当 Kubernetes 接收到删除 Pod 的请求时,它会将 Pod 的状态设置为 Terminating 执行 preStop 钩子:如果 Pod 定义了 preStop 钩子,Kubernetes 会立即同步执行这个钩子 并行更新 Endpoint:在 Kubernetes 标记 Pod 为 Terminating 状态的同时,Endpoint Controller 会异步地从相关的服务端点(endpoints)中移除该 Pod 的 IP 地址。Kube-proxy 也会开始更新其网络规则,以停止向该 Pod 转发流量 发送 SIGTERM 信号:一旦 preStop 钩子完成,Kubernetes 会向 Pod 中的容器发送 SIGTERM 信号,告诉容器开始优雅地关闭 等待或强制终止:如果容器在终止宽限期(terminationGracePeriodSeconds)内没有关闭,Kubernetes 会发送 SIGKILL 信号强制终止容器。 k8s doc %% Kubernetes Pod 终止流程(Endpoint更新与preStop并行) graph TD A[用户/系统删除Pod] --> B(标记Pod为Terminating状态) B --> C[[Endpoint控制器异步移除Pod IP]] B --> D{执行preStop钩子} C --> E[停止流量路由到Pod] D -->|同步等待完成或超时| F[发送SIGTERM信号] F --> G{进程处理SIGTERM} G -->|异步处理| H[等待退出] H --> I{是否在terminationGracePeriod内退出?} I -->|是| J[Pod终止完成] I -->|否| K[发送SIGKILL强制终止] K --> J %% 同步/异步标注 style B fill:#c9f7d4,stroke:#2d8a3e style C fill:#e3f2fd,stroke:#1e88e5 style D fill:#c9f7d4,stroke:#2d8a3e style F fill:#c9f7d4,stroke:#2d8a3e style K fill:#c9f7d4,stroke:#2d8a3e style G fill:#f8e5d4,stroke:#cc6b2c style H fill:#f8e5d4,stroke:#cc6b2c 注: ...

2024-09-11 15:44:16    |    1 分钟    |    166 字    |    Fengbin

Kafka使用kraft搭建集群

主机准备 主机 IP 系统 kafka1 192.168.10.101 ubuntu22.04 kafka2 192.168.10.102 ubuntu22.04 kafka3 192.168.10.103 ubuntu22.04 主机环境 安装java 11 kafka_2.13-3.7.0 配置 这里部署的是broker和controller在一起的方式,也可以分别部署,具体修改kraft相关文件,配置都是相通的 kafka/config/kraft/server.properties #集群角色 process.roles=broker,controller #每台机器的id不能一样 node.id=3 #这个是所有conntroller的地址,用于投票选举使用 controller.quorum.voters=1@192.168.10.101:9093,2@192.168.10.102:9093,3@192.168.10.103:9093 # 监听端口 listeners=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 # 客户端连接地址 advertised.listeners=PLAINTEXT://192.168.20.208:9092 # 日志地址, 这个修改到非/tmp目录,否则系统重启后会丢失 log.dirs=/var/log/kafka/kraft-combined-logs # ...其他配置按照实际情况修改 启动集群步骤: KAFKA_CLUSTER_ID="$(bin/kafka-storage.sh random-uuid)" 这个操作只在一个机器上运行,执行后记录这个值,这个是集群id,整个集群需要一致 bin/kafka-storage.sh format -t $KAFKA_CLUSTER_ID -c config/kraft/server.properties 每个机器上都要执行, 这个KAFKA_CLUSTER_ID 就是是上面执行的值 bin/kafka-server-start.sh config/kraft/server.properties 启动集群 配置systemd开机启动 在/etc/systemd/system/kafka.service文件中添加内容 [Unit] Description=Apache Kafka Server [Service] Type=simple User=root Group=root ExecStart=/usr/local/kafka/bin/kafka-server-start.sh /usr/local/kafka/config/kraft/server.properties ExecStop=/usr/local/kafka/bin/kafka-server-stop.sh Restart=on-failure [Install] WantedBy=multi-user.target 执行sudo systemctl daemon-reload 重新加载 执行sudo systemctl enable kafka 开机启动 执行sudo systemctl start kafka 启动 使用sudo journalctl -u kafka.service查看日志 使用jps查看进程是否启动成功 ...

2024-07-04 15:16:44    |    1 分钟    |    135 字    |    Fengbin

Debezium

Debezium 用于捕获数据库中的更改,以便应用程序可以查看这些更改并对其做出响应。 Debezium 会记录每个数据库表中所有行级别的更改,并将其作为更改事件流记录下来 主流CDC工具: canal : 监控binlog,支持mysql,社区已不活跃,非首选 debezium : 支持mysql, postgresql, mongodb等十余种数据库,mysql也支持binlog,成熟稳定 flink cdc: 主要应用于大数据,基于debezium,延迟较低 这里选择debezium的理由: 不选canal的原因 只支持mysql,并且社区已不活跃,除了老项目使用新的已经不是首选,在阿里也都边缘化了 不选flink cdc的原因,公司大数据没有flink的项目,增加运维成本,并且需要使用java开发,并不是所有开发都会使用java 选择debezium的原因,debezium成熟稳定,支持多种数据库,经典的使用方式是使用的是kafka connect部署, 我们有自己的kafka,不会增加运维成本, kafka connect是kafka自带的分布式工具,不用搭建额外的平台管理任务,使用消息队列和固定语言解耦,降低开发成本 当我们想监控数据库数据变动时我可以使用一些CDC工具,这里介绍一款配合Kafka使用的Connect插件Debezium,他支持Mysql, PostgreSQL, MongoDB等 能做什么: 1. 解耦数据修改端和使用端,减少应该通知但是没有通知的数据变更的错误,或者手动修改数据库时没有或忘记通知其他端 2. 异构数据库同步数据,比如搜索相关业务,需要数据实时同步,但是要保证数据一致 3. 缓存数据的生成和过期 4. 一些计算任务(数据统计,聚合) 这里我们以MySQL为例 环境 1. Kafka 3.7 2. MySQL 8.0 3. Debezium Mysql connect Plugin 2.6.2 Final Mysql 需要开启row格式binlog [mysqld] bind-address = 0.0.0.0 binlog_format = ROW server_id = 1 log_bin = /var/log/mysql/mysql-bin.log 需要以下权限 GRANT SELECT, RELOAD, SHOW DATABASES, REPLICATION SLAVE, LOCK TABLES, REPLICATION CLIENT ON *.* TO 'user' IDENTIFIED BY 'password'; 权限 作用 SELECT 查询数据,仅在执行快照时使用 RELOAD 允许连接器使用 FLUSH 语句来清除或重新加载内部缓存、刷新表或获取锁。仅在执行快照时使用 SHOW DATABASES 使连接器能够通过发出 SHOW DATABASE 语句来查看数据库名称。仅在执行快照时使用 REPLICATION SLAVE 使连接器能够连接并读取 MySQL 服务器二进制日志 REPLICATION CLIENT 允许连接器使用以下语句:SHOW MASTER STATUS,SHOW SLAVE STATUS,SHOW BINARY LOGS LOCK TABLES 执行快照时需要锁表 Debezium 把插件解压到一个目录下,我这里解压到Kafka目录下,创建一个connects目录,解压到这里,解压后我的目录像这样 --kafka |--connects |--debezium-connector-mysql 在kafka的config文件夹下配置connect-distributed.properties这个文件 修改plugin.path填写connects文件夹路径 ...

2024-06-28 11:15:28    |    2 分钟    |    425 字    |    Fengbin

Deadlock检测时机

Go语言的运行时会在所有活跃的goroutine都无法继续执行时判定为死锁。这意味着,只要还有至少一个goroutine能够正常运行,Go运行时就不会触发死锁检测机制。死锁检测通常在以下情况下触发: 所有goroutine都阻塞:如果所有的goroutine都在等待某些事件(如通道操作、锁获取等),而这些事件无法由其他goroutine触发(因为没有其他goroutine在运行或者能够解除阻塞状态),Go运行时就会判定程序为死锁状态。(这里不包括io等待,因为io等待是阻塞的,但是go的运行时并不会触发死锁检测机制) 这种自动死锁检测主要是为了帮助开发者在开发阶段识别出潜在的并发问题。然而,它的能力是有限的,特别是在涉及网络I/O、系统调用或者复杂锁逻辑的情况下,Go的死锁检测可能不会触发。因此,即使Go运行时没有报告死锁,也不代表程序中不存在潜在的并发问题。 为了避免死锁,推荐的做法包括: 避免循环等待:设计系统时应确保资源的分配顺序一致,以避免循环等待的情况发生。 使用适当的同步原语:比如使用带缓冲的channel、正确使用锁(如sync.Mutex)、以及其他并发控制工具(如sync.WaitGroup、context.Context等)。 限制并发数:有时通过限制系统中并发执行的goroutine数量可以简化资源管理,减少死锁的风险。 彻底测试:并发程序应该经过详尽的测试,包括使用竞态检测工具(如Go的-race标志)来帮助识别并发错误。 这些措施可以帮助开发者构建更健壮、更可靠的并发程序。

2024-05-08 17:52:55    |    1 分钟    |    9 字    |    Fengbin

在docker模拟虚拟IP实验时遇到的问题

获取不到虚拟IP 使用下面的命令时不能获取到虚拟IP docker run -it --net vipnet --ip 172.18.0.2 vipimage /bin/bash 应该添加参数可以让容器有权限操作网络配置 docker run -it --net vipnet --ip 172.18.0.2 --cap-add=NET_ADMIN vipimage /bin/bash 或者 docker run -it --net vipnet --ip 172.18.0.2 --privileged vipimage /bin/bash privileged小知识 在 Docker 中使用 --privileged 标志会给容器提供类似于宿主机 root 用户的权限。当容器以 --privileged 模式运行时,它可以绕过 Linux 内核的许多安全限制,从而获得较广泛的操作权限。这通常用于需要执行一些高级系统管理操作的场景,例如直接访问硬件设备或进行某些需要特殊权限的网络操作。 --privileged 模式的主要影响包括: 全能力(Capabilities): 容器将获得 Linux 所有的 capabilities,与在宿主机上运行的进程几乎相同。 设备访问: 容器可以访问和操作宿主机上的所有设备(/dev 下的设备)。 安全限制: 绕过了 AppArmor 或 SELinux 的限制,容器可以执行更多的系统级操作。 文件系统: 容器可以挂载宿主机上的文件系统,甚至使用一些通常需要更高权限的挂载选项。 网络操作: 允许执行一些通常受限的网络操作,如更改网络配置或使用低号端口。 使用场景 使用 --privileged 模式通常适用于以下场景: 开发和测试: ...

2024-04-26 18:12:19    |    1 分钟    |    132 字    |    Fengbin

Wine

使用flatpak安装wine后执行winecfg配置wine时出现乱码可以使用命令安装字体解决 sudo apt-get install fonts-wqy-zenhei fonts-wqy-microhei

2024-04-22 16:42:34    |    1 分钟    |    6 字    |    Fengbin

添加字段引发的不兼容

大家都是知道如果我们在接口返回值添加字段或者proto中添加字段一般是不会发生不兼容的情况,那么在数据库中给表添加字段会导致不兼容问题吗? 通常情况是不会,添加字段不会影响到已有的数据,但是下面这种情况会引发不兼容 假设A表有字段id, bid, c, B表有id, d,业务中有这么一条语句 select a.id, b.d from a join b on a.bid = b.id where c = 1; 那么现在我们给B表加字段c,那么现在这个语句就会错,因为a表有个c,b表有个c,现在where条件中的c已经有歧义了,所以这条语句就会报错,所以给表加字段会引发不兼容 所以加字段的时候也要小心,sql如果是多表一定给字段加上别名,避免这种歧义就比如上面的语句就改为 select a.id, b.d from a join b on a.bid = b.id where a.c = 1; 这只能说约束我们自己,历史的老系统中有什么样的写法都未可知

2024-01-12 12:37:19    |    1 分钟    |    40 字    |    Fengbin

mysql中time_zone的作用,以及为什么要配置本地时区和db时区

mysql中time_zone的作用,以及为什么要配置本地时区和db时区 1. mysql中time_zone的作用 mysql中time_zone的作用,就是用来设置时区的(废话),time_zone影响TIMESTAMP类型和NOW等函数的值,但并不影响DATETIME类型和DATE类型。 因为TIMESTAMP存储的时时间戳,当用户发送过来一个时间如“2023-12-11 10:41:18”,那么mysql会将其时间戳,这个时间就是按time_zone设置的时区来解析的,然后转换成时间戳保存, 在给用户查询时在通过时区转换会时间串。 DATETIME类型不是时间戳,存入时是“2023-12-11 10:41:18”,查询时也是“2023-12-11 10:41:18”,不会做转换,也和时区无关 2. 为什么要配置本地时区和db时区 本地时区是给mysql驱动使用,并不会影响mysql的时区,只会影响mysql驱动的解析, db时区是mysql的时区,会影响mysql的时区,会影响mysql的查询结果。 本地时区作用 在读取到mysql发来的时间,go会按照本地时区来解析,转换为time.Time类型mysql按照数据库time_zone返回时间串后,go并不知道用哪个时区来解析这个时间串,所以需要设置本地时区。 本在写入time.Time类型时,go会把time.Time转换为本地时区发送给mysql 比如设置本地时区为“Asia/Shanghai” root:root@tcp(127.0.0.1:3306)/db?charset=utf8&loc=Asia%2FShanghai&parseTime=true通过loc参数来这设置 同时设置本地和数据库时区 root:root@tcp(127.0.0.1:3306)/db?charset=utf8&loc=Asia%2FShanghai&parseTime=true&time_zone=%27%2B8%3A00%27 dsn上的参数有的是给数据库驱动使用,有的是给mysql使用,具体可参阅mysql驱动的DSN

2023-12-11 10:41:18    |    1 分钟    |    22 字    |    Fengbin