Compare commits
No commits in common. "2f23ffe482ee95c8bdf816de5a0c45da64226dad" and "9904fecbeee73443368e13d48c4e6c4f55d556b6" have entirely different histories.
2f23ffe482
...
9904fecbee
|
@ -95,12 +95,6 @@ try
|
||||||
.AllowAnyMethod()
|
.AllowAnyMethod()
|
||||||
.AllowAnyHeader()
|
.AllowAnyHeader()
|
||||||
);
|
);
|
||||||
options.AddPolicy("SignalR", policy => policy
|
|
||||||
.WithOrigins("http://localhost:5173")
|
|
||||||
.AllowAnyHeader()
|
|
||||||
.AllowAnyMethod()
|
|
||||||
.AllowCredentials()
|
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Use SignalR
|
// Use SignalR
|
||||||
|
@ -207,15 +201,12 @@ try
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
app.UseSwaggerUi();
|
app.UseSwaggerUi();
|
||||||
|
|
||||||
// SignalR
|
|
||||||
app.UseWebSockets();
|
|
||||||
app.UseSignalRHubSpecification();
|
app.UseSignalRHubSpecification();
|
||||||
app.UseSignalRHubDevelopmentUI();
|
app.UseSignalRHubDevelopmentUI();
|
||||||
|
|
||||||
// Router
|
// Router
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
app.MapHub<server.Hubs.JtagHub.JtagHub>("hubs/JtagHub");
|
app.MapHub<server.Hubs.JtagHub.JtagHub>("hubs/JtagHub").RequireCors("Users");
|
||||||
|
|
||||||
// Setup Program
|
// Setup Program
|
||||||
MsgBus.Init();
|
MsgBus.Init();
|
||||||
|
|
|
@ -25,19 +25,12 @@ public interface IJtagReceiver
|
||||||
}
|
}
|
||||||
|
|
||||||
[Authorize]
|
[Authorize]
|
||||||
[EnableCors("SignalR")]
|
[EnableCors("Users")]
|
||||||
public class JtagHub : Hub<IJtagReceiver>, IJtagHub
|
public class JtagHub : Hub<IJtagReceiver>, IJtagHub
|
||||||
{
|
{
|
||||||
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
private static NLog.Logger logger = NLog.LogManager.GetCurrentClassLogger();
|
||||||
private static ConcurrentDictionary<string, int> FreqTable = new();
|
private ConcurrentDictionary<string, int> FreqTable = new();
|
||||||
private static ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSourceTable = new();
|
private ConcurrentDictionary<string, CancellationTokenSource> CancellationTokenSourceTable = new();
|
||||||
|
|
||||||
private readonly IHubContext<JtagHub, IJtagReceiver> _hubContext;
|
|
||||||
|
|
||||||
public JtagHub(IHubContext<JtagHub, IJtagReceiver> hubContext)
|
|
||||||
{
|
|
||||||
_hubContext = hubContext;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Optional<Peripherals.JtagClient.Jtag> GetJtagClient(string userName)
|
private Optional<Peripherals.JtagClient.Jtag> GetJtagClient(string userName)
|
||||||
{
|
{
|
||||||
|
@ -99,40 +92,33 @@ public class JtagHub : Hub<IJtagReceiver>, IJtagHub
|
||||||
}
|
}
|
||||||
|
|
||||||
await SetBoundaryScanFreq(freq);
|
await SetBoundaryScanFreq(freq);
|
||||||
var cts = new CancellationTokenSource();
|
var cts = CancellationTokenSource.CreateLinkedTokenSource();
|
||||||
CancellationTokenSourceTable.AddOrUpdate(userName, cts, (key, value) => cts);
|
CancellationTokenSourceTable.AddOrUpdate(userName, cts, (key, value) => cts);
|
||||||
|
|
||||||
_ = Task.Run(
|
_ = Task
|
||||||
() => BoundaryScanLogicPorts(Context.ConnectionId, userName, cts.Token),
|
.Run(
|
||||||
|
() => BoundaryScanLogicPorts(
|
||||||
|
Context.ConnectionId,
|
||||||
|
userName,
|
||||||
|
cts.Token),
|
||||||
cts.Token)
|
cts.Token)
|
||||||
.ContinueWith((task) =>
|
.ContinueWith((task) =>
|
||||||
{
|
{
|
||||||
if (task.IsFaulted)
|
if (!task.IsFaulted)
|
||||||
{
|
{
|
||||||
// 遍历所有异常
|
return;
|
||||||
foreach (var ex in task.Exception.InnerExceptions)
|
|
||||||
{
|
|
||||||
if (ex is OperationCanceledException)
|
|
||||||
{
|
|
||||||
logger.Info($"Boundary scan operation cancelled for user {userName}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
logger.Error($"Boundary scan operation failed for user {userName}: {ex}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (task.IsCanceled)
|
|
||||||
|
if (task.Exception.InnerException is OperationCanceledException)
|
||||||
{
|
{
|
||||||
logger.Info($"Boundary scan operation cancelled for user {userName}");
|
logger.Info($"Boundary scan operation cancelled for user {userName}");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logger.Info($"Boundary scan completed successfully for user {userName}");
|
logger.Error(task.Exception);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
logger.Info($"Boundary scan started for user {userName}");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
catch (Exception error)
|
catch (Exception error)
|
||||||
|
@ -158,12 +144,10 @@ public class JtagHub : Hub<IJtagReceiver>, IJtagHub
|
||||||
|
|
||||||
cts.Cancel();
|
cts.Cancel();
|
||||||
cts.Token.WaitHandle.WaitOne();
|
cts.Token.WaitHandle.WaitOne();
|
||||||
|
|
||||||
logger.Info($"Boundary scan stopped for user {userName}");
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task BoundaryScanLogicPorts(string connectionID, string userName, CancellationToken cancellationToken)
|
private async void BoundaryScanLogicPorts(string connectionID, string userName, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var jtagCtrl = GetJtagClient(userName).OrThrow(() => new InvalidOperationException("JTAG client not found"));
|
var jtagCtrl = GetJtagClient(userName).OrThrow(() => new InvalidOperationException("JTAG client not found"));
|
||||||
var cntFail = 0;
|
var cntFail = 0;
|
||||||
|
@ -177,10 +161,9 @@ public class JtagHub : Hub<IJtagReceiver>, IJtagHub
|
||||||
{
|
{
|
||||||
logger.Error($"User {userName} boundary scan failed for device {jtagCtrl.address}: {ret.Error}");
|
logger.Error($"User {userName} boundary scan failed for device {jtagCtrl.address}: {ret.Error}");
|
||||||
cntFail++;
|
cntFail++;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
await _hubContext.Clients.Client(connectionID).OnReceiveBoundaryScanData(ret.Value);
|
await this.Clients.Client(connectionID).OnReceiveBoundaryScanData(ret.Value);
|
||||||
// logger.Info($"User {userName} successfully completed boundary scan for device {jtagCtrl.address}");
|
// logger.Info($"User {userName} successfully completed boundary scan for device {jtagCtrl.address}");
|
||||||
|
|
||||||
await Task.Delay(FreqTable.TryGetValue(userName, out var freq) ? 1000 / freq : 1000 / 100, cancellationToken);
|
await Task.Delay(FreqTable.TryGetValue(userName, out var freq) ? 1000 / freq : 1000 / 100, cancellationToken);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ref, reactive, watchPostEffect, onMounted, onUnmounted } from "vue";
|
import { ref, reactive, watchPostEffect, onMounted, onUnmounted } from "vue";
|
||||||
import { defineStore } from "pinia";
|
import { defineStore } from "pinia";
|
||||||
import { useLocalStorage } from "@vueuse/core";
|
import { useLocalStorage } from "@vueuse/core";
|
||||||
import { isString, toNumber, isUndefined, type Dictionary } from "lodash";
|
import { isString, toNumber, type Dictionary } from "lodash";
|
||||||
import z from "zod";
|
import z from "zod";
|
||||||
import { isNumber } from "mathjs";
|
import { isNumber } from "mathjs";
|
||||||
import { Mutex, withTimeout } from "async-mutex";
|
import { Mutex, withTimeout } from "async-mutex";
|
||||||
|
@ -9,10 +9,9 @@ import { useConstraintsStore } from "@/stores/constraints";
|
||||||
import { useDialogStore } from "./dialog";
|
import { useDialogStore } from "./dialog";
|
||||||
import { toFileParameterOrUndefined } from "@/utils/Common";
|
import { toFileParameterOrUndefined } from "@/utils/Common";
|
||||||
import { AuthManager } from "@/utils/AuthManager";
|
import { AuthManager } from "@/utils/AuthManager";
|
||||||
import { HubConnection, HubConnectionBuilder } from "@microsoft/signalr";
|
import { HubConnectionBuilder } from "@microsoft/signalr";
|
||||||
import { getHubProxyFactory, getReceiverRegister } from "@/TypedSignalR.Client";
|
import { getHubProxyFactory, getReceiverRegister } from "@/TypedSignalR.Client";
|
||||||
import type { ResourceInfo } from "@/APIClient";
|
import type { ResourceInfo } from "@/APIClient";
|
||||||
import type { IJtagHub } from "@/TypedSignalR.Client/server.Hubs.JtagHub";
|
|
||||||
|
|
||||||
export const useEquipments = defineStore("equipments", () => {
|
export const useEquipments = defineStore("equipments", () => {
|
||||||
// Global Stores
|
// Global Stores
|
||||||
|
@ -31,32 +30,22 @@ export const useEquipments = defineStore("equipments", () => {
|
||||||
1000,
|
1000,
|
||||||
new Error("JtagClient Mutex Timeout!"),
|
new Error("JtagClient Mutex Timeout!"),
|
||||||
);
|
);
|
||||||
const jtagHubConnection = ref<HubConnection>();
|
const jtagHubConnection = new HubConnectionBuilder()
|
||||||
const jtagHubProxy = ref<IJtagHub>();
|
.withUrl("http://localhost:5000/hubs/JtagHub")
|
||||||
|
.withAutomaticReconnect()
|
||||||
onMounted(async () => {
|
.build();
|
||||||
// 每次挂载都重新创建连接
|
const jtagHubProxy =
|
||||||
jtagHubConnection.value =
|
getHubProxyFactory("IJtagHub").createHubProxy(jtagHubConnection);
|
||||||
AuthManager.createAuthenticatedJtagHubConnection();
|
const jtagHubSubscription = getReceiverRegister("IJtagReceiver").register(
|
||||||
jtagHubProxy.value = getHubProxyFactory("IJtagHub").createHubProxy(
|
jtagHubConnection,
|
||||||
jtagHubConnection.value,
|
{
|
||||||
);
|
|
||||||
|
|
||||||
getReceiverRegister("IJtagReceiver").register(jtagHubConnection.value, {
|
|
||||||
onReceiveBoundaryScanData: async (msg) => {
|
onReceiveBoundaryScanData: async (msg) => {
|
||||||
constrainsts.batchSetConstraintStates(msg);
|
constrainsts.batchSetConstraintStates(msg);
|
||||||
},
|
},
|
||||||
});
|
},
|
||||||
await jtagHubConnection.value.start();
|
);
|
||||||
});
|
onMounted(() => {
|
||||||
|
|
||||||
onUnmounted(() => {
|
|
||||||
// 断开连接,清理资源
|
|
||||||
if (jtagHubConnection.value) {
|
|
||||||
jtagHubConnection.value.stop();
|
|
||||||
jtagHubConnection.value = undefined;
|
|
||||||
jtagHubProxy.value = undefined;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Matrix Key
|
// Matrix Key
|
||||||
|
@ -100,27 +89,13 @@ export const useEquipments = defineStore("equipments", () => {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function jtagBoundaryScanSetOnOff(enable: boolean) {
|
async function jtagBoundaryScanSetOnOff(enable: boolean) {
|
||||||
if (isUndefined(jtagHubProxy.value)) {
|
jtagHubConnection.start();
|
||||||
console.error("JtagHub Not Initialize...");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (enable) {
|
|
||||||
const ret = await jtagHubProxy.value.startBoundaryScan(
|
|
||||||
jtagBoundaryScanFreq.value,
|
|
||||||
);
|
|
||||||
if (!ret) {
|
|
||||||
console.error("Failed to start boundary scan");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const ret = await jtagHubProxy.value.stopBoundaryScan();
|
|
||||||
if (!ret) {
|
|
||||||
console.error("Failed to stop boundary scan");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
enableJtagBoundaryScan.value = enable;
|
enableJtagBoundaryScan.value = enable;
|
||||||
|
if (enable) {
|
||||||
|
jtagHubProxy.startBoundaryScan(jtagBoundaryScanFreq.value);
|
||||||
|
} else {
|
||||||
|
jtagHubProxy.stopBoundaryScan();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async function jtagUploadBitstream(bitstream: File, examId?: string): Promise<number | null> {
|
async function jtagUploadBitstream(bitstream: File, examId?: string): Promise<number | null> {
|
||||||
|
|
|
@ -16,10 +16,7 @@ import {
|
||||||
ExamClient,
|
ExamClient,
|
||||||
ResourceClient,
|
ResourceClient,
|
||||||
} from "@/APIClient";
|
} from "@/APIClient";
|
||||||
import router from "@/router";
|
|
||||||
import { HubConnectionBuilder } from "@microsoft/signalr";
|
|
||||||
import axios, { type AxiosInstance } from "axios";
|
import axios, { type AxiosInstance } from "axios";
|
||||||
import { isNull } from "lodash";
|
|
||||||
|
|
||||||
// 支持的客户端类型联合类型
|
// 支持的客户端类型联合类型
|
||||||
type SupportedClient =
|
type SupportedClient =
|
||||||
|
@ -122,7 +119,7 @@ export class AuthManager {
|
||||||
if (!token) return null;
|
if (!token) return null;
|
||||||
|
|
||||||
const instance = axios.create();
|
const instance = axios.create();
|
||||||
instance.interceptors.request.use((config) => {
|
instance.interceptors.request.use(config => {
|
||||||
config.headers = config.headers || {};
|
config.headers = config.headers || {};
|
||||||
(config.headers as any)["Authorization"] = `Bearer ${token}`;
|
(config.headers as any)["Authorization"] = `Bearer ${token}`;
|
||||||
return config;
|
return config;
|
||||||
|
@ -205,21 +202,6 @@ export class AuthManager {
|
||||||
return AuthManager.createAuthenticatedClient(ResourceClient);
|
return AuthManager.createAuthenticatedClient(ResourceClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static createAuthenticatedJtagHubConnection() {
|
|
||||||
const token = this.getToken();
|
|
||||||
if (isNull(token)) {
|
|
||||||
router.push("/login");
|
|
||||||
throw Error("Token Null!");
|
|
||||||
}
|
|
||||||
|
|
||||||
return new HubConnectionBuilder()
|
|
||||||
.withUrl("http://127.0.0.1:5000/hubs/JtagHub", {
|
|
||||||
accessTokenFactory: () => token,
|
|
||||||
})
|
|
||||||
.withAutomaticReconnect()
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
// 登录函数
|
// 登录函数
|
||||||
public static async login(
|
public static async login(
|
||||||
username: string,
|
username: string,
|
||||||
|
|
|
@ -53,6 +53,10 @@ export default defineConfig({
|
||||||
target: "http://localhost:5000",
|
target: "http://localhost:5000",
|
||||||
changeOrigin: true,
|
changeOrigin: true,
|
||||||
},
|
},
|
||||||
|
"/hubs": {
|
||||||
|
target: "http://localhost:5000",
|
||||||
|
changeOrigin: true,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
port: 5173,
|
port: 5173,
|
||||||
},
|
},
|
||||||
|
|
Loading…
Reference in New Issue