Added Veadotube integration
This commit is contained in:
parent
48dd6858a1
commit
b35183249b
@ -35,6 +35,7 @@ using TwitchChatTTS.Chat.Observers;
|
|||||||
using TwitchChatTTS.Chat.Commands.Limits;
|
using TwitchChatTTS.Chat.Commands.Limits;
|
||||||
using TwitchChatTTS.Hermes.Socket.Requests;
|
using TwitchChatTTS.Hermes.Socket.Requests;
|
||||||
using TwitchChatTTS.Bus;
|
using TwitchChatTTS.Bus;
|
||||||
|
using TwitchChatTTS.Veadotube;
|
||||||
|
|
||||||
// dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained true
|
// dotnet publish -r linux-x64 -p:PublishSingleFile=true --self-contained true
|
||||||
// dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true
|
// dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true
|
||||||
@ -147,6 +148,10 @@ s.AddKeyedSingleton<IWebSocketHandler, EndOfStreamHandler>("7tv");
|
|||||||
s.AddKeyedSingleton<MessageTypeManager<IWebSocketHandler>, SevenMessageTypeManager>("7tv");
|
s.AddKeyedSingleton<MessageTypeManager<IWebSocketHandler>, SevenMessageTypeManager>("7tv");
|
||||||
s.AddKeyedSingleton<SocketClient<WebSocketMessage>, SevenSocketClient>("7tv");
|
s.AddKeyedSingleton<SocketClient<WebSocketMessage>, SevenSocketClient>("7tv");
|
||||||
|
|
||||||
|
// Veadotube
|
||||||
|
s.AddKeyedSingleton<MessageTypeManager<IWebSocketHandler>, VeadoMessageTypeManager>("veadotube");
|
||||||
|
s.AddKeyedSingleton<SocketClient<object>, VeadoSocketClient>("veadotube");
|
||||||
|
|
||||||
// Nightbot
|
// Nightbot
|
||||||
s.AddSingleton<NightbotApiClient>();
|
s.AddSingleton<NightbotApiClient>();
|
||||||
|
|
||||||
|
13
TTS.cs
13
TTS.cs
@ -14,6 +14,7 @@ using TwitchChatTTS.Twitch.Socket;
|
|||||||
using TwitchChatTTS.Chat.Commands;
|
using TwitchChatTTS.Chat.Commands;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using TwitchChatTTS.Chat.Speech;
|
using TwitchChatTTS.Chat.Speech;
|
||||||
|
using TwitchChatTTS.Veadotube;
|
||||||
|
|
||||||
namespace TwitchChatTTS
|
namespace TwitchChatTTS
|
||||||
{
|
{
|
||||||
@ -29,6 +30,7 @@ namespace TwitchChatTTS
|
|||||||
private readonly OBSSocketClient _obs;
|
private readonly OBSSocketClient _obs;
|
||||||
private readonly SevenSocketClient _seven;
|
private readonly SevenSocketClient _seven;
|
||||||
private readonly TwitchWebsocketClient _twitch;
|
private readonly TwitchWebsocketClient _twitch;
|
||||||
|
private readonly VeadoSocketClient _veado;
|
||||||
private readonly ICommandFactory _commandFactory;
|
private readonly ICommandFactory _commandFactory;
|
||||||
private readonly ICommandManager _commandManager;
|
private readonly ICommandManager _commandManager;
|
||||||
private readonly IEmoteDatabase _emotes;
|
private readonly IEmoteDatabase _emotes;
|
||||||
@ -45,6 +47,7 @@ namespace TwitchChatTTS
|
|||||||
[FromKeyedServices("obs")] SocketClient<WebSocketMessage> obs,
|
[FromKeyedServices("obs")] SocketClient<WebSocketMessage> obs,
|
||||||
[FromKeyedServices("7tv")] SocketClient<WebSocketMessage> seven,
|
[FromKeyedServices("7tv")] SocketClient<WebSocketMessage> seven,
|
||||||
[FromKeyedServices("twitch")] SocketClient<TwitchWebsocketMessage> twitch,
|
[FromKeyedServices("twitch")] SocketClient<TwitchWebsocketMessage> twitch,
|
||||||
|
[FromKeyedServices("veadotube")] SocketClient<object> veado,
|
||||||
ICommandFactory commandFactory,
|
ICommandFactory commandFactory,
|
||||||
ICommandManager commandManager,
|
ICommandManager commandManager,
|
||||||
IEmoteDatabase emotes,
|
IEmoteDatabase emotes,
|
||||||
@ -61,6 +64,7 @@ namespace TwitchChatTTS
|
|||||||
_obs = (obs as OBSSocketClient)!;
|
_obs = (obs as OBSSocketClient)!;
|
||||||
_seven = (seven as SevenSocketClient)!;
|
_seven = (seven as SevenSocketClient)!;
|
||||||
_twitch = (twitch as TwitchWebsocketClient)!;
|
_twitch = (twitch as TwitchWebsocketClient)!;
|
||||||
|
_veado = (veado as VeadoSocketClient)!;
|
||||||
_commandFactory = commandFactory;
|
_commandFactory = commandFactory;
|
||||||
_commandManager = commandManager;
|
_commandManager = commandManager;
|
||||||
_emotes = emotes;
|
_emotes = emotes;
|
||||||
@ -132,6 +136,15 @@ namespace TwitchChatTTS
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_veado.Initialize();
|
||||||
|
await _veado.Connect();
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
_logger.Warning(e, "Failed to connect to Veado websocket server.");
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _twitch.Connect();
|
await _twitch.Connect();
|
||||||
|
@ -10,6 +10,7 @@ using TwitchChatTTS.Bus.Data;
|
|||||||
using TwitchChatTTS.Hermes.Socket;
|
using TwitchChatTTS.Hermes.Socket;
|
||||||
using TwitchChatTTS.OBS.Socket;
|
using TwitchChatTTS.OBS.Socket;
|
||||||
using TwitchChatTTS.OBS.Socket.Data;
|
using TwitchChatTTS.OBS.Socket.Data;
|
||||||
|
using TwitchChatTTS.Veadotube;
|
||||||
|
|
||||||
namespace TwitchChatTTS.Twitch.Redemptions
|
namespace TwitchChatTTS.Twitch.Redemptions
|
||||||
{
|
{
|
||||||
@ -20,6 +21,7 @@ namespace TwitchChatTTS.Twitch.Redemptions
|
|||||||
private readonly User _user;
|
private readonly User _user;
|
||||||
private readonly OBSSocketClient _obs;
|
private readonly OBSSocketClient _obs;
|
||||||
private readonly HermesSocketClient _hermes;
|
private readonly HermesSocketClient _hermes;
|
||||||
|
private readonly VeadoSocketClient _veado;
|
||||||
private readonly NightbotApiClient _nightbot;
|
private readonly NightbotApiClient _nightbot;
|
||||||
private readonly AudioPlaybackEngine _playback;
|
private readonly AudioPlaybackEngine _playback;
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
@ -32,6 +34,7 @@ namespace TwitchChatTTS.Twitch.Redemptions
|
|||||||
User user,
|
User user,
|
||||||
[FromKeyedServices("obs")] SocketClient<WebSocketMessage> obs,
|
[FromKeyedServices("obs")] SocketClient<WebSocketMessage> obs,
|
||||||
[FromKeyedServices("hermes")] SocketClient<WebSocketMessage> hermes,
|
[FromKeyedServices("hermes")] SocketClient<WebSocketMessage> hermes,
|
||||||
|
[FromKeyedServices("veadotube")] SocketClient<object> veado,
|
||||||
NightbotApiClient nightbot,
|
NightbotApiClient nightbot,
|
||||||
AudioPlaybackEngine playback,
|
AudioPlaybackEngine playback,
|
||||||
ILogger logger)
|
ILogger logger)
|
||||||
@ -41,6 +44,7 @@ namespace TwitchChatTTS.Twitch.Redemptions
|
|||||||
_user = user;
|
_user = user;
|
||||||
_obs = (obs as OBSSocketClient)!;
|
_obs = (obs as OBSSocketClient)!;
|
||||||
_hermes = (hermes as HermesSocketClient)!;
|
_hermes = (hermes as HermesSocketClient)!;
|
||||||
|
_veado = (veado as VeadoSocketClient)!;
|
||||||
_nightbot = nightbot;
|
_nightbot = nightbot;
|
||||||
_playback = playback;
|
_playback = playback;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
@ -220,6 +224,15 @@ namespace TwitchChatTTS.Twitch.Redemptions
|
|||||||
case "NIGHTBOT_CLEAR_QUEUE":
|
case "NIGHTBOT_CLEAR_QUEUE":
|
||||||
await _nightbot.ClearQueue();
|
await _nightbot.ClearQueue();
|
||||||
break;
|
break;
|
||||||
|
case "VEADOTUBE_SET_STATE":
|
||||||
|
await _veado.SetCurrentState(action.Data["state"]);
|
||||||
|
break;
|
||||||
|
case "VEADOTUBE_PUSH_STATE":
|
||||||
|
await _veado.PushState(action.Data["state"]);
|
||||||
|
break;
|
||||||
|
case "VEADOTUBE_POP_STATE":
|
||||||
|
await _veado.PopState(action.Data["state"]);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
_logger.Warning($"Unknown redeemable action has occured. Update needed? [type: {action.Type}][chatter: {senderDisplayName}][chatter id: {senderId}]");
|
_logger.Warning($"Unknown redeemable action has occured. Update needed? [type: {action.Type}][chatter: {senderDisplayName}][chatter id: {senderId}]");
|
||||||
break;
|
break;
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
|
||||||
<PackageReference Include="NAudio" Version="2.2.1" />
|
<PackageReference Include="NAudio" Version="2.2.1" />
|
||||||
<PackageReference Include="NAudio.Extras" Version="2.2.1" />
|
<PackageReference Include="NAudio.Extras" Version="2.2.1" />
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="Serilog" Version="4.0.0" />
|
<PackageReference Include="Serilog" Version="4.0.0" />
|
||||||
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2-dev-00338" />
|
<PackageReference Include="Serilog.AspNetCore" Version="8.0.2-dev-00338" />
|
||||||
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
<PackageReference Include="Serilog.Formatting.Compact" Version="3.0.0" />
|
||||||
|
14
Veadotube/VeadoInstanceInfo.cs
Normal file
14
Veadotube/VeadoInstanceInfo.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
|
namespace TwitchChatTTS.Veadotube
|
||||||
|
{
|
||||||
|
public class VeadoInstanceInfo
|
||||||
|
{
|
||||||
|
[JsonPropertyName("time")]
|
||||||
|
public long Time { get; set; }
|
||||||
|
[JsonPropertyName("name")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
[JsonPropertyName("server")]
|
||||||
|
public string Server { get; set; }
|
||||||
|
}
|
||||||
|
}
|
38
Veadotube/VeadoMessage.cs
Normal file
38
Veadotube/VeadoMessage.cs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
using System.Text.Json.Serialization;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace TwitchChatTTS.Veadotube
|
||||||
|
{
|
||||||
|
public class VeadoPayloadMessage
|
||||||
|
{
|
||||||
|
public string Event { get; set; }
|
||||||
|
public string Type { get; set; }
|
||||||
|
public string Id { get; set; }
|
||||||
|
public object Payload { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VeadoEventMessage
|
||||||
|
{
|
||||||
|
[JsonPropertyName("event")]
|
||||||
|
public string Event { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VeadoNodeState {
|
||||||
|
public string Id { get; set; }
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VeadoNodeStateListMessage : VeadoEventMessage {
|
||||||
|
public IEnumerable<VeadoNodeState> Entries { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VeadoNodeStateMessage : VeadoEventMessage {
|
||||||
|
public string State { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class VeadoNodeThumbMessage {
|
||||||
|
public int Width { get; set; }
|
||||||
|
public int Height { get; set; }
|
||||||
|
public string Png { get; set; }
|
||||||
|
}
|
||||||
|
}
|
17
Veadotube/VeadoMessageTypeManager.cs
Normal file
17
Veadotube/VeadoMessageTypeManager.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using CommonSocketLibrary.Common;
|
||||||
|
using CommonSocketLibrary.Socket.Manager;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Serilog;
|
||||||
|
|
||||||
|
namespace TwitchChatTTS.Veadotube
|
||||||
|
{
|
||||||
|
public class VeadoMessageTypeManager : WebSocketMessageTypeManager
|
||||||
|
{
|
||||||
|
public VeadoMessageTypeManager(
|
||||||
|
[FromKeyedServices("veadotube")] IEnumerable<IWebSocketHandler> handlers,
|
||||||
|
ILogger logger
|
||||||
|
) : base(handlers, logger)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
222
Veadotube/VeadoSocketClient.cs
Normal file
222
Veadotube/VeadoSocketClient.cs
Normal file
@ -0,0 +1,222 @@
|
|||||||
|
using CommonSocketLibrary.Common;
|
||||||
|
using CommonSocketLibrary.Abstract;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Serilog;
|
||||||
|
using System.Text.Json;
|
||||||
|
using CommonSocketLibrary.Backoff;
|
||||||
|
using System.Text;
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
|
||||||
|
namespace TwitchChatTTS.Veadotube
|
||||||
|
{
|
||||||
|
public class VeadoSocketClient : SocketClient<object>
|
||||||
|
{
|
||||||
|
private VeadoInstanceInfo? Instance;
|
||||||
|
|
||||||
|
public bool Connected { get; set; }
|
||||||
|
public bool Identified { get; set; }
|
||||||
|
public bool Streaming { get; set; }
|
||||||
|
|
||||||
|
|
||||||
|
public VeadoSocketClient(
|
||||||
|
[FromKeyedServices("veadotube")] IEnumerable<IWebSocketHandler> handlers,
|
||||||
|
[FromKeyedServices("veadotube")] MessageTypeManager<IWebSocketHandler> typeManager,
|
||||||
|
ILogger logger
|
||||||
|
) : base(logger, new JsonSerializerOptions()
|
||||||
|
{
|
||||||
|
PropertyNameCaseInsensitive = false,
|
||||||
|
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||||
|
})
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task<T> Deserialize<T>(Stream stream)
|
||||||
|
{
|
||||||
|
using StreamReader reader = new StreamReader(stream);
|
||||||
|
string content = await reader.ReadToEndAsync();
|
||||||
|
int index = content.IndexOf(':');
|
||||||
|
string json = content.Substring(index + 1).Replace("\0", string.Empty);
|
||||||
|
T? value = JsonSerializer.Deserialize<T>(json, _options);
|
||||||
|
return value!;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Initialize()
|
||||||
|
{
|
||||||
|
_logger.Information($"Initializing Veadotube websocket client.");
|
||||||
|
OnConnected += (sender, e) =>
|
||||||
|
{
|
||||||
|
Connected = true;
|
||||||
|
_logger.Information("Veadotube websocket client connected.");
|
||||||
|
};
|
||||||
|
|
||||||
|
OnDisconnected += async (sender, e) =>
|
||||||
|
{
|
||||||
|
_logger.Information($"Veadotube websocket client disconnected [status: {e.Status}][reason: {e.Reason}] " + (Identified ? "Will be attempting to reconnect every 30 seconds." : "Will not be attempting to reconnect."));
|
||||||
|
|
||||||
|
Connected = false;
|
||||||
|
Identified = false;
|
||||||
|
Streaming = false;
|
||||||
|
|
||||||
|
await Reconnect(new ExponentialBackoff(5000, 300000));
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task Connect()
|
||||||
|
{
|
||||||
|
if (!UpdateURL() || string.IsNullOrEmpty(Instance?.Server) || string.IsNullOrEmpty(Instance.Name))
|
||||||
|
{
|
||||||
|
_logger.Warning("Lacking connection info for Veadotube websockets. Not connecting to Veadotube.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
string url = $"ws://{Instance.Server}?n={Instance.Name}";
|
||||||
|
_logger.Debug($"Veadotube websocket client attempting to connect to {url}");
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await ConnectAsync(url);
|
||||||
|
}
|
||||||
|
catch (Exception)
|
||||||
|
{
|
||||||
|
_logger.Warning("Connecting to Veadotube failed. Skipping Veadotube websockets.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task FetchStates()
|
||||||
|
{
|
||||||
|
await Send(new VeadoPayloadMessage()
|
||||||
|
{
|
||||||
|
Event = "payload",
|
||||||
|
Type = "stateEvents",
|
||||||
|
Id = "mini",
|
||||||
|
Payload = new VeadoEventMessage()
|
||||||
|
{
|
||||||
|
Event = "list",
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SetCurrentState(string stateId)
|
||||||
|
{
|
||||||
|
await Send(new VeadoPayloadMessage()
|
||||||
|
{
|
||||||
|
Event = "payload",
|
||||||
|
Type = "stateEvents",
|
||||||
|
Id = "mini",
|
||||||
|
Payload = new VeadoNodeStateMessage()
|
||||||
|
{
|
||||||
|
Event = "set",
|
||||||
|
State = stateId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PushState(string stateId)
|
||||||
|
{
|
||||||
|
await Send(new VeadoPayloadMessage()
|
||||||
|
{
|
||||||
|
Event = "payload",
|
||||||
|
Type = "stateEvents",
|
||||||
|
Id = "mini",
|
||||||
|
Payload = new VeadoNodeStateMessage()
|
||||||
|
{
|
||||||
|
Event = "push",
|
||||||
|
State = stateId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task PopState(string stateId)
|
||||||
|
{
|
||||||
|
await Send(new VeadoPayloadMessage()
|
||||||
|
{
|
||||||
|
Event = "payload",
|
||||||
|
Type = "stateEvents",
|
||||||
|
Id = "mini",
|
||||||
|
Payload = new VeadoNodeStateMessage()
|
||||||
|
{
|
||||||
|
Event = "pop",
|
||||||
|
State = stateId
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Send<T>(T data)
|
||||||
|
{
|
||||||
|
if (_socket == null || data == null)
|
||||||
|
return;
|
||||||
|
if (!Connected)
|
||||||
|
{
|
||||||
|
_logger.Debug("Not sending Veadotube message due to no connection.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var content = "nodes:" + JsonSerializer.Serialize(data, _options);
|
||||||
|
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(content);
|
||||||
|
var array = new ArraySegment<byte>(bytes);
|
||||||
|
var total = bytes.Length;
|
||||||
|
var current = 0;
|
||||||
|
|
||||||
|
while (current < total)
|
||||||
|
{
|
||||||
|
var size = Encoding.UTF8.GetBytes(content.Substring(current), array);
|
||||||
|
await _socket.SendAsync(array, WebSocketMessageType.Text, current + size >= total, _cts!.Token);
|
||||||
|
current += size;
|
||||||
|
}
|
||||||
|
_logger.Debug($"Veado TX [message type: {typeof(T).Name}]: " + content);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (_socket.State.ToString().Contains("Close") || _socket.State == WebSocketState.Aborted)
|
||||||
|
{
|
||||||
|
await DisconnectAsync(new SocketDisconnectionEventArgs(_socket.CloseStatus.ToString()!, _socket.CloseStatusDescription ?? string.Empty));
|
||||||
|
_logger.Warning($"Socket state on closing = {_socket.State} | {_socket.CloseStatus?.ToString()} | {_socket.CloseStatusDescription}");
|
||||||
|
}
|
||||||
|
_logger.Error(e, $"Failed to send a websocket message to Veado [message type: {typeof(T).Name}]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool UpdateURL()
|
||||||
|
{
|
||||||
|
string path = Environment.ExpandEnvironmentVariables("%userprofile%/.veadotube/instances");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Directory.Exists(path))
|
||||||
|
{
|
||||||
|
var directory = Directory.CreateDirectory(path);
|
||||||
|
var files = directory.GetFiles()
|
||||||
|
.Where(f => f.Name.StartsWith("mini-"))
|
||||||
|
.OrderByDescending(f => f.CreationTime);
|
||||||
|
if (files.Any())
|
||||||
|
{
|
||||||
|
_logger.Debug("Veadotube's instance file exists: " + files.First().FullName);
|
||||||
|
var data = File.ReadAllText(files.First().FullName);
|
||||||
|
var instance = JsonSerializer.Deserialize<VeadoInstanceInfo>(data);
|
||||||
|
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
Instance = instance;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.Error(ex, "Failed to find Veadotube instance information.");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task OnResponseReceived(object? content)
|
||||||
|
{
|
||||||
|
var contentAsString = JsonSerializer.Serialize(content);
|
||||||
|
_logger.Debug("VEADO RX: " + contentAsString);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user