@@ -5,7 +5,7 @@ import { useMeasurement } from '../../MeasurementContext'
55// - Before rendering, fetch GET /instruments/DMM/{device_id} to obtain features (modes list)
66// - Settings: full-width dropdown to select mode; hover tooltip shows POST endpoint template
77// - Readings: placeholder big-number display U[V] with 5-digit readonly value
8- export function GenericDMM ( { channelPath } : { channelPath ?: string } ) {
8+ export function GenericDMM ( { channelPath, registry } : { channelPath ?: string , registry ?: any } ) {
99 const apiBase = `${ window . location . protocol } //${ window . location . hostname } :57666`
1010 const { registerSource } = useMeasurement ( )
1111
@@ -15,20 +15,66 @@ export function GenericDMM({ channelPath }: { channelPath?: string }) {
1515 const [ modes , setModes ] = useState < string [ ] > ( [ ] )
1616 const [ mode , setMode ] = useState < string > ( '' )
1717 const [ busy , setBusy ] = useState ( false )
18+ const [ modesData , setModesData ] = useState < Record < string , any > > ( { } )
19+ const [ currentSymbol , setCurrentSymbol ] = useState ( 'U' )
20+ const [ currentUnit , setCurrentUnit ] = useState ( 'V' )
21+ const [ currentNote , setCurrentNote ] = useState < string | undefined > ( undefined )
22+
23+ // Extract measurement value and prefix from registry
24+ const { measurementValue, unitPrefix } = useMemo ( ( ) => {
25+ if ( ! registry || ! deviceId || ! klass || ! channel ) {
26+ return { measurementValue : '00000' , unitPrefix : '' }
27+ }
28+
29+ const statusKey = `status_ch${ channel } `
30+ const channelData = registry [ deviceId ] ?. [ klass ] ?. [ statusKey ]
31+
32+ if ( ! channelData ) {
33+ return { measurementValue : '00000' , unitPrefix : '' }
34+ }
35+
36+ const rawValue = String ( channelData . measurement1_num || '0' )
37+ // Ensure 5 numerical digits (excluding decimal point and sign)
38+ const isNegative = rawValue . startsWith ( '-' )
39+ const absoluteValue = isNegative ? rawValue . slice ( 1 ) : rawValue
40+ const parts = absoluteValue . split ( '.' )
41+
42+ // Count total digits needed (excluding decimal point)
43+ const totalDigits = parts . join ( '' ) . length
44+ const zerosNeeded = Math . max ( 0 , 5 - totalDigits )
45+
46+ // Add leading zeros and reconstruct with decimal point if present
47+ const paddedInteger = '0' . repeat ( zerosNeeded ) + parts [ 0 ]
48+ const formattedValue = parts . length > 1 ? `${ paddedInteger } .${ parts [ 1 ] } ` : paddedInteger
49+ const value = isNegative ? `-${ formattedValue } ` : formattedValue
50+ const prefix = channelData . measurement1_symbol || ''
51+
52+ return { measurementValue : value , unitPrefix : prefix }
53+ } , [ registry , deviceId , klass , channel ] )
54+
55+ // Update symbol and unit when mode changes
56+ useEffect ( ( ) => {
57+ if ( mode && modesData [ mode ] ) {
58+ const modeInfo = modesData [ mode ]
59+ setCurrentSymbol ( modeInfo . symbol || 'U' )
60+ setCurrentUnit ( modeInfo . unit || 'V' )
61+ setCurrentNote ( modeInfo . note )
62+ }
63+ } , [ mode , modesData ] )
1864
1965 // Register measurement sources
2066 useEffect ( ( ) => {
2167 if ( ! channelPath || ! deviceId ) return
2268
2369 registerSource ( {
24- id : `${ deviceId } -${ channel } -U ` ,
70+ id : `${ deviceId } -${ channel } -${ currentSymbol } ` ,
2571 deviceId,
2672 channelPath,
2773 parameter : 'voltage' ,
28- label : `${ deviceId } Ch${ channel } U ` ,
29- unit : 'V'
74+ label : `${ deviceId } Ch${ channel } ${ currentSymbol } ` ,
75+ unit : currentUnit
3076 } )
31- } , [ channelPath , deviceId , channel , registerSource ] )
77+ } , [ channelPath , deviceId , channel , currentSymbol , currentUnit , registerSource ] )
3278
3379 // Fetch class features (modes) before rendering content
3480 useEffect ( ( ) => {
@@ -40,15 +86,36 @@ export function GenericDMM({ channelPath }: { channelPath?: string }) {
4086 if ( ! r . ok ) return
4187 const j = await r . json ( ) . catch ( ( ) => ( { } as any ) )
4288 if ( ! cancelled ) {
43- const mm = Array . isArray ( j ?. modes ) ? ( j . modes as any [ ] ) . map ( String ) : [ ]
89+ let mm : string [ ] = [ ]
90+ let mData : Record < string , any > = { }
91+
92+ if ( Array . isArray ( j ?. modes ) ) {
93+ // Old format: array of mode names
94+ mm = ( j . modes as any [ ] ) . map ( String )
95+ } else if ( j ?. modes && typeof j . modes === 'object' ) {
96+ // New format: object with mode names as keys and details as values
97+ mm = Object . keys ( j . modes )
98+ mData = j . modes
99+ }
100+
44101 setModes ( mm )
45- if ( ! mode && mm . length ) setMode ( String ( mm [ 0 ] ) )
102+ setModesData ( mData )
103+ if ( ! mode && mm . length ) {
104+ const firstMode = String ( mm [ 0 ] )
105+ setMode ( firstMode )
106+ // Set initial symbol and unit from first mode
107+ if ( mData [ firstMode ] ) {
108+ setCurrentSymbol ( mData [ firstMode ] . symbol || 'U' )
109+ setCurrentUnit ( mData [ firstMode ] . unit || 'V' )
110+ setCurrentNote ( mData [ firstMode ] . note )
111+ }
112+ }
46113 }
47114 } catch { }
48115 }
49116 loadFeatures ( )
50117 return ( ) => { cancelled = true }
51- } , [ apiBase , deviceId , klass ] )
118+ } , [ apiBase , deviceId , klass , mode ] )
52119
53120 const endpointTemplate = useMemo ( ( ) => {
54121 const k = klass || 'DMM'
@@ -101,7 +168,13 @@ export function GenericDMM({ channelPath }: { channelPath?: string }) {
101168 </ div >
102169 < div className = "psu-section" >
103170 < div className = "psu-section-title" > Readings</ div >
104- < ReadonlyBigNumber kind = "U" label = { < Label symbol = "U" unit = "V" /> } value = { "00000" } channelPath = { channelPath } parameter = "voltage" />
171+ < ReadonlyBigNumber
172+ kind = { currentSymbol as 'U' | 'I' | 'P' }
173+ label = { < Label symbol = { currentSymbol } unit = { `${ unitPrefix } ${ currentUnit } ` } note = { currentNote } /> }
174+ value = { measurementValue }
175+ channelPath = { channelPath }
176+ parameter = "voltage"
177+ />
105178 </ div >
106179 < hr className = "sep" />
107180 </ div >
@@ -291,10 +364,14 @@ function ReadonlyBigNumber({ kind, label, value, channelPath, parameter }: { kin
291364 )
292365}
293366
294- function Label ( { symbol, unit } : { symbol : string , unit : string } ) {
367+ function Label ( { symbol, unit, note } : { symbol : string , unit : string , note ? : string } ) {
295368 return (
296369 < >
297- < span className = "psu-symbol" > { symbol } </ span > < span className = "psu-unit" > [{ unit } ]</ span >
370+ < span className = "psu-symbol" style = { { fontSize : '24px' } } > { symbol } </ span >
371+ < span className = "psu-unit" style = { { fontSize : '20px' } } >
372+ [{ unit } ]
373+ { note && < span style = { { fontSize : '14px' , marginLeft : '4px' , color : 'var(--text-2)' } } > { note } </ span > }
374+ </ span >
298375 </ >
299376 )
300377}
0 commit comments