Compare commits
No commits in common. "master" and "develop" have entirely different histories.
10
Squirrowse.Client/Properties/launchSettings.json
Normal file
10
Squirrowse.Client/Properties/launchSettings.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"Squirrowse.Client": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"environmentVariables": {
|
||||||
|
"DOTNET_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
61
Squirrowse.Client/Service/ActionDispatcher.cs
Normal file
61
Squirrowse.Client/Service/ActionDispatcher.cs
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
using Squirrowse.Core.Services;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Service
|
||||||
|
{
|
||||||
|
public class ActionDispatcher : IActionDispatcher
|
||||||
|
{
|
||||||
|
private readonly ICameraService camera;
|
||||||
|
private readonly IConnectionManager connectionManager;
|
||||||
|
private readonly ILogger<ActionDispatcher> logger;
|
||||||
|
private readonly HubConnection session;
|
||||||
|
private bool streamOn = false;
|
||||||
|
public ActionDispatcher(ILogger<ActionDispatcher> logger, IConnectionManager connectionManager,
|
||||||
|
ICameraService camera)
|
||||||
|
{
|
||||||
|
this.connectionManager = connectionManager;
|
||||||
|
this.logger = logger;
|
||||||
|
this.camera = camera;
|
||||||
|
session = connectionManager.GetConnection().Result;
|
||||||
|
session.On("Start", StartStream);
|
||||||
|
//session.On("StartEnum", StartStreamEnumerable);
|
||||||
|
session.On("Stop", StopStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task StopStream()
|
||||||
|
{
|
||||||
|
streamOn = false;
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SayHello()
|
||||||
|
{
|
||||||
|
await session.SendAsync("AddToGroup", Groups.debug);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SendStreamAsync(IAsyncEnumerable<byte[]> asb)
|
||||||
|
{
|
||||||
|
if(!streamOn)return;
|
||||||
|
logger.LogInformation($"{nameof(SendStreamAsync)} Start stream");
|
||||||
|
|
||||||
|
await session.SendAsync("UploadByteStream", asb);
|
||||||
|
|
||||||
|
logger.LogInformation($"{nameof(SendStreamAsync)} End stream");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task StartStream()
|
||||||
|
{
|
||||||
|
if (streamOn) return;
|
||||||
|
streamOn = true;
|
||||||
|
await SendStreamAsync(camera.GetFramesAsyncEnumerator());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
29
Squirrowse.Client/Service/Camera.cs
Normal file
29
Squirrowse.Client/Service/Camera.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using OpenCvSharp;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Service
|
||||||
|
{
|
||||||
|
public class Camera : CameraFactory
|
||||||
|
{
|
||||||
|
private readonly bool Disposable;
|
||||||
|
private readonly double Fps;
|
||||||
|
private readonly int Height;
|
||||||
|
private readonly int Width;
|
||||||
|
|
||||||
|
public Camera(int height = 480, int width = 640, double fps = 30f)
|
||||||
|
{
|
||||||
|
Height = height;
|
||||||
|
Width = width;
|
||||||
|
Fps = fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override VideoCapture GetCamera()
|
||||||
|
{
|
||||||
|
var cam = new VideoCapture(CaptureDevice.Any)
|
||||||
|
{
|
||||||
|
Fps = Fps, FrameHeight = Height, FrameWidth = Width
|
||||||
|
};
|
||||||
|
|
||||||
|
return cam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Squirrowse.Client/Service/CameraFactory.cs
Normal file
9
Squirrowse.Client/Service/CameraFactory.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using OpenCvSharp;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Service
|
||||||
|
{
|
||||||
|
public abstract class CameraFactory
|
||||||
|
{
|
||||||
|
public abstract VideoCapture GetCamera();
|
||||||
|
}
|
||||||
|
}
|
35
Squirrowse.Client/Service/CameraService.cs
Normal file
35
Squirrowse.Client/Service/CameraService.cs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using OpenCvSharp;
|
||||||
|
using Squirrowse.Core.Services;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Service
|
||||||
|
{
|
||||||
|
public class CameraService : ICameraService
|
||||||
|
{
|
||||||
|
private readonly VideoCapture _videoCapture;
|
||||||
|
|
||||||
|
public CameraService(CameraFactory cam)
|
||||||
|
{
|
||||||
|
_videoCapture = cam.GetCamera();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task<Mat> GetFrame()
|
||||||
|
{
|
||||||
|
var video = _videoCapture.RetrieveMat();
|
||||||
|
return video;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async IAsyncEnumerable<byte[]> GetFramesAsyncEnumerator()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
using var fr = await GetFrame();
|
||||||
|
yield return fr.ConvertToJpgByte();
|
||||||
|
await Task.Delay(1000 / 30);
|
||||||
|
}
|
||||||
|
//fr.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Squirrowse.Client/Service/IActionDispatcher.cs
Normal file
13
Squirrowse.Client/Service/IActionDispatcher.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Service
|
||||||
|
{
|
||||||
|
public interface IActionDispatcher
|
||||||
|
{
|
||||||
|
Task SendStreamAsync(IAsyncEnumerable<byte[]> asb);
|
||||||
|
Task StartStream();
|
||||||
|
Task StopStream();
|
||||||
|
Task SayHello();
|
||||||
|
}
|
||||||
|
}
|
12
Squirrowse.Client/Service/ICameraService.cs
Normal file
12
Squirrowse.Client/Service/ICameraService.cs
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using OpenCvSharp;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Service
|
||||||
|
{
|
||||||
|
public interface ICameraService
|
||||||
|
{
|
||||||
|
Task<Mat> GetFrame();
|
||||||
|
IAsyncEnumerable<byte[]> GetFramesAsyncEnumerator();
|
||||||
|
}
|
||||||
|
}
|
11
Squirrowse.Client/appsettings.Development.json
Normal file
11
Squirrowse.Client/appsettings.Development.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information",
|
||||||
|
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||||
|
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
9
Squirrowse.Client/appsettings.json
Normal file
9
Squirrowse.Client/appsettings.json
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
34
Squirrowse.Core.Tests/ImgExtensionTests.cs
Normal file
34
Squirrowse.Core.Tests/ImgExtensionTests.cs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
using FluentAssertions;
|
||||||
|
using OpenCvSharp;
|
||||||
|
using Squirrowse.Core.Services;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace Squirrowse.Core.Tests
|
||||||
|
{
|
||||||
|
public class ImgExtensionTests
|
||||||
|
{
|
||||||
|
private readonly Mat sampleMat = new Mat(500, 600, MatType.CV_8UC3);
|
||||||
|
|
||||||
|
[SkippableFact]
|
||||||
|
public void ByteShouldBeConvertedToMat()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
Skip.If(true, "Cannot use fluent assertion in this kind of test (compare pointer to obj)");
|
||||||
|
//
|
||||||
|
var bytes = sampleMat.ConvertToJpgByte();
|
||||||
|
|
||||||
|
var reMet = bytes.ConvertByteToMat();
|
||||||
|
|
||||||
|
reMet.Should().BeEquivalentTo(sampleMat);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MatShouldBeConvertedToByteArr()
|
||||||
|
{
|
||||||
|
var newByteArr = sampleMat.ConvertToJpgByte();
|
||||||
|
|
||||||
|
newByteArr.Should().BeOfType(typeof(byte[]));
|
||||||
|
newByteArr.Should().NotBeNullOrEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
Squirrowse.Core.Tests/Squirrowse.Core.Tests.csproj
Normal file
23
Squirrowse.Core.Tests/Squirrowse.Core.Tests.csproj
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="FluentAssertions" Version="5.9.0" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.2.0" />
|
||||||
|
<PackageReference Include="xunit" Version="2.4.0" />
|
||||||
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||||
|
<PackageReference Include="coverlet.collector" Version="1.0.1" />
|
||||||
|
<PackageReference Include="OpenCvSharp4.Windows" Version="4.1.1.20191021" />
|
||||||
|
<PackageReference Include="Xunit.SkippableFact" Version="1.3.12" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Squirrowse.Core\Squirrowse.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
17
Squirrowse.Core/CoreModule.cs
Normal file
17
Squirrowse.Core/CoreModule.cs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Squirrowse.Core.Services;
|
||||||
|
|
||||||
|
namespace Squirrowse.Core
|
||||||
|
{
|
||||||
|
public static class CoreModule
|
||||||
|
{
|
||||||
|
public static IServiceCollection AddCoreModule(this IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddSingleton(typeof(ILogger<>), typeof(Logger<>));
|
||||||
|
services.AddSingleton<IConnectionManager, ConnectionManager>(x =>
|
||||||
|
new ConnectionManager("http://localhost", 5000));
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
10
Squirrowse.Core/Models/ConnectionType.cs
Normal file
10
Squirrowse.Core/Models/ConnectionType.cs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
namespace Squirrowse.Core.Models
|
||||||
|
{
|
||||||
|
public enum ConnectionType
|
||||||
|
{
|
||||||
|
Unknown = -1,
|
||||||
|
Client,
|
||||||
|
Server,
|
||||||
|
Root
|
||||||
|
}
|
||||||
|
}
|
9
Squirrowse.Core/Models/Groups.cs
Normal file
9
Squirrowse.Core/Models/Groups.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
namespace Squirrowse.Core.Models
|
||||||
|
{
|
||||||
|
public enum Groups
|
||||||
|
{
|
||||||
|
debug = -1,
|
||||||
|
normal,
|
||||||
|
superUser
|
||||||
|
}
|
||||||
|
}
|
16
Squirrowse.Core/Models/User.cs
Normal file
16
Squirrowse.Core/Models/User.cs
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
namespace Squirrowse.Core.Models
|
||||||
|
{
|
||||||
|
public class User
|
||||||
|
{
|
||||||
|
public User(string connectionId, string agentName, ConnectionType userType)
|
||||||
|
{
|
||||||
|
ConnectionId = connectionId;
|
||||||
|
AgentName = agentName;
|
||||||
|
UserType = userType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string ConnectionId { get; set; }
|
||||||
|
public string AgentName { get; set; }
|
||||||
|
public ConnectionType UserType { get; set; }
|
||||||
|
}
|
||||||
|
}
|
14
Squirrowse.Core/Models/VStream.cs
Normal file
14
Squirrowse.Core/Models/VStream.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using Squirrowse.Core.Models;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Squirrowse.Client.Models
|
||||||
|
{
|
||||||
|
public class VStream
|
||||||
|
{
|
||||||
|
public User user { get; set; }
|
||||||
|
public byte[] FrameBytes { get; set; }
|
||||||
|
public DateTime TimeStamp => DateTime.Now;
|
||||||
|
public Guid id => Guid.NewGuid();
|
||||||
|
public string Issuer { get; set; }
|
||||||
|
}
|
||||||
|
}
|
51
Squirrowse.Core/Services/ConnectionManager.cs
Normal file
51
Squirrowse.Core/Services/ConnectionManager.cs
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
|
||||||
|
namespace Squirrowse.Core.Services
|
||||||
|
{
|
||||||
|
public class ConnectionManager : IConnectionManager
|
||||||
|
{
|
||||||
|
private readonly HubConnection _connection;
|
||||||
|
private bool Connected;
|
||||||
|
|
||||||
|
public ConnectionManager(string url, int port)
|
||||||
|
{
|
||||||
|
_connection = new HubConnectionBuilder()
|
||||||
|
.WithUrl($"{url}:{port}/StreamHub")
|
||||||
|
.AddMessagePackProtocol()
|
||||||
|
.WithAutomaticReconnect()
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<HubConnection> GetConnection()
|
||||||
|
{
|
||||||
|
return _connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InitConnection(ConnectionType type)
|
||||||
|
{
|
||||||
|
if (_connection.State == HubConnectionState.Connected) return;
|
||||||
|
if (_connection.State == HubConnectionState.Disconnected) await _connection.StartAsync();
|
||||||
|
|
||||||
|
await RegisterOnHub(type);
|
||||||
|
Connected = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task Disconnect()
|
||||||
|
{
|
||||||
|
if (_connection.State == HubConnectionState.Disconnected) throw new Exception();
|
||||||
|
await _connection.StopAsync();
|
||||||
|
Connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task RegisterOnHub(ConnectionType type)
|
||||||
|
{
|
||||||
|
await _connection.SendAsync("AddUser", Environment.UserName, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
13
Squirrowse.Core/Services/IConnectionManager.cs
Normal file
13
Squirrowse.Core/Services/IConnectionManager.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR.Client;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
|
||||||
|
namespace Squirrowse.Core.Services
|
||||||
|
{
|
||||||
|
public interface IConnectionManager
|
||||||
|
{
|
||||||
|
Task<HubConnection> GetConnection();
|
||||||
|
Task InitConnection(ConnectionType type);
|
||||||
|
Task Disconnect();
|
||||||
|
}
|
||||||
|
}
|
20
Squirrowse.Core/Services/ImgExtensions.cs
Normal file
20
Squirrowse.Core/Services/ImgExtensions.cs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using OpenCvSharp;
|
||||||
|
|
||||||
|
namespace Squirrowse.Core.Services
|
||||||
|
{
|
||||||
|
public static class ImgExtensions
|
||||||
|
{
|
||||||
|
public static byte[] ConvertToJpgByte(this Mat mat)
|
||||||
|
{
|
||||||
|
Cv2.ImEncode(".jpg", mat, out var imgbuffer); //no need to dispose
|
||||||
|
return imgbuffer.Any() ? imgbuffer : new byte[] { };
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Mat ConvertByteToMat(this byte[] bytearr)
|
||||||
|
{
|
||||||
|
var tempMat = Cv2.ImDecode(bytearr, ImreadModes.Unchanged); //keep as disposable
|
||||||
|
return tempMat ?? new Mat();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
Squirrowse.Service/Dockerfile
Normal file
21
Squirrowse.Service/Dockerfile
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
FROM mcr.microsoft.com/dotnet/core/aspnet:3.0-buster-slim AS base
|
||||||
|
WORKDIR /app
|
||||||
|
EXPOSE 5000
|
||||||
|
EXPOSE 5001
|
||||||
|
|
||||||
|
FROM mcr.microsoft.com/dotnet/core/sdk:3.0-buster AS build
|
||||||
|
WORKDIR /src
|
||||||
|
COPY ["Squirrowse.Service/Squirrowse.Service.csproj", "Squirrowse.Service/"]
|
||||||
|
COPY ["Squirrowse.Core/Squirrowse.Core.csproj", "Squirrowse.Core/"]
|
||||||
|
RUN dotnet restore "Squirrowse.Service/Squirrowse.Service.csproj"
|
||||||
|
COPY . .
|
||||||
|
WORKDIR "/src/Squirrowse.Service"
|
||||||
|
RUN dotnet build "Squirrowse.Service.csproj" -c Release -o /app/build
|
||||||
|
|
||||||
|
FROM build AS publish
|
||||||
|
RUN dotnet publish "Squirrowse.Service.csproj" -c Release -o /app/publish
|
||||||
|
|
||||||
|
FROM base AS final
|
||||||
|
WORKDIR /app
|
||||||
|
COPY --from=publish /app/publish .
|
||||||
|
ENTRYPOINT ["dotnet", "Squirrowse.Service.dll"]
|
19
Squirrowse.Service/Hubs/IStreamHub.cs
Normal file
19
Squirrowse.Service/Hubs/IStreamHub.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
|
||||||
|
namespace Squirrowse.Service.Hubs
|
||||||
|
{
|
||||||
|
public interface IStreamHub
|
||||||
|
{
|
||||||
|
Task AddUser(string username, ConnectionType type);
|
||||||
|
Task UploadByteStream(IAsyncEnumerable<byte[]> stream);
|
||||||
|
Task Startstream(string userId);
|
||||||
|
Task StopStream(string userId);
|
||||||
|
Task ExecCommandOnAll(string command, object[] act); //gni
|
||||||
|
Task AddToGroup(Groups group, string user = "");
|
||||||
|
Task RemoveFromGroup(Groups group, string user = "");
|
||||||
|
Task<IEnumerable<User>> GetListOfTypeUser(ConnectionType t);
|
||||||
|
Task<IEnumerable<User>> GetAllUsers();
|
||||||
|
}
|
||||||
|
}
|
19
Squirrowse.Service/Hubs/IStreamManager.cs
Normal file
19
Squirrowse.Service/Hubs/IStreamManager.cs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
|
||||||
|
namespace Squirrowse.Service.Hubs
|
||||||
|
{
|
||||||
|
public interface IStreamManager
|
||||||
|
{
|
||||||
|
Task AddUser(string connectionId, string agentName, ConnectionType type);
|
||||||
|
Task RemoveUserbyConnectionId(string connectionId);
|
||||||
|
Task RemoveUserByUserName(string agentName);
|
||||||
|
IEnumerable<User> getServerSideUsers();
|
||||||
|
bool CheckUser(string agentName);
|
||||||
|
IEnumerable<User> getClientSideUsers();
|
||||||
|
IEnumerable<User> getAllUsers();
|
||||||
|
|
||||||
|
Task SaveData(IAsyncEnumerable<byte[]> stream);
|
||||||
|
}
|
||||||
|
}
|
143
Squirrowse.Service/Hubs/StreamHub.cs
Normal file
143
Squirrowse.Service/Hubs/StreamHub.cs
Normal file
@ -0,0 +1,143 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.SignalR;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using OpenCvSharp;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
using Squirrowse.Core.Services;
|
||||||
|
|
||||||
|
namespace Squirrowse.Service.Hubs
|
||||||
|
{
|
||||||
|
public class StreamHub : Hub, IStreamHub //fujka
|
||||||
|
{
|
||||||
|
private readonly ILogger<StreamHub> logger;
|
||||||
|
private readonly IStreamManager manager;
|
||||||
|
|
||||||
|
|
||||||
|
public StreamHub(ILogger<StreamHub> logger, IStreamManager manager)
|
||||||
|
{
|
||||||
|
this.logger = logger;
|
||||||
|
this.manager = manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AddUser(string UserName, ConnectionType type)
|
||||||
|
{
|
||||||
|
await manager.AddUser(Context.ConnectionId, UserName, type);
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case ConnectionType.Client:
|
||||||
|
await AddToGroup(Core.Models.Groups.normal);
|
||||||
|
break;
|
||||||
|
case ConnectionType.Server:
|
||||||
|
await AddToGroup(Core.Models.Groups.superUser);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.LogInformation($"{nameof(AddUser)}: {UserName} of {type}");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task AddToGroup(Groups group, string user = "")
|
||||||
|
{
|
||||||
|
var connectionId = string.IsNullOrWhiteSpace(user) ? Context.ConnectionId : user;
|
||||||
|
await Groups.AddToGroupAsync(connectionId, group.ToString());
|
||||||
|
logger.LogInformation($"{nameof(AddToGroup)}: {connectionId} joined to {group}");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// USE ONLY FOR DEBUG
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="act"></param>
|
||||||
|
/// <returns>DESTRUCTION</returns>
|
||||||
|
public async Task ExecCommandOnAll(string command, object[] act)
|
||||||
|
{
|
||||||
|
await Clients.All.SendCoreAsync(command, act);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RemoveFromGroup(Groups group, string user = "")
|
||||||
|
{
|
||||||
|
var connectionId = string.IsNullOrWhiteSpace(user) ? Context.ConnectionId : user;
|
||||||
|
await Groups.RemoveFromGroupAsync(connectionId, group.ToString());
|
||||||
|
logger.LogInformation($"{nameof(AddToGroup)}: {connectionId} joined to {group}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task Startstream(string clientId)
|
||||||
|
{
|
||||||
|
streamOn = true;
|
||||||
|
//var client = Clients.Client(clientId);
|
||||||
|
await Clients.Groups(Core.Models.Groups.normal.ToString()).SendAsync("Start");
|
||||||
|
// await client.SendAsync("Start");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public async Task StopStream(string clientId)
|
||||||
|
{
|
||||||
|
streamOn = false;
|
||||||
|
//var client = Clients.Client(clientId);
|
||||||
|
// await Clients.Groups(Core.Models.Groups.normal.ToString()).SendAsync("Stop");
|
||||||
|
//await client.SendAsync("Stop");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool streamOn { get; set; }
|
||||||
|
|
||||||
|
public async Task UploadByteStream(IAsyncEnumerable<byte[]> stream)
|
||||||
|
{
|
||||||
|
|
||||||
|
await foreach (var frame in stream)
|
||||||
|
{
|
||||||
|
// var frameStamp = frame.ConvertByteToMat();
|
||||||
|
// string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
|
||||||
|
// CultureInfo.InvariantCulture);
|
||||||
|
// Cv2.PutText(frameStamp, timestamp, new Point(1, 480 / 2), HersheyFonts.HersheySimplex, 0.5f, Scalar.Red);
|
||||||
|
logger.LogInformation($"{this.GetHashCode()}: send frame");
|
||||||
|
|
||||||
|
//logger.LogInformation($"Got frame size: {frame.Length} ");
|
||||||
|
//if (!streamOn) continue;
|
||||||
|
// logger.LogInformation($"Send frame of size: {frame.Length} to {Core.Models.Groups.superUser.ToString()}");
|
||||||
|
var framewithTs = await AddTimestamp(frame);
|
||||||
|
await Clients.Groups(Core.Models.Groups.superUser.ToString()).SendAsync("RecData",framewithTs );
|
||||||
|
logger.LogInformation($"{this.GetHashCode()}: send data");
|
||||||
|
//await Task.Delay(100); //leave some delay for debug purpose
|
||||||
|
await Task.Delay(1000 / 30);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public async Task StartRecord(string connectionId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public async Task StopRecord(string connectionId)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public async Task<byte[]> AddTimestamp(byte[] framebytes)
|
||||||
|
{
|
||||||
|
|
||||||
|
var frameStamp = framebytes.ConvertByteToMat();
|
||||||
|
string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
|
||||||
|
CultureInfo.InvariantCulture);
|
||||||
|
Cv2.PutText(frameStamp, timestamp, new Point(1, 480 / 2), HersheyFonts.HersheySimplex, 0.5f, Scalar.Red);
|
||||||
|
return frameStamp.ConvertToJpgByte();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<User>> GetListOfTypeUser(ConnectionType t)
|
||||||
|
{
|
||||||
|
if (t == ConnectionType.Client) return manager.getClientSideUsers();
|
||||||
|
if (t == ConnectionType.Server) return manager.getServerSideUsers();
|
||||||
|
return manager.getAllUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<IEnumerable<User>> GetAllUsers()
|
||||||
|
{
|
||||||
|
return manager.getAllUsers();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async IAsyncEnumerable<User> GetListOfTypeUserAsync(ConnectionType t)
|
||||||
|
{
|
||||||
|
var client = await GetListOfTypeUser(t);
|
||||||
|
foreach (var va in client) yield return va;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
Squirrowse.Service/Hubs/StreamManager.cs
Normal file
65
Squirrowse.Service/Hubs/StreamManager.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using OpenCvSharp;
|
||||||
|
using Squirrowse.Core.Models;
|
||||||
|
using Squirrowse.Core.Services;
|
||||||
|
|
||||||
|
namespace Squirrowse.Service.Hubs
|
||||||
|
{
|
||||||
|
public class StreamManager : IStreamManager
|
||||||
|
{
|
||||||
|
private readonly List<User> _users = new List<User>(); //temporary
|
||||||
|
public bool StreamOn { get; set; }
|
||||||
|
public Task AddUser(string connectionId, string userName, ConnectionType type)
|
||||||
|
{
|
||||||
|
_users.Add(new User(connectionId, userName, type));
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task RemoveUserbyConnectionId(string connectionId)
|
||||||
|
{
|
||||||
|
_users.Remove(_users.First(user => user.ConnectionId == connectionId));
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task RemoveUserByUserName(string userName)
|
||||||
|
{
|
||||||
|
_users.RemoveAll(user => user.AgentName == userName);
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<User> getServerSideUsers()
|
||||||
|
{
|
||||||
|
return _users.Where(user => user.UserType == ConnectionType.Server);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public IEnumerable<User> getClientSideUsers()
|
||||||
|
{
|
||||||
|
return _users.Where(user => user.UserType == ConnectionType.Client);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckUser(string userName)
|
||||||
|
{
|
||||||
|
return _users.Any(user => user.AgentName == userName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerable<User> getAllUsers()
|
||||||
|
{
|
||||||
|
// var t = _users;
|
||||||
|
return _users;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task SaveData(IAsyncEnumerable<byte[]> stream)
|
||||||
|
{
|
||||||
|
VideoWriter output = new VideoWriter("m.avi",FourCC.DIVX,30,new Size(640,480));
|
||||||
|
|
||||||
|
await foreach (var b in stream)
|
||||||
|
{
|
||||||
|
output.Write(b.ConvertByteToMat());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
66
Squirrowse.Service/Program.cs
Normal file
66
Squirrowse.Service/Program.cs
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using NLog;
|
||||||
|
using NLog.Extensions.Logging;
|
||||||
|
using NLog.Web;
|
||||||
|
|
||||||
|
namespace Squirrowse.Service
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static IConfigurationRoot Configuration { get; set; }
|
||||||
|
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Configuration = CreateConfigurationBuilder().Build();
|
||||||
|
var logger = GetLogger();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
logger.Debug("Application started");
|
||||||
|
CreateHostBuilder(args)
|
||||||
|
.Build()
|
||||||
|
.Run();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
logger.Error(ex, "Stopped program because of exception when building WebHost");
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
LogManager.Shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IHostBuilder CreateHostBuilder(string[] args)
|
||||||
|
{
|
||||||
|
return Host.CreateDefaultBuilder(args)
|
||||||
|
.ConfigureWebHostDefaults(webBuilder =>
|
||||||
|
{
|
||||||
|
webBuilder.UseStartup<Startup>();
|
||||||
|
webBuilder.UseConfiguration(Configuration);
|
||||||
|
webBuilder.UseNLog();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IConfigurationBuilder CreateConfigurationBuilder()
|
||||||
|
{
|
||||||
|
var environment = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
|
||||||
|
return new ConfigurationBuilder()
|
||||||
|
.SetBasePath(Directory.GetCurrentDirectory())
|
||||||
|
.AddJsonFile("appsettings.json", false, true)
|
||||||
|
.AddJsonFile($"appsettings.{environment}.json", false, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ILogger GetLogger()
|
||||||
|
{
|
||||||
|
var nlogConfigSection = Configuration.GetSection("NLog");
|
||||||
|
LogManager.Configuration = new NLogLoggingConfiguration(nlogConfigSection);
|
||||||
|
ILogger logger = LogManager.GetCurrentClassLogger();
|
||||||
|
return logger;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
40
Squirrowse.Service/Properties/launchSettings.json
Normal file
40
Squirrowse.Service/Properties/launchSettings.json
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"iisSettings": {
|
||||||
|
"windowsAuthentication": false,
|
||||||
|
"anonymousAuthentication": true,
|
||||||
|
"iisExpress": {
|
||||||
|
"applicationUrl": "http://localhost:59337",
|
||||||
|
"sslPort": 44365
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||||
|
"profiles": {
|
||||||
|
"IIS Express": {
|
||||||
|
"commandName": "IISExpress",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Squirrowse.Service": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"launchBrowser": false,
|
||||||
|
"launchUrl": "weatherforecast",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||||
|
},
|
||||||
|
"applicationUrl": "https://localhost:5001;http://localhost:5000"
|
||||||
|
},
|
||||||
|
"Docker": {
|
||||||
|
"commandName": "Docker",
|
||||||
|
"launchBrowser": true,
|
||||||
|
"launchUrl": "{Scheme}://{ServiceHost}:{ServicePort}",
|
||||||
|
"environmentVariables": {
|
||||||
|
"ASPNETCORE_URLS": "https://+:443;http://+:80",
|
||||||
|
"ASPNETCORE_HTTPS_PORT": "44366"
|
||||||
|
},
|
||||||
|
"httpPort": 59338,
|
||||||
|
"useSSL": true,
|
||||||
|
"sslPort": 44366
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
28
Squirrowse.Service/Squirrowse.Service.csproj
Normal file
28
Squirrowse.Service/Squirrowse.Service.csproj
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||||
|
<UserSecretsId>996aee3a-63a2-4e6b-abcd-b0c6a183af8c</UserSecretsId>
|
||||||
|
<DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Controllers\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="MediatR" Version="7.0.0" />
|
||||||
|
<PackageReference Include="MediatR.Extensions.Microsoft.DependencyInjection" Version="7.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.App" Version="3.0.0-*" />
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.SignalR.Protocols.MessagePack" Version="3.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" />
|
||||||
|
<PackageReference Include="NLog.Web.AspNetCore" Version="4.9.0" />
|
||||||
|
<PackageReference Include="System.Reactive.Linq" Version="4.0.0" />
|
||||||
|
<PackageReference Include="OpenCvSharp4.Windows" Version="4.1.1.20191021" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Squirrowse.Core\Squirrowse.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
54
Squirrowse.Service/Startup.cs
Normal file
54
Squirrowse.Service/Startup.cs
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
using System.Reflection;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.AspNetCore.Hosting;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Hosting;
|
||||||
|
using Squirrowse.Core;
|
||||||
|
using Squirrowse.Service.Hubs;
|
||||||
|
|
||||||
|
namespace Squirrowse.Service
|
||||||
|
{
|
||||||
|
public class Startup
|
||||||
|
{
|
||||||
|
public Startup(IConfiguration configuration)
|
||||||
|
{
|
||||||
|
Configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IConfiguration Configuration { get; }
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to add services to the container.
|
||||||
|
public void ConfigureServices(IServiceCollection services)
|
||||||
|
{
|
||||||
|
services.AddControllers();
|
||||||
|
services.AddMediatR(Assembly.GetAssembly(typeof(Startup)));
|
||||||
|
//services.AddSingleton<IStreamHub, StreamHub>();
|
||||||
|
services.AddSingleton<IStreamManager, StreamManager>();
|
||||||
|
services.AddCoreModule();
|
||||||
|
services.AddSignalR()
|
||||||
|
.AddHubOptions<StreamHub
|
||||||
|
>(opt => opt.MaximumReceiveMessageSize = 102400000) //~100mb per frame instead of 32kb default
|
||||||
|
.AddMessagePackProtocol();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
|
||||||
|
{
|
||||||
|
if (env.IsDevelopment()) app.UseDeveloperExceptionPage();
|
||||||
|
|
||||||
|
app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
app.UseEndpoints(endpoints =>
|
||||||
|
{
|
||||||
|
endpoints.MapControllers();
|
||||||
|
endpoints.MapHub<StreamHub>($"{nameof(StreamHub)}");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Squirrowse.Service/appsettings.Development.json
Normal file
11
Squirrowse.Service/appsettings.Development.json
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Debug",
|
||||||
|
"System": "Information",
|
||||||
|
"Microsoft": "Information",
|
||||||
|
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||||
|
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
43
Squirrowse.Service/appsettings.json
Normal file
43
Squirrowse.Service/appsettings.json
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
{
|
||||||
|
"Logging": {
|
||||||
|
"LogLevel": {
|
||||||
|
"Default": "Information",
|
||||||
|
"Microsoft": "Warning",
|
||||||
|
"Microsoft.Hosting.Lifetime": "Information",
|
||||||
|
"Microsoft.AspNetCore.SignalR": "Debug",
|
||||||
|
"Microsoft.AspNetCore.Http.Connections": "Debug"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"NLog": {
|
||||||
|
"autoreload": true,
|
||||||
|
"throwConfigExceptions": true,
|
||||||
|
"variables": {
|
||||||
|
"logDirectory": "${basedir}/logs"
|
||||||
|
},
|
||||||
|
"targets": {
|
||||||
|
"FileLogger": {
|
||||||
|
"type": "AsyncWrapper",
|
||||||
|
"target": {
|
||||||
|
"wrappedFile": {
|
||||||
|
"type": "File",
|
||||||
|
"fileName": "${logDirectory}/${machinename}.Log.txt",
|
||||||
|
"layout": "${longdate} ${level}: ${message} ${exception:format=tostring}",
|
||||||
|
"archiveFileName": "${logDirectory}/archives/${machinename}.Log_{#}.txt",
|
||||||
|
"archiveDateFormat": "yyyy-MM-dd",
|
||||||
|
"archiveAboveSize": "5242880",
|
||||||
|
"archiveEvery": "Day",
|
||||||
|
"archiveNumbering": "DateAndSequence",
|
||||||
|
"maxArchiveFiles": "90"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"logger": "*",
|
||||||
|
"writeTo": "FileLogger"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"AllowedHosts": "*"
|
||||||
|
}
|
BIN
Squirrowse.Service/dll/openh264-1.8.0-win64.dll
Normal file
BIN
Squirrowse.Service/dll/openh264-1.8.0-win64.dll
Normal file
Binary file not shown.
BIN
Squirrowse.Service/dupa.avi
Normal file
BIN
Squirrowse.Service/dupa.avi
Normal file
Binary file not shown.
BIN
Squirrowse.Service/dupa.mkv
Normal file
BIN
Squirrowse.Service/dupa.mkv
Normal file
Binary file not shown.
136
Squirrowse.Web/Pages/Hub.razor
Normal file
136
Squirrowse.Web/Pages/Hub.razor
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
@page "/hub"
|
||||||
|
|
||||||
|
<h3>Hub</h3>
|
||||||
|
|
||||||
|
@using System.Collections
|
||||||
|
@using Microsoft.AspNetCore.SignalR.Client
|
||||||
|
@using Squirrowse.Core.Models
|
||||||
|
@using Squirrowse.Core.Services
|
||||||
|
@inject IConnectionManager _connection;
|
||||||
|
|
||||||
|
@*<button id="LoadData"class="btn btn-success btn-sm" @onclick="@(() => loadData())">dupa123 </button>*@
|
||||||
|
|
||||||
|
<div class="card border-primary mb-3" style="max-width: 20rem;">
|
||||||
|
@if (agents != null && agents.Any())
|
||||||
|
{
|
||||||
|
@foreach (var agent in agents)
|
||||||
|
{
|
||||||
|
<div class="card-body">
|
||||||
|
<div>
|
||||||
|
<h3 class="badge-primary">
|
||||||
|
@agent.AgentName -> @agent.UserType.ToString()
|
||||||
|
</h3>
|
||||||
|
<div style="padding-top:10px">
|
||||||
|
<button id="ViewCast" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-success btn-sm" @onclick="@(() => OnViewCastClicked(agent.ConnectionId))">
|
||||||
|
View cast
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button id="StopViewCast" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() => OnStopViewCastClicked(agent.ConnectionId))">
|
||||||
|
Stop cast
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<button id="StartRecording" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() =>StartRecording(agent.ConnectionId))">
|
||||||
|
Stop cast
|
||||||
|
</button>
|
||||||
|
<button id="StartRecording" disabled="@(IsViewingCastOf(agent.AgentName))" class="btn btn-warning btn-sm" @onclick="@(() =>StopRecording(agent.ConnectionId))">
|
||||||
|
Stop cast
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-header badge-warning">No Cams</h3>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="border">
|
||||||
|
<img id='screenImage' src="@imageSource" />
|
||||||
|
</div>
|
||||||
|
@code{
|
||||||
|
|
||||||
|
private List<User> agents=new List<User>();
|
||||||
|
|
||||||
|
HubConnection connection;
|
||||||
|
string imageSource = null;
|
||||||
|
string CurrentViewCastAgent = null;
|
||||||
|
|
||||||
|
protected override async Task OnInitializedAsync()
|
||||||
|
{
|
||||||
|
await _connection.InitConnection(ConnectionType.Server);
|
||||||
|
connection = await _connection.GetConnection();
|
||||||
|
connection.On<byte[]>("RecData", OnStreamDataReceived);
|
||||||
|
|
||||||
|
await foreach (var user in connection.StreamAsync<User>("GetListOfTypeUserAsync", ConnectionType.Client).ConfigureAwait(false))
|
||||||
|
{
|
||||||
|
agents.Add(user);
|
||||||
|
this.StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool IsViewingCastOf(string agentName)
|
||||||
|
{
|
||||||
|
return agentName == CurrentViewCastAgent;
|
||||||
|
}
|
||||||
|
async Task StartRecording(string agent)
|
||||||
|
{
|
||||||
|
await connection.SendAsync("StartRecord");
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
async Task StopRecording(string agent)
|
||||||
|
{
|
||||||
|
await connection.SendAsync("StopRecord");
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
async Task OnStreamDataReceived(byte[] streamData)
|
||||||
|
{
|
||||||
|
//await foreach (var t in streamData)
|
||||||
|
//{
|
||||||
|
// var base64 = Convert.ToBase64String(t);
|
||||||
|
// imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||||
|
// StateHasChanged();
|
||||||
|
//}
|
||||||
|
|
||||||
|
var base64 = Convert.ToBase64String(streamData);
|
||||||
|
imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
async Task OnStreamDataReceivedEn(byte[] streamData)
|
||||||
|
{
|
||||||
|
//await foreach (var t in streamData)
|
||||||
|
//{
|
||||||
|
// var base64 = Convert.ToBase64String(t);
|
||||||
|
// imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||||
|
// StateHasChanged();
|
||||||
|
//}
|
||||||
|
|
||||||
|
var base64 = Convert.ToBase64String(streamData);
|
||||||
|
imageSource = String.Format("data:image/jpg;base64,{0}", base64);
|
||||||
|
StateHasChanged();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnViewCastClicked(string agentName)
|
||||||
|
{
|
||||||
|
CurrentViewCastAgent = agentName;
|
||||||
|
await connection.InvokeAsync("Startstream", agentName);
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task OnStopViewCastClicked(string agentName)
|
||||||
|
{
|
||||||
|
CurrentViewCastAgent = null;
|
||||||
|
await connection.InvokeAsync("StopStream", agentName);
|
||||||
|
imageSource = null;
|
||||||
|
StateHasChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,6 +19,7 @@ namespace squirrowse.web.Data
|
|||||||
public async Task<List<string>> tags()
|
public async Task<List<string>> tags()
|
||||||
{
|
{
|
||||||
var tlist = new List<string>();
|
var tlist = new List<string>();
|
||||||
|
// using var db = new LiteDatabase("db.db");
|
||||||
var t = db.GetCollection<Frame>();
|
var t = db.GetCollection<Frame>();
|
||||||
|
|
||||||
foreach (var frame in t.FindAll().Where(x => x.Objects != null))
|
foreach (var frame in t.FindAll().Where(x => x.Objects != null))
|
||||||
@ -33,6 +34,7 @@ namespace squirrowse.web.Data
|
|||||||
public async Task<Dictionary<string, List<Frame>>> galeryEntireView()
|
public async Task<Dictionary<string, List<Frame>>> galeryEntireView()
|
||||||
{
|
{
|
||||||
var tags = await this.tags();
|
var tags = await this.tags();
|
||||||
|
// using var db = new LiteDatabase("db.db");
|
||||||
var t = db.GetCollection<Frame>();
|
var t = db.GetCollection<Frame>();
|
||||||
var d = new Dictionary<string, List<Frame>>();
|
var d = new Dictionary<string, List<Frame>>();
|
||||||
|
|
||||||
@ -42,11 +44,17 @@ namespace squirrowse.web.Data
|
|||||||
var t2 = t1.Where(x => x.Objects.Any(y => y.ObjectProperty == tag));
|
var t2 = t1.Where(x => x.Objects.Any(y => y.ObjectProperty == tag));
|
||||||
d.Add(tag, t2.ToList());
|
d.Add(tag, t2.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//var temp = t.Query().Select(x => x.Objects.Where().ToArray();
|
||||||
|
|
||||||
|
// t.Find(x => x.Objects.Any(y => y.ObjectProperty == tag)).ForEach(x => { d.Add(tag, x); });
|
||||||
|
//d.Add(tag,temp);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<Dictionary<string, List<Frame>>> galerViewbyTag(List<string> tags)
|
public async Task<Dictionary<string, List<Frame>>> galerViewbyTag(List<string> tags)
|
||||||
{
|
{
|
||||||
|
// using var db = new LiteDatabase("db.db");
|
||||||
var t = db.GetCollection<Frame>();
|
var t = db.GetCollection<Frame>();
|
||||||
var d = new Dictionary<string, List<Frame>>();
|
var d = new Dictionary<string, List<Frame>>();
|
||||||
|
|
||||||
@ -56,6 +64,11 @@ namespace squirrowse.web.Data
|
|||||||
var t2 = t1.Where(x => x.Objects.Any(y => y.ObjectProperty == tag));
|
var t2 = t1.Where(x => x.Objects.Any(y => y.ObjectProperty == tag));
|
||||||
d.Add(tag, t2.ToList());
|
d.Add(tag, t2.ToList());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//var temp = t.Query().Select(x => x.Objects.Where().ToArray();
|
||||||
|
|
||||||
|
// t.Find(x => x.Objects.Any(y => y.ObjectProperty == tag)).ForEach(x => { d.Add(tag, x); });
|
||||||
|
//d.Add(tag,temp);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user