实现单例任务,可推送新任务功能,垃圾回收功能。
This commit is contained in:
@@ -8,6 +8,8 @@ from machine import Pin, I2S
|
|||||||
import ubinascii
|
import ubinascii
|
||||||
import urandom
|
import urandom
|
||||||
|
|
||||||
|
import shared_vars
|
||||||
|
|
||||||
# I2S 引脚配置
|
# I2S 引脚配置
|
||||||
BCLK_PIN = 13
|
BCLK_PIN = 13
|
||||||
WS_PIN = 12
|
WS_PIN = 12
|
||||||
@@ -38,7 +40,6 @@ def init_i2s():
|
|||||||
ibuf=BUFFER_SIZE) # 输入缓冲区大小
|
ibuf=BUFFER_SIZE) # 输入缓冲区大小
|
||||||
return i2s
|
return i2s
|
||||||
|
|
||||||
|
|
||||||
class InterphoneHandler:
|
class InterphoneHandler:
|
||||||
|
|
||||||
def play_wav_file(self, data):
|
def play_wav_file(self, data):
|
||||||
@@ -67,41 +68,41 @@ class InterphoneHandler:
|
|||||||
if 'audio_out' in locals():
|
if 'audio_out' in locals():
|
||||||
audio_out.deinit()
|
audio_out.deinit()
|
||||||
|
|
||||||
def play_audio_stream(self, i2s, url):
|
def stream_and_play(self, data):
|
||||||
|
current_task_id = shared_vars.handle_task_id
|
||||||
|
url = "https://iot.julecn.com/interphone/get_voice?name=" + data['name'] # 替换为音频文件的URL
|
||||||
|
print(url)
|
||||||
try:
|
try:
|
||||||
# 添加请求头信息
|
print("添加请求头信息")
|
||||||
headers = {
|
headers = {
|
||||||
'User-Agent': 'MicroPython v1.0.0'
|
'User-Agent': 'MicroPython v1.0.0'
|
||||||
}
|
}
|
||||||
# 发送 HTTP 请求,获取流式响应
|
print("发送 HTTP 请求,获取流式响应")
|
||||||
response = urequests.get(url, headers=headers, stream=True)
|
response = urequests.get(url, headers=headers, stream=True)
|
||||||
|
|
||||||
# 检查响应状态码
|
print("检查响应状态码")
|
||||||
if response.status_code != 200:
|
if response.status_code != 200:
|
||||||
print(f"请求失败,状态码: {response.status_code}")
|
print(f"请求失败,状态码: {response.status_code}")
|
||||||
response.close()
|
response.close()
|
||||||
return
|
return
|
||||||
|
print("解析 WAV 头部")
|
||||||
# 解析 WAV 头部
|
|
||||||
header = response.raw.read(44)
|
header = response.raw.read(44)
|
||||||
|
|
||||||
if len(header) != 44 or header[0:4] != b'RIFF' or header[8:12] != b'WAVE' or header[12:16] != b'fmt ':
|
if len(header) != 44 or header[0:4] != b'RIFF' or header[8:12] != b'WAVE' or header[12:16] != b'fmt ':
|
||||||
print(header)
|
print(header)
|
||||||
raise ValueError("Not a valid WAV file")
|
raise ValueError("Not a valid WAV file")
|
||||||
|
|
||||||
# 提取采样率、位深、声道数
|
print("提取采样率、位深、声道数")
|
||||||
global SAMPLE_RATE, BITS_PER_SAMPLE, CHANNELS
|
global SAMPLE_RATE, BITS_PER_SAMPLE, CHANNELS
|
||||||
SAMPLE_RATE = int.from_bytes(header[24:28], 'little')
|
SAMPLE_RATE = int.from_bytes(header[24:28], 'little')
|
||||||
BITS_PER_SAMPLE = int.from_bytes(header[34:36], 'little')
|
BITS_PER_SAMPLE = int.from_bytes(header[34:36], 'little')
|
||||||
CHANNELS = int.from_bytes(header[22:24], 'little')
|
CHANNELS = int.from_bytes(header[22:24], 'little')
|
||||||
|
|
||||||
# 重新初始化 I2S 输出
|
print("初始化 I2S 输出")
|
||||||
audio_out = init_i2s()
|
audio_out = init_i2s()
|
||||||
|
print("开始流式播放")
|
||||||
# 开始流式播放
|
chunk_size = 512
|
||||||
chunk_size = 1024
|
while shared_vars.handle_task_id == current_task_id:
|
||||||
|
|
||||||
while True:
|
|
||||||
chunk = response.raw.read(chunk_size)
|
chunk = response.raw.read(chunk_size)
|
||||||
if not chunk:
|
if not chunk:
|
||||||
break
|
break
|
||||||
@@ -114,26 +115,8 @@ class InterphoneHandler:
|
|||||||
audio_out.deinit()
|
audio_out.deinit()
|
||||||
if 'response' in locals():
|
if 'response' in locals():
|
||||||
response.close()
|
response.close()
|
||||||
|
print('音频播放完成')
|
||||||
|
|
||||||
def stream_and_play(self, data):
|
def stop_playing(self, data):
|
||||||
i2s = init_i2s()
|
print("停止播放音频")
|
||||||
url = "http://iot.julecn.com/interphone/get_voice?name=" + data['name'] # 替换为音频文件的URL
|
pass
|
||||||
print(url)
|
|
||||||
self.play_audio_stream(i2s, url)
|
|
||||||
|
|
||||||
|
|
||||||
def generate_random_hex():
|
|
||||||
# 初始化一个空的字节数组,用于存储随机字节
|
|
||||||
random_bytes = bytearray()
|
|
||||||
|
|
||||||
# 循环 4 次,每次生成 32 位(4 字节)的随机数
|
|
||||||
for _ in range(4):
|
|
||||||
# 生成 32 位随机数
|
|
||||||
rand_32_bits = urandom.getrandbits(32)
|
|
||||||
# 将 32 位随机数转换为 4 字节,并添加到字节数组中
|
|
||||||
random_bytes.extend(rand_32_bits.to_bytes(4, 'big'))
|
|
||||||
|
|
||||||
# 将随机字节转换为十六进制字符串
|
|
||||||
hex_string = ubinascii.hexlify(random_bytes).decode()
|
|
||||||
return hex_string
|
|
||||||
|
|
||||||
|
|||||||
41
SingletonThreadPool.py
Normal file
41
SingletonThreadPool.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import _thread
|
||||||
|
import time
|
||||||
|
import gc
|
||||||
|
|
||||||
|
class SingletonThreadPool:
|
||||||
|
_instance = None
|
||||||
|
|
||||||
|
def __new__(cls):
|
||||||
|
if not cls._instance:
|
||||||
|
pool_size = 2
|
||||||
|
cls._instance = super().__new__(cls)
|
||||||
|
cls._instance.pool_size = pool_size
|
||||||
|
cls._instance.task_queue = []
|
||||||
|
cls._instance.pool_lock = _thread.allocate_lock()
|
||||||
|
# 创建线程池
|
||||||
|
for _ in range(pool_size):
|
||||||
|
_thread.start_new_thread(cls._instance.worker, ())
|
||||||
|
return cls._instance
|
||||||
|
|
||||||
|
def worker(self):
|
||||||
|
while True:
|
||||||
|
self.pool_lock.acquire()
|
||||||
|
if self.task_queue:
|
||||||
|
task, args = self.task_queue.pop(0)
|
||||||
|
self.pool_lock.release()
|
||||||
|
try:
|
||||||
|
task(*args)
|
||||||
|
gc.collect()
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Task execution error: {e}")
|
||||||
|
else:
|
||||||
|
self.pool_lock.release()
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def add_task(self, task, *args):
|
||||||
|
self.pool_lock.acquire()
|
||||||
|
self.task_queue.append((task, args))
|
||||||
|
self.pool_lock.release()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
35
boot.py
35
boot.py
@@ -7,10 +7,17 @@ import urandom
|
|||||||
import hashlib
|
import hashlib
|
||||||
import _thread
|
import _thread
|
||||||
import ujson
|
import ujson
|
||||||
|
import gc
|
||||||
|
|
||||||
|
import shared_vars
|
||||||
|
from SingletonThreadPool import SingletonThreadPool
|
||||||
|
|
||||||
from InterphoneHandler import InterphoneHandler
|
from InterphoneHandler import InterphoneHandler
|
||||||
|
|
||||||
|
|
||||||
|
gc.enable()
|
||||||
|
|
||||||
|
|
||||||
# Wi-Fi配置
|
# Wi-Fi配置
|
||||||
WIFI_SSID = "JULM"
|
WIFI_SSID = "JULM"
|
||||||
WIFI_PASSWORD = "11223344"
|
WIFI_PASSWORD = "11223344"
|
||||||
@@ -127,16 +134,19 @@ def handle_action(action, data):
|
|||||||
method = getattr(handler, method_part, None)
|
method = getattr(handler, method_part, None)
|
||||||
if method and callable(method):
|
if method and callable(method):
|
||||||
print(f"执行 {action} 方法")
|
print(f"执行 {action} 方法")
|
||||||
method(data)
|
shared_vars.handle_task_id = generate_random_hex()
|
||||||
|
#method(data)
|
||||||
|
thread_pool = SingletonThreadPool()
|
||||||
|
|
||||||
|
thread_pool.add_task(method,data)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
print(f"处理器 {class_part} 没有方法: {method_part}")
|
print(f"处理器 {class_part} 没有方法: {method_part}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"执行 {action} 失败: {str(e)}")
|
print(f"执行 {action} 失败: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
def handle_new_data(data):
|
def handle_new_data(data):
|
||||||
print(f"接收到新数据: {data}")
|
print(f"接收到新数据: {data}")
|
||||||
# 修改后的处理逻辑
|
|
||||||
try:
|
try:
|
||||||
# 解析JSON数据
|
# 解析JSON数据
|
||||||
message = ujson.loads(data)
|
message = ujson.loads(data)
|
||||||
@@ -151,7 +161,6 @@ def handle_new_data(data):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"数据处理异常: {str(e)}")
|
print(f"数据处理异常: {str(e)}")
|
||||||
|
|
||||||
|
|
||||||
def receive_message(sock):
|
def receive_message(sock):
|
||||||
header = b""
|
header = b""
|
||||||
while len(header) < 2: # 确保接收到至少2字节头部
|
while len(header) < 2: # 确保接收到至少2字节头部
|
||||||
@@ -233,7 +242,6 @@ def send_text(sock, message):
|
|||||||
print(f"发送失败:{str(e)}")
|
print(f"发送失败:{str(e)}")
|
||||||
raise # 抛出异常供上层处理
|
raise # 抛出异常供上层处理
|
||||||
|
|
||||||
|
|
||||||
# 启动接收数据的线程
|
# 启动接收数据的线程
|
||||||
_thread.start_new_thread(websocket_receive_thread, ())
|
_thread.start_new_thread(websocket_receive_thread, ())
|
||||||
|
|
||||||
@@ -261,8 +269,6 @@ def ws_client():
|
|||||||
time.sleep(5)
|
time.sleep(5)
|
||||||
reset()
|
reset()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def force_cleanup():
|
def force_cleanup():
|
||||||
"""强制清理残留资源"""
|
"""强制清理残留资源"""
|
||||||
global WS_SOCK
|
global WS_SOCK
|
||||||
@@ -288,4 +294,19 @@ def check_connection_alive():
|
|||||||
return False
|
return False
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def generate_random_hex():
|
||||||
|
# 初始化一个空的字节数组,用于存储随机字节
|
||||||
|
random_bytes = bytearray()
|
||||||
|
|
||||||
|
# 循环 4 次,每次生成 32 位(4 字节)的随机数
|
||||||
|
for _ in range(4):
|
||||||
|
# 生成 32 位随机数
|
||||||
|
rand_32_bits = urandom.getrandbits(32)
|
||||||
|
# 将 32 位随机数转换为 4 字节,并添加到字节数组中
|
||||||
|
random_bytes.extend(rand_32_bits.to_bytes(4, 'big'))
|
||||||
|
|
||||||
|
# 将随机字节转换为十六进制字符串
|
||||||
|
hex_string = ubinascii.hexlify(random_bytes).decode()
|
||||||
|
return hex_string
|
||||||
|
|
||||||
ws_client()
|
ws_client()
|
||||||
|
|||||||
1
shared_vars.py
Normal file
1
shared_vars.py
Normal file
@@ -0,0 +1 @@
|
|||||||
|
handle_task_id = None
|
||||||
Reference in New Issue
Block a user