11
This commit is contained in:
parent
9b7bd2318c
commit
63a0438406
|
|
@ -17,8 +17,8 @@ public class SignalRService : ISignalRService
|
|||
private readonly SemaphoreSlim _semaphore = new(1, 1);
|
||||
private string? _clientId;
|
||||
private bool _isInitialConnection = true;
|
||||
private const int MAX_RETRY_COUNT = 10;
|
||||
private const int RETRY_INTERVAL_MS = 1000;
|
||||
private const int MAX_RETRY_COUNT = 15;
|
||||
private const int RETRY_INTERVAL_MS = 200;
|
||||
private const int HEARTBEAT_INTERVAL_MS = 3000; // 3秒发送一次心跳
|
||||
private Timer? _heartbeatTimer;
|
||||
private DateTime _lastHeartbeatTime = DateTime.MinValue;
|
||||
|
|
@ -78,7 +78,7 @@ public class SignalRService : ISignalRService
|
|||
|
||||
_hubConnection = new HubConnectionBuilder()
|
||||
.WithUrl(hubUrl)
|
||||
.WithAutomaticReconnect([TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(2), TimeSpan.FromSeconds(3)])
|
||||
.WithAutomaticReconnect()
|
||||
.Build();
|
||||
|
||||
// 启动心跳定时器
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"SignalRHubUrl": "http://115.159.44.16/audiohub",
|
||||
"SignalRHubUrl": "http://localhost:81/audiohub",
|
||||
"ConfigBackupPath": "config.json",
|
||||
"AutoConnectToServer": true,
|
||||
"AllowOfflineStart": false
|
||||
|
|
|
|||
BIN
ShengShengBuXi.ConsoleApp/mp3/风铃.wav
Normal file
BIN
ShengShengBuXi.ConsoleApp/mp3/风铃.wav
Normal file
Binary file not shown.
|
|
@ -874,44 +874,101 @@ namespace ShengShengBuXi.Hubs
|
|||
/// </summary>
|
||||
private void InitializeDisplayTextTimer()
|
||||
{
|
||||
// 注意:不再需要实际启动定时器,因为已改为客户端主动请求模式
|
||||
// 但保留此方法以保持代码结构兼容性
|
||||
if (!_isDisplayTimerInitialized)
|
||||
{
|
||||
lock (_displayTimerLock)
|
||||
{
|
||||
if (!_isDisplayTimerInitialized)
|
||||
{
|
||||
_displayTextTimer = new Timer(SendNextDisplayText, null, 0, Timeout.Infinite);
|
||||
// 不再需要实际启动定时器
|
||||
// _displayTextTimer = new Timer(SendNextDisplayText, null, 0, Timeout.Infinite);
|
||||
_isDisplayTimerInitialized = true;
|
||||
_logger.LogInformation("显示文本定时器已初始化");
|
||||
_logger.LogInformation("显示文本系统已初始化(客户端主动获取模式)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 注意:以下方法不再使用,由客户端主动获取替代,保留代码仅作参考
|
||||
/// <summary>
|
||||
/// 发送下一条显示文本
|
||||
/// 发送下一条显示文本(不再使用,由客户端主动获取替代)
|
||||
/// </summary>
|
||||
/// <param name="state">状态对象</param>
|
||||
private async void SendNextDisplayText(object state)
|
||||
{
|
||||
// 这个方法不再使用,由客户端主动获取替代
|
||||
// 保留原有逻辑仅作参考
|
||||
|
||||
try
|
||||
{
|
||||
// 获取随机等待时间(5-10秒)
|
||||
|
||||
// 获取随机等待时间(10-30秒)
|
||||
int nextInterval = new Random().Next(10000, 30000);
|
||||
|
||||
// 设置下一次触发时间
|
||||
_displayTextTimer.Change(nextInterval, Timeout.Infinite);
|
||||
// 设置下一次触发时间,此处设置为较长时间,避免频繁触发未使用的方法
|
||||
_displayTextTimer?.Change(nextInterval, Timeout.Infinite);
|
||||
|
||||
_logger.LogWarning("使用了已废弃的发送显示文本方法,应改为客户端主动获取模式");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"发送显示文本失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 开始接收显示文本(兼容旧客户端,新客户端应使用GetNextDisplayText)
|
||||
/// </summary>
|
||||
public async Task StartReceivingDisplayText()
|
||||
{
|
||||
// 兼容旧版客户端的方法
|
||||
_logger.LogWarning($"客户端 {Context.ConnectionId} 使用了已废弃的StartReceivingDisplayText方法,应改为GetNextDisplayText");
|
||||
|
||||
// 转发到新方法
|
||||
await GetNextDisplayText();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取下一条要显示的文本(由客户端主动请求)
|
||||
/// </summary>
|
||||
/// <returns>处理任务</returns>
|
||||
public async Task GetNextDisplayText()
|
||||
{
|
||||
try
|
||||
{
|
||||
// 检查客户端是否已注册
|
||||
if (!_clients.TryGetValue(Context.ConnectionId, out var clientInfo))
|
||||
{
|
||||
_logger.LogWarning($"未注册的客户端尝试获取显示文本: {Context.ConnectionId}");
|
||||
await Clients.Caller.SendAsync("Error", "请先注册客户端");
|
||||
return;
|
||||
}
|
||||
|
||||
// 检查客户端是否为Display类型
|
||||
if (clientInfo.ClientType != ClientType.Display)
|
||||
{
|
||||
_logger.LogWarning($"非显示端客户端尝试获取显示文本: {Context.ConnectionId}, 类型: {clientInfo.ClientType}");
|
||||
await Clients.Caller.SendAsync("Error", "只有显示端客户端可以获取显示文本");
|
||||
return;
|
||||
}
|
||||
|
||||
_logger.LogInformation($"显示端请求获取下一条显示文本: {Context.ConnectionId}");
|
||||
|
||||
// 检查队列是否为空
|
||||
if (_displayTextQueue.IsEmpty)
|
||||
{
|
||||
// 检查是否需要添加预设文本(如果30秒内没有真实用户说话)
|
||||
// 检查是否需要添加预设文本
|
||||
if (DateTime.Now.Subtract(_lastRealUserSpeakTime).TotalSeconds > 30)
|
||||
{
|
||||
AddFakeTextToQueue();
|
||||
}
|
||||
return;
|
||||
else
|
||||
{
|
||||
_logger.LogInformation("显示文本队列为空,且不需要添加预设文本");
|
||||
// 如果队列为空且不需要添加预设文本,返回空
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 从队列中选择最高优先级的消息
|
||||
|
|
@ -921,29 +978,28 @@ namespace ShengShengBuXi.Hubs
|
|||
|
||||
// 检查是否获取到有效的消息
|
||||
if (highestPriority.Key == Guid.Empty || highestPriority.Value == null)
|
||||
return;
|
||||
|
||||
// 获取大屏显示客户端数量
|
||||
int displayClientsCount = _clients.Values.Count(c => c.ClientType == ClientType.Display);
|
||||
|
||||
if (displayClientsCount > 0)
|
||||
{
|
||||
// 从队列中移除该消息
|
||||
if (_displayTextQueue.TryRemove(highestPriority.Key, out _))
|
||||
{
|
||||
// 发送给所有Display客户端
|
||||
await _hubContext.Clients.Group("displays").SendAsync("ReceiveDisplayText", highestPriority.Value.Text);
|
||||
_logger.LogInformation($"已发送显示文本到大屏: {highestPriority.Value.Text} (来源: {(highestPriority.Value.IsRealUser ? "真实用户" : "预设文本")})");
|
||||
}
|
||||
_logger.LogWarning("无法从队列中获取有效的显示文本");
|
||||
return;
|
||||
}
|
||||
|
||||
// 从队列中移除该消息
|
||||
if (_displayTextQueue.TryRemove(highestPriority.Key, out var textToDisplay))
|
||||
{
|
||||
// 只发送给请求的客户端
|
||||
await Clients.Caller.SendAsync("ReceiveDisplayText", textToDisplay.Text);
|
||||
_logger.LogInformation($"已发送显示文本到客户端: {textToDisplay.Text} (来源: {(textToDisplay.IsRealUser ? "真实用户" : "预设文本")})");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"无法从队列中移除显示文本: {highestPriority.Key}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError($"发送显示文本失败: {ex.Message}");
|
||||
_logger.LogError($"获取显示文本失败: {ex.Message}");
|
||||
}
|
||||
}
|
||||
private static int _presetSentencesIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// 添加预设文本到队列
|
||||
|
|
@ -964,14 +1020,6 @@ namespace ShengShengBuXi.Hubs
|
|||
_presetSentences.Add("时光匆匆流逝,思念却越来越深。");
|
||||
}
|
||||
}
|
||||
//if (_presetSentencesIndex == -1)
|
||||
//{
|
||||
// _presetSentencesIndex = new Random().Next(_presetSentences.Count);
|
||||
//}
|
||||
//if (_presetSentencesIndex >= _presetSentences.Count)
|
||||
//{
|
||||
// _presetSentencesIndex = new Random().Next(_presetSentences.Count); ;
|
||||
//}
|
||||
_presetSentences.OrderBy(it => Guid.NewGuid()).ToList().ForEach(item =>
|
||||
{
|
||||
var displayText = new DisplayText
|
||||
|
|
@ -982,16 +1030,8 @@ namespace ShengShengBuXi.Hubs
|
|||
IsRealUser = false,
|
||||
RecognitionId = ""
|
||||
};
|
||||
//AddRecognizedTextToDisplay(item, false);
|
||||
_displayTextQueue.TryAdd(displayText.Id, displayText);
|
||||
//_logger.LogInformation($"添加预设文本到显示队列: {text}");
|
||||
});
|
||||
|
||||
// 从未最近显示过的句子中随机选择一条
|
||||
//string randomText = _presetSentences[_presetSentencesIndex];
|
||||
|
||||
//_presetSentencesIndex += new Random().Next(3);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -218,6 +218,12 @@
|
|||
} else {
|
||||
isAnimating = false;
|
||||
if (callback) callback();
|
||||
|
||||
// 打字效果完成后,等待随机4-7秒,然后请求下一条文本
|
||||
const delay = Math.floor(Math.random() * 3000) + 4000; // 4000-7000毫秒
|
||||
console.log(`文本显示完成,将在${delay/1000}秒后请求下一条文本`);
|
||||
|
||||
setTimeout(requestNextText, delay);
|
||||
}
|
||||
}
|
||||
typeWriter();
|
||||
|
|
@ -377,11 +383,8 @@
|
|||
console.error("解析显示配置失败:", error);
|
||||
}
|
||||
}
|
||||
// 开始接收显示文本
|
||||
return hubConnection.invoke("StartReceivingDisplayText");
|
||||
})
|
||||
.then(function() {
|
||||
console.log("开始接收显示文本");
|
||||
// 开始请求第一条显示文本
|
||||
requestNextText();
|
||||
})
|
||||
.catch(function(err) {
|
||||
console.error("客户端操作失败:", err);
|
||||
|
|
@ -507,12 +510,9 @@
|
|||
$('#magazine').turn('previous');
|
||||
else if (e.keyCode == 39)
|
||||
$('#magazine').turn('next');
|
||||
// 空格键不再触发说话,改为请求下一条文本
|
||||
else if (e.keyCode == 32 && hubConnection && hubConnection.state === signalR.HubConnectionState.Connected) {
|
||||
hubConnection.invoke("StartReceivingDisplayText")
|
||||
.catch(function(err) {
|
||||
console.error("请求下一条文本失败:", err);
|
||||
});
|
||||
// 空格键请求下一条文本
|
||||
else if (e.keyCode == 32) {
|
||||
requestNextText();
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -625,6 +625,25 @@
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* 请求下一条文本
|
||||
*/
|
||||
function requestNextText() {
|
||||
if (hubConnection && hubConnection.state === signalR.HubConnectionState.Connected) {
|
||||
console.log("正在向服务器请求下一条文本...");
|
||||
hubConnection.invoke("GetNextDisplayText")
|
||||
.catch(function(err) {
|
||||
console.error("请求下一条文本失败:", err);
|
||||
// 如果请求失败,稍后重试
|
||||
setTimeout(requestNextText, 5000);
|
||||
});
|
||||
} else {
|
||||
console.warn("SignalR连接未就绪,无法请求下一条文本");
|
||||
// 如果连接未就绪,稍后重试
|
||||
setTimeout(requestNextText, 3000);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user