fix: 修复示波器修改后无法配置的问题;修复无法生成api的问题;feat: 新增全局控制七段数码管

This commit is contained in:
SikongJueluo 2025-08-22 02:17:30 +08:00
parent 8fbd30e69f
commit 7d3ef598de
13 changed files with 204 additions and 58 deletions

View File

@ -130,7 +130,7 @@ try
.AllowAnyHeader()
);
options.AddPolicy("SignalR", policy => policy
.WithOrigins("http://localhost:5173")
.WithOrigins([$"http://{Global.LocalHost}:5173", "http://127.0.0.1:5173"])
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials()

View File

@ -362,7 +362,7 @@ class OscilloscopeCtrl
{
// 等待WAVE_READY[0]位为1最多等待50ms5次x10ms间隔
var readyResult = await UDPClientPool.ReadAddrWithWait(
this.ep, this.taskID, OscilloscopeAddr.WAVE_READY, 0b00, 0x01, 10, 50);
this.ep, this.taskID, OscilloscopeAddr.WAVE_READY, 0b01, 0x01, 10, 50);
if (!readyResult.IsSuccessful)
{

View File

@ -1,5 +1,6 @@
using System.Net;
using DotNext;
using Tapper;
namespace Peripherals.WS2812Client;
@ -12,7 +13,8 @@ class WS2812Addr
/// <summary>
/// RGB颜色结构体包含红、绿、蓝三个颜色分量
/// </summary>
public struct RGBColor
[TranspilationSource]
public class RGBColor
{
public byte Red { get; set; }
public byte Green { get; set; }

View File

@ -156,6 +156,7 @@ const [useProvideOscilloscope, useOscilloscopeState] = createInjectionState(
try {
const proxy = getHubProxy();
// console.log("Applying configuration", config);
const success = await proxy.initialize(config);
if (success) {

View File

@ -66,7 +66,7 @@
</div>
<div class="divider"></div>
<h1 class="font-bold text-center text-2xl">外设</h1>
<div class="flex flex-row justify-center">
<div class="flex flex-row justify-between columns-2">
<div class="flex flex-row">
<input
type="checkbox"
@ -76,6 +76,15 @@
/>
<p class="mx-2">启用矩阵键盘</p>
</div>
<div class="flex flex-row">
<input
type="checkbox"
class="checkbox"
:checked="eqps.enableSevenSegmentDisplay"
@change="handleSevenSegmentDisplayCheckboxChange"
/>
<p class="mx-2">启用数码管</p>
</div>
</div>
</div>
</template>
@ -146,6 +155,15 @@ async function handleMatrixkeyCheckboxChange(event: Event) {
}
}
async function handleSevenSegmentDisplayCheckboxChange(event: Event) {
const target = event.target as HTMLInputElement;
if (target.checked) {
await eqps.sevenSegmentDisplaySetOnOff(true);
} else {
await eqps.sevenSegmentDisplaySetOnOff(false);
}
}
async function toggleJtagBoundaryScan() {
eqps.jtagBoundaryScanSetOnOff(!eqps.enableJtagBoundaryScan);
}

View File

@ -41,7 +41,7 @@
<!-- 引脚仅在非数字孪生模式下显示 -->
<div
v-if="!props.enableDigitalTwin"
v-if="!eqps.enableSevenSegmentDisplay"
v-for="pin in props.pins"
:key="pin.pinId"
:style="{
@ -74,6 +74,12 @@ import { ref, computed, watch, onMounted, onUnmounted } from "vue";
import { useConstraintsStore } from "../../stores/constraints";
import Pin from "./Pin.vue";
import { useEquipments } from "@/stores/equipments";
import { watchEffect } from "vue";
import { useRequiredInjection } from "@/utils/Common";
import { useComponentManager } from "../LabCanvas";
const eqps = useEquipments();
const componentManger = useRequiredInjection(useComponentManager);
// ============================================================================
// Linusbyte
@ -82,7 +88,7 @@ import { useEquipments } from "@/stores/equipments";
interface Props {
size?: number;
color?: string;
enableDigitalTwin?: boolean;
// enableDigitalTwin?: boolean;
digitalTwinNum?: number;
// afterglowDuration?: number;
cathodeType?: "common" | "anode";
@ -97,7 +103,7 @@ interface Props {
const props = withDefaults(defineProps<Props>(), {
size: 1,
color: "red",
enableDigitalTwin: false,
// enableDigitalTwin: false,
digitalTwinNum: 1,
afterglowDuration: 500,
cathodeType: "common",
@ -158,7 +164,7 @@ function isBitSet(byte: number, bit: number): boolean {
}
function isSegmentActive(segmentId: keyof typeof SEGMENT_BITS): boolean {
if (props.enableDigitalTwin) {
if (eqps.enableSevenSegmentDisplay) {
// byte
const bit = SEGMENT_BITS[segmentId];
return (
@ -174,18 +180,16 @@ function isSegmentActive(segmentId: keyof typeof SEGMENT_BITS): boolean {
// SignalR
// ============================================================================
const eqps = useEquipments();
async function initDigitalTwin() {
if (
!props.enableDigitalTwin ||
!eqps.enableSevenSegmentDisplay ||
props.digitalTwinNum <= 0 ||
props.digitalTwinNum > 31
)
return;
try {
eqps.sevenSegmentDisplaySetOnOff(props.enableDigitalTwin);
eqps.sevenSegmentDisplaySetOnOff(eqps.enableSevenSegmentDisplay);
console.log(
`Digital twin initialized for address: ${props.digitalTwinNum}`,
@ -205,7 +209,9 @@ watch(
)
return;
handleDigitalTwinData(eqps.sevenSegmentDisplayData[props.digitalTwinNum - 1]);
handleDigitalTwinData(
eqps.sevenSegmentDisplayData[props.digitalTwinNum - 1],
);
},
);
@ -265,7 +271,7 @@ const { getConstraintState, onConstraintStateChange } = useConstraintsStore();
let constraintUnsubscribe: (() => void) | null = null;
function updateConstraintStates() {
if (props.enableDigitalTwin) return; //
if (eqps.enableSevenSegmentDisplay) return; //
// COM
const comPin = props.pins.find((p) => p.pinId === "COM");
@ -328,7 +334,7 @@ const pinRefs = ref<Record<string, any>>({});
// ============================================================================
onMounted(async () => {
if (props.enableDigitalTwin) {
if (eqps.enableSevenSegmentDisplay) {
await initDigitalTwin();
} else {
constraintUnsubscribe = onConstraintStateChange(updateConstraintStates);
@ -349,25 +355,24 @@ onUnmounted(() => {
});
//
watch(
() => [props.enableDigitalTwin],
async () => {
//
cleanupDigitalTwin();
if (constraintUnsubscribe) {
constraintUnsubscribe();
constraintUnsubscribe = null;
}
// watch(
// () => [eqps.enableSevenSegmentDisplay],
// async () => {
// //
// if (constraintUnsubscribe) {
// constraintUnsubscribe();
// constraintUnsubscribe = null;
// }
//
if (props.enableDigitalTwin) {
await initDigitalTwin();
} else {
constraintUnsubscribe = onConstraintStateChange(updateConstraintStates);
updateConstraintStates();
}
},
);
// //
// if (eqps.enableSevenSegmentDisplay) {
// await initDigitalTwin();
// } else {
// constraintUnsubscribe = onConstraintStateChange(updateConstraintStates);
// updateConstraintStates();
// }
// },
// );
</script>
<style scoped>
@ -393,7 +398,7 @@ export function getDefaultProps() {
return {
size: 1,
color: "red",
enableDigitalTwin: false,
// enableDigitalTwin: false,
digitalTwinNum: 1,
// afterglowDuration: 500,
cathodeType: "common",

View File

@ -313,8 +313,10 @@ export const useEquipments = defineStore("equipments", () => {
if (enable) {
await sevenSegmentDisplayHubProxy.value.startScan();
enableSevenSegmentDisplay.value = true;
} else {
await sevenSegmentDisplayHubProxy.value.stopScan();
enableSevenSegmentDisplay.value = false;
}
}

View File

@ -0,0 +1,8 @@
/* THIS (.ts) FILE IS GENERATED BY Tapper */
/* eslint-disable */
/* tslint:disable */
/** Transpiled from Database.ResourceTypes */
export type ResourceTypes = {
}

View File

@ -0,0 +1,14 @@
/* THIS (.ts) FILE IS GENERATED BY Tapper */
/* eslint-disable */
/* tslint:disable */
/** Transpiled from Peripherals.WS2812Client.RGBColor */
export type RGBColor = {
/** Transpiled from byte */
red: number;
/** Transpiled from byte */
green: number;
/** Transpiled from byte */
blue: number;
}

View File

@ -3,9 +3,10 @@
/* tslint:disable */
// @ts-nocheck
import type { HubConnection, IStreamResult, Subject } from '@microsoft/signalr';
import type { IDigitalTubesHub, IJtagHub, IOscilloscopeHub, IProgressHub, IRotaryEncoderHub, IDigitalTubesReceiver, IJtagReceiver, IOscilloscopeReceiver, IProgressReceiver, IRotaryEncoderReceiver } from './server.Hubs';
import type { IDigitalTubesHub, IJtagHub, IOscilloscopeHub, IProgressHub, IRotaryEncoderHub, IWS2812Hub, IDigitalTubesReceiver, IJtagReceiver, IOscilloscopeReceiver, IProgressReceiver, IRotaryEncoderReceiver, IWS2812Receiver } from './server.Hubs';
import type { DigitalTubeTaskStatus, OscilloscopeFullConfig, OscilloscopeDataResponse, ProgressInfo } from '../server.Hubs';
import type { RotaryEncoderDirection } from '../Peripherals.RotaryEncoderClient';
import type { RGBColor } from '../Peripherals.WS2812Client';
// components
@ -49,6 +50,7 @@ export type HubProxyFactoryProvider = {
(hubType: "IOscilloscopeHub"): HubProxyFactory<IOscilloscopeHub>;
(hubType: "IProgressHub"): HubProxyFactory<IProgressHub>;
(hubType: "IRotaryEncoderHub"): HubProxyFactory<IRotaryEncoderHub>;
(hubType: "IWS2812Hub"): HubProxyFactory<IWS2812Hub>;
}
export const getHubProxyFactory = ((hubType: string) => {
@ -67,6 +69,9 @@ export const getHubProxyFactory = ((hubType: string) => {
if(hubType === "IRotaryEncoderHub") {
return IRotaryEncoderHub_HubProxyFactory.Instance;
}
if(hubType === "IWS2812Hub") {
return IWS2812Hub_HubProxyFactory.Instance;
}
}) as HubProxyFactoryProvider;
export type ReceiverRegisterProvider = {
@ -75,6 +80,7 @@ export type ReceiverRegisterProvider = {
(receiverType: "IOscilloscopeReceiver"): ReceiverRegister<IOscilloscopeReceiver>;
(receiverType: "IProgressReceiver"): ReceiverRegister<IProgressReceiver>;
(receiverType: "IRotaryEncoderReceiver"): ReceiverRegister<IRotaryEncoderReceiver>;
(receiverType: "IWS2812Receiver"): ReceiverRegister<IWS2812Receiver>;
}
export const getReceiverRegister = ((receiverType: string) => {
@ -93,6 +99,9 @@ export const getReceiverRegister = ((receiverType: string) => {
if(receiverType === "IRotaryEncoderReceiver") {
return IRotaryEncoderReceiver_Binder.Instance;
}
if(receiverType === "IWS2812Receiver") {
return IWS2812Receiver_Binder.Instance;
}
}) as ReceiverRegisterProvider;
// HubProxy
@ -270,6 +279,31 @@ class IRotaryEncoderHub_HubProxy implements IRotaryEncoderHub {
}
}
class IWS2812Hub_HubProxyFactory implements HubProxyFactory<IWS2812Hub> {
public static Instance = new IWS2812Hub_HubProxyFactory();
private constructor() {
}
public readonly createHubProxy = (connection: HubConnection): IWS2812Hub => {
return new IWS2812Hub_HubProxy(connection);
}
}
class IWS2812Hub_HubProxy implements IWS2812Hub {
public constructor(private connection: HubConnection) {
}
public readonly getAllLedColors = async (): Promise<RGBColor[]> => {
return await this.connection.invoke("GetAllLedColors");
}
public readonly getLedColor = async (ledIndex: number): Promise<RGBColor> => {
return await this.connection.invoke("GetLedColor", ledIndex);
}
}
// Receiver
@ -378,3 +412,24 @@ class IRotaryEncoderReceiver_Binder implements ReceiverRegister<IRotaryEncoderRe
}
}
class IWS2812Receiver_Binder implements ReceiverRegister<IWS2812Receiver> {
public static Instance = new IWS2812Receiver_Binder();
private constructor() {
}
public readonly register = (connection: HubConnection, receiver: IWS2812Receiver): Disposable => {
const __onReceive = (...args: [RGBColor[]]) => receiver.onReceive(...args);
connection.on("OnReceive", __onReceive);
const methodList: ReceiverMethod[] = [
{ methodName: "OnReceive", method: __onReceive }
]
return new ReceiverMethodSubscription(connection, methodList);
}
}

View File

@ -5,6 +5,7 @@
import type { IStreamResult, Subject } from '@microsoft/signalr';
import type { DigitalTubeTaskStatus, OscilloscopeFullConfig, OscilloscopeDataResponse, ProgressInfo } from '../server.Hubs';
import type { RotaryEncoderDirection } from '../Peripherals.RotaryEncoderClient';
import type { RGBColor } from '../Peripherals.WS2812Client';
export type IDigitalTubesHub = {
/**
@ -126,6 +127,18 @@ export type IRotaryEncoderHub = {
disableCycleRotateEncoder(): Promise<boolean>;
}
export type IWS2812Hub = {
/**
* @returns Transpiled from System.Threading.Tasks.Task<Peripherals.WS2812Client.RGBColor[]?>
*/
getAllLedColors(): Promise<RGBColor[]>;
/**
* @param ledIndex Transpiled from int
* @returns Transpiled from System.Threading.Tasks.Task<Peripherals.WS2812Client.RGBColor?>
*/
getLedColor(ledIndex: number): Promise<RGBColor>;
}
export type IDigitalTubesReceiver = {
/**
* @param data Transpiled from byte[]
@ -167,3 +180,11 @@ export type IRotaryEncoderReceiver = {
onReceiveRotate(num: number, direction: RotaryEncoderDirection): Promise<void>;
}
export type IWS2812Receiver = {
/**
* @param data Transpiled from Peripherals.WS2812Client.RGBColor[]
* @returns Transpiled from System.Threading.Tasks.Task
*/
onReceive(data: RGBColor[]): Promise<void>;
}

View File

@ -60,3 +60,9 @@ export type ProgressInfo = {
errorMessage: string;
}
/** Transpiled from server.Hubs.WS2812TaskStatus */
export type WS2812TaskStatus = {
/** Transpiled from bool */
isRunning: boolean;
}

View File

@ -141,16 +141,14 @@
<div class="form-control">
<label class="label">
<span class="label-text font-medium">触发电平</span>
<span class="label-text-alt">{{
osc.config.triggerLevel
}}</span>
<span class="label-text-alt">{{ triggerLevel }}</span>
</label>
<input
type="range"
min="0"
max="255"
step="1"
v-model="osc.config.triggerLevel"
v-model="triggerLevel"
class="range range-primary [--range-bg:#2b7fff]"
/>
<div
@ -181,16 +179,14 @@
<div class="form-control">
<label class="label">
<span class="label-text font-medium">水平偏移</span>
<span class="label-text-alt">{{
osc.config.horizontalShift
}}</span>
<span class="label-text-alt">{{ horizontalShift }}</span>
</label>
<input
type="range"
min="0"
max="1000"
step="1"
v-model="osc.config.horizontalShift"
v-model="horizontalShift"
class="range range-secondary [--range-bg:#c27aff]"
/>
</div>
@ -198,16 +194,14 @@
<div class="form-control">
<label class="label">
<span class="label-text font-medium">抽取率</span>
<span class="label-text-alt"
>{{ osc.config.decimationRate }}%</span
>
<span class="label-text-alt">{{ decimationRate }}%</span>
</label>
<input
type="range"
min="0"
max="100"
step="1"
v-model="osc.config.decimationRate"
v-model="decimationRate"
class="range range-accent [--range-bg:#fb64b6]"
/>
</div>
@ -215,16 +209,14 @@
<div class="form-control">
<label class="label">
<span class="label-text font-medium">刷新频率</span>
<span class="label-text-alt"
>{{ osc.config.captureFrequency }}Hz</span
>
<span class="label-text-alt">{{ captureFrequency }}Hz</span>
</label>
<input
type="range"
min="1"
max="1000"
step="1"
v-model="osc.config.captureFrequency"
v-model="captureFrequency"
class="range range-info [--range-bg:#51a2ff]"
/>
</div>
@ -334,6 +326,7 @@ import { useOscilloscopeState } from "@/components/Oscilloscope/OscilloscopeMana
import { useRequiredInjection } from "@/utils/Common";
import { ref, computed } from "vue";
import { watchEffect } from "vue";
import { toNumber } from "lodash";
// 使
const equipments = useEquipments();
@ -341,6 +334,23 @@ const equipments = useEquipments();
//
const osc = useRequiredInjection(useOscilloscopeState);
const decimationRate = ref(osc.config.decimationRate);
watchEffect(() => {
osc.config.decimationRate = toNumber(decimationRate.value);
});
const captureFrequency = ref(osc.config.captureFrequency);
watchEffect(() => {
osc.config.captureFrequency = toNumber(captureFrequency.value);
});
const triggerLevel = ref(osc.config.triggerLevel);
watchEffect(() => {
osc.config.triggerLevel = toNumber(triggerLevel.value);
});
const horizontalShift = ref(osc.config.horizontalShift);
watchEffect(() => {
osc.config.horizontalShift = toNumber(horizontalShift.value);
});
//
const hasWaveformData = computed(() => {
const data = osc.oscData.value;
@ -358,6 +368,10 @@ function toggleCapture() {
function resetConfiguration() {
osc.resetConfiguration();
horizontalShift.value = osc.config.horizontalShift;
triggerLevel.value = osc.config.triggerLevel;
captureFrequency.value = osc.config.captureFrequency;
decimationRate.value = osc.config.decimationRate;
}
</script>