fix: 修复示波器修改后无法配置的问题;修复无法生成api的问题;feat: 新增全局控制七段数码管
This commit is contained in:
		@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -362,7 +362,7 @@ class OscilloscopeCtrl
 | 
			
		||||
    {
 | 
			
		||||
        // 等待WAVE_READY[0]位为1,最多等待50ms(5次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)
 | 
			
		||||
        {
 | 
			
		||||
 
 | 
			
		||||
@@ -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; }
 | 
			
		||||
@@ -84,13 +86,13 @@ public class WS2812Client
 | 
			
		||||
    {
 | 
			
		||||
        if (ledIndex < 0 || ledIndex >= WS2812Addr.LED_COUNT)
 | 
			
		||||
        {
 | 
			
		||||
            return new(new ArgumentOutOfRangeException(nameof(ledIndex), 
 | 
			
		||||
            return new(new ArgumentOutOfRangeException(nameof(ledIndex),
 | 
			
		||||
                $"LED index must be between 0 and {WS2812Addr.LED_COUNT - 1}"));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (MsgBus.IsRunning)
 | 
			
		||||
            MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        else 
 | 
			
		||||
        else
 | 
			
		||||
            return new(new Exception("Message Bus not work!"));
 | 
			
		||||
 | 
			
		||||
        var addr = WS2812Addr.BASE + (UInt32)(ledIndex * 4); // 每个地址32位,步长为4字节
 | 
			
		||||
@@ -123,14 +125,14 @@ public class WS2812Client
 | 
			
		||||
    {
 | 
			
		||||
        if (MsgBus.IsRunning)
 | 
			
		||||
            MsgBus.UDPServer.ClearUDPData(this.address, this.taskID);
 | 
			
		||||
        else 
 | 
			
		||||
        else
 | 
			
		||||
            return new(new Exception("Message Bus not work!"));
 | 
			
		||||
 | 
			
		||||
        try
 | 
			
		||||
        {
 | 
			
		||||
            // 一次性读取所有LED数据,每个LED占用4字节,总共128*4=512字节
 | 
			
		||||
            var ret = await UDPClientPool.ReadAddr4Bytes(this.ep, this.taskID, WS2812Addr.BASE, WS2812Addr.LED_COUNT, this.timeout);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            if (!ret.IsSuccessful)
 | 
			
		||||
            {
 | 
			
		||||
                logger.Error($"Get all LED colors failed: {ret.Error}");
 | 
			
		||||
@@ -139,7 +141,7 @@ public class WS2812Client
 | 
			
		||||
 | 
			
		||||
            var data = ret.Value;
 | 
			
		||||
            var expectedLength = WS2812Addr.LED_COUNT * 4; // 128 * 4 = 512 bytes
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            if (data.Length < expectedLength)
 | 
			
		||||
            {
 | 
			
		||||
                var error = new Exception($"Invalid data length: expected {expectedLength} bytes, got {data.Length}");
 | 
			
		||||
@@ -148,7 +150,7 @@ public class WS2812Client
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var colors = new RGBColor[WS2812Addr.LED_COUNT];
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            for (int i = 0; i < WS2812Addr.LED_COUNT; i++)
 | 
			
		||||
            {
 | 
			
		||||
                var offset = i * 4;
 | 
			
		||||
@@ -156,7 +158,7 @@ public class WS2812Client
 | 
			
		||||
                var colorData = BitConverter.ToUInt32(data, offset);
 | 
			
		||||
                colors[i] = RGBColor.FromUInt32(colorData);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            return new(colors);
 | 
			
		||||
        }
 | 
			
		||||
        catch (Exception ex)
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 | 
			
		||||
// ============================================================================
 | 
			
		||||
// Linus式极简数据结构:一个byte解决一切
 | 
			
		||||
@@ -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",
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										8
									
								
								src/utils/signalR/Database.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/utils/signalR/Database.ts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
			
		||||
/* THIS (.ts) FILE IS GENERATED BY Tapper */
 | 
			
		||||
/* eslint-disable */
 | 
			
		||||
/* tslint:disable */
 | 
			
		||||
 | 
			
		||||
/** Transpiled from Database.ResourceTypes */
 | 
			
		||||
export type ResourceTypes = {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								src/utils/signalR/Peripherals.WS2812Client.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/utils/signalR/Peripherals.WS2812Client.ts
									
									
									
									
									
										Normal 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -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);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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>;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -60,3 +60,9 @@ export type ProgressInfo = {
 | 
			
		||||
    errorMessage: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Transpiled from server.Hubs.WS2812TaskStatus */
 | 
			
		||||
export type WS2812TaskStatus = {
 | 
			
		||||
    /** Transpiled from bool */
 | 
			
		||||
    isRunning: boolean;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user