From 773af4f2c6271e4f441c13fe99780ba393976a35 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2024 08:31:09 -0800 Subject: [PATCH 1/9] Power and Thermal Specification for RPE - Front end (updated) --- src/components/Tables/PowerSummaryTable.js | 346 ++++++++++++++++----- src/components/style/PowerSummaryTable.css | 187 ++++++++++- 2 files changed, 446 insertions(+), 87 deletions(-) diff --git a/src/components/Tables/PowerSummaryTable.js b/src/components/Tables/PowerSummaryTable.js index a25d9cbb..8f93f170 100644 --- a/src/components/Tables/PowerSummaryTable.js +++ b/src/components/Tables/PowerSummaryTable.js @@ -1,11 +1,11 @@ -import React from 'react'; +import React, { useState, useEffect, useRef } from 'react'; import PropTypes from 'prop-types'; import { IoMdCloseCircleOutline } from 'react-icons/io'; import { Tooltip } from 'antd'; import { PowerCell } from './TableCells'; import { fixed, color } from '../../utils/common'; import { State } from '../ComponentsLib'; - +import { api, PATCH, GET, deviceInfo } from '../../utils/serverAPI'; import '../style/PowerSummaryTable.css'; function PowerSummaryTableToolTip({ title, statusColor }) { @@ -17,91 +17,290 @@ function PowerSummaryTableToolTip({ title, statusColor }) { ); } -function PowerSummaryTable({ - title, data, total, percent, -}) { - function getErrors(messages) { - if (messages === undefined) return []; - const errors = messages.filter((item) => item.filter((inner) => inner.type === 'error').length > 0); - return errors; - } - function getWarning(messages) { - if (messages === undefined) return []; - const warnings = messages.filter((item) => item.filter((inner) => inner.type === 'warn').length > 0); - return warnings; - } - function buildMessage(messages) { - return messages.reduce((sum, item, currentIndex) => { - item.forEach((i, index) => sum.push( - // eslint-disable-next-line react/no-array-index-key - - {i.text} -
-
, - )); - return sum; - }, []); - } - function message(messages) { - const errors = getErrors(messages); - if (errors.length > 0) { - return buildMessage(errors); + +function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId = 'MPW1' }) { + const [thermalData, setThermalData] = useState({ + ambientTypical: 25, + ambientWorstCase: 50, + thetaJa: 10, + }); + + const [powerData, setPowerData] = useState({ + powerBudget: 1.0, + fpgaScaling: 25, + pcScaling: 25, + }); + + const ambientTypicalRef = useRef(null); + const ambientWorstCaseRef = useRef(null); + const thetaJaRef = useRef(null); + const powerBudgetRef = useRef(null); + const fpgaScalingRef = useRef(null); + const pcScalingRef = useRef(null); + + useEffect(() => { + const fetchData = async () => { + try { + // Update the API call to match the correct endpoint + GET(deviceInfo(deviceId), (result) => { + if (result && result.specification) { + const { specification } = result; + + // Process thermal data + setThermalData({ + ambientTypical: specification.thermal?.ambient?.typical || 25, + ambientWorstCase: specification.thermal?.ambient?.worstcase || 50, + thetaJa: specification.thermal?.theta_ja || 10, + }); + + // Process power data + setPowerData({ + powerBudget: specification.power?.budget || 1.0, + fpgaScaling: (specification.power?.typical_dynamic_scaling?.fpga_complex || 0) * 100, + pcScaling: (specification.power?.typical_dynamic_scaling?.processing_complex || 0) * 100, + }); + } + }); + } catch (error) { + console.error('Error fetching data:', error); + } + }; + + fetchData(); // Trigger the fetch function + }, [deviceId]); // Re-run effect when deviceId changes + + const updateBackend = async (deviceId, thermalData, powerData) => { + const updatedData = { + specification: { + thermal: { + ambient: { + typical: thermalData.ambientTypical || 0, + worsecase: thermalData.ambientWorstCase || 0, // Note: This matches the schema + }, + theta_ja: thermalData.thetaJa || 0, + }, + power: { + budget: powerData.powerBudget || 0, + typical_dynamic_scaling: { + fpga_complex: powerData.fpgaScaling || 0, + processing_complex: powerData.pcScaling || 0, + }, + }, + }, + }; + + console.log('PATCH Payload:', JSON.stringify(updatedData, null, 2)); + + try { + const response = await fetch(`http://127.0.0.1:5000/devices/${deviceId}`, { + method: 'PATCH', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(updatedData), + }); + + if (!response.ok) { + throw new Error(`PATCH request failed: ${response.status} ${response.statusText}`); + } + + const result = await response.json(); + console.log('PATCH Response:', result); + } catch (error) { + console.error('Error during PATCH request:', error); + } + }; + + const handleFieldUpdate = (field, value) => { + const updatedThermalData = { ...thermalData }; + const updatedPowerData = { ...powerData }; + + if (field in thermalData) { + updatedThermalData[field] = isNaN(parseFloat(value)) ? 0 : parseFloat(value); + } else { + updatedPowerData[field] = isNaN(parseFloat(value)) ? 0 : parseFloat(value); + } + + setThermalData(updatedThermalData); + setPowerData(updatedPowerData); + + updateBackend(deviceId, updatedThermalData, updatedPowerData); + }; + + const enforceNumericInput = (e) => { + const value = e.target.value; + const valid = /^-?\d*\.?\d*%?$/.test(value); + if (!valid) { + e.target.value = value.slice(0, -1); } - const warnings = getWarning(messages); - if (warnings.length > 0) { - return buildMessage(warnings); + }; + + const handleKeyDown = (e, nextFieldRef) => { + if (e.key === 'Enter' && nextFieldRef && nextFieldRef.current) { + nextFieldRef.current.focus(); } - return ''; - } - - function isError(messages) { return getErrors(messages).length > 0; } - function isWarning(messages) { return getWarning(messages).length > 0; } - function statusColor(messages) { - return color(isError(messages), isWarning(messages)); - } + }; + + const getErrors = (messages) => + messages?.filter((item) => item.some((inner) => inner.type === 'error')) || []; + const getWarnings = (messages) => + messages?.filter((item) => item.some((inner) => inner.type === 'warn')) || []; + + const buildMessage = (messages) => + messages.reduce((acc, item, currentIndex) => { + item.forEach((i, index) => acc.push({i.text}
)); + return acc; + }, []); + + const message = (messages) => { + const errors = getErrors(messages); + return errors.length > 0 ? buildMessage(errors) : buildMessage(getWarnings(messages)); + }; + + const statusColor = (messages) => + color(getErrors(messages).length > 0, getWarnings(messages).length > 0); + return (
-
{title}
+ {title === 'FPGA Complex and Core Power' && ( +
+
Thermal Specification
+ + + + + + + + + + + + + + + + + + +
TypicalWorst-Case
Ambient + handleFieldUpdate('ambientTypical', e.target.value)} + onInput={enforceNumericInput} + ref={ambientTypicalRef} + onKeyDown={(e) => handleKeyDown(e, ambientWorstCaseRef)} + />{' '} + °C + + handleFieldUpdate('ambientWorstCase', e.target.value)} + onInput={enforceNumericInput} + ref={ambientWorstCaseRef} + onKeyDown={(e) => handleKeyDown(e, thetaJaRef)} + />{' '} + °C +
+ ΘJA: + handleFieldUpdate('thetaJa', e.target.value)} + onInput={enforceNumericInput} + ref={thetaJaRef} + onKeyDown={(e) => handleKeyDown(e, powerBudgetRef)} + />{' '} + °C/W +
+ +
Power Specification
+ + + + + + + + + + + + +
Power Budget + handleFieldUpdate('powerBudget', e.target.value)} + onInput={enforceNumericInput} + ref={powerBudgetRef} + onKeyDown={(e) => handleKeyDown(e, fpgaScalingRef)} + />{' '} + W +
Typical Dynamic Scaling % + FPGA: + handleFieldUpdate('fpgaScaling', e.target.value)} + onInput={enforceNumericInput} + ref={fpgaScalingRef} + onKeyDown={(e) => handleKeyDown(e, pcScalingRef)} + />{' '} + % + + PC: + handleFieldUpdate('pcScaling', e.target.value)} + onInput={enforceNumericInput} + ref={pcScalingRef} + />{' '} + % +
+
+ )} + +
{title || 'FPGA Complex and Core Power'}
- { - data.map((item, index) => ( - // eslint-disable-next-line react/no-array-index-key - - - - - - - - )) - } + {data.map((item, index) => ( + + + + + + + + ))}
{item.text} - {`${fixed(item.percent, 0)} %`} - - { - (isError(item.messages) || isWarning(item.messages)) && ( - - ) - } -
+ + {item.text || 'N/A'} + {`${fixed(item.percent || 0, 0)} %`} + + {(getErrors(item.messages).length > 0 || getWarnings(item.messages).length > 0) && ( + + )} +
+
- - + +
Total - {` ${fixed(total)} W`} + {` ${fixed(total || 0)} W`}
@@ -110,11 +309,10 @@ function PowerSummaryTable({ PowerSummaryTable.propTypes = { title: PropTypes.string.isRequired, - data: PropTypes.oneOfType([ - PropTypes.array, - ]).isRequired, + data: PropTypes.array.isRequired, total: PropTypes.number.isRequired, percent: PropTypes.number.isRequired, + deviceId: PropTypes.string.isRequired, }; export default PowerSummaryTable; diff --git a/src/components/style/PowerSummaryTable.css b/src/components/style/PowerSummaryTable.css index c98c0c5e..88a4881c 100644 --- a/src/components/style/PowerSummaryTable.css +++ b/src/components/style/PowerSummaryTable.css @@ -1,36 +1,180 @@ +/* Main container for the entire table layout */ .pst-container { - padding: 8px; + padding: 4px; display: flex; flex-direction: column; - row-gap: 5px; + row-gap: 2px; height: 100%; + width: 100%; + box-sizing: border-box; +} + +/* Styling for the Thermal and Power Specification section */ +.thermal-power-specification { + padding: 4px; + background-color: #f0f7f5; + border: 1px solid #d1d1d1; + border-radius: 6px; + margin-bottom: 4px; + display: flex; + flex-direction: column; + row-gap: 4px; + width: 100%; + margin-left: auto; + margin-right: auto; + box-sizing: border-box; +} + +/* Header styling for the Thermal and Power Specification */ +.spec-header { + font-weight: bold; + font-size: 11px; + text-align: center; + color: #333; + background-color: #e1e1e1; + padding: 4px; + border: 1px solid #c0c0c0; + border-radius: 4px; +} + +/* Table styling for the specification sections */ +.spec-table { + width: 100%; + border-collapse: collapse; + margin-bottom: 4px; +} + +.spec-table th, .spec-table td { + padding: 3px; + text-align: center; + border: 1px solid #d1d1d1; + font-size: 10px; +} + +/* Styling for headers in the Typical and Worst-Case columns */ +.spec-table .typical-header, .spec-table .worst-header { + font-weight: bold; + background-color: #f0f0f0; + border-bottom: 1px solid #c0c0c0; +} + +/* Special handling for ΘJA row that spans across two columns */ +.spec-table .theta-row td { + text-align: center; + font-weight: bold; + color: #444; + padding: 3px; + border-right: 1px solid #d1d1d1; + border-left: 1px solid #d1d1d1; +} + +/* Input field styling */ +.spec-table td input { + width: 45px; + padding: 2px; + font-size: 10px; + text-align: center; +} + +/* Bottom section for Power Specification */ +.power-spec-section { + padding: 4px; + background-color: #f0f7f5; + border: 1px solid #d1d1d1; + border-radius: 6px; + margin-bottom: 4px; + width: 100%; + margin-left: auto; + margin-right: auto; +} + +/* Table for Power Specification */ +.power-spec-table { + width: 100%; + border-collapse: collapse; +} + +.power-spec-table th, .power-spec-table td { + padding: 3px; + text-align: center; + border: 1px solid #d1d1d1; + font-size: 10px; +} + +/* Styling for power budget and dynamic scaling */ +.power-spec-table .scaling-cell { + font-weight: bold; + color: #444; } +/* Input fields in Power Specification */ +.power-spec-table td input { + width: 45px; + padding: 2px; + text-align: center; + font-size: 10px; +} + +/* Header styling for both Thermal and Power sections */ +.bold-text-title { + font-weight: bold; + font-size: 11px; + color: #333; + text-align: left; +} + +/* FPGA Complex and Core Power table */ .pst-table { width: 100%; border-collapse: collapse; + box-sizing: border-box; + height: auto; /* Changed height to auto to fit content */ + display: table; + table-layout: fixed; /* Ensure equal column widths */ + margin-bottom: 0; /* Removed extra margin for symmetrical alignment */ } .pst-table td { - padding-top: 0.5em; - padding-bottom: 0.5em; + padding: 0.20em 0.99em; /* Adjusted padding for consistent spacing */ + border-bottom: 1px solid #e1e1e1; + text-align: left; /* Align content to the left */ + font-size: 10px; + width: 100%; } -.pst-table td { +/* Processing Complex (SOC) Power table */ +.pst-table-soc { + width: 100%; + border-collapse: collapse; + box-sizing: border-box; + height: auto; /* Changed height to auto to fit content */ + display: table; + table-layout: fixed; + margin-bottom: 0; /* Ensures symmetrical gap with the FPGA table */ +} + +.pst-table-soc td { + padding: 0.80em 0.99em; /* Same padding adjustments for consistency */ border-bottom: 1px solid #e1e1e1; + text-align: left; + font-size: 20px; + width: 100%; } -.pst-table tbody>tr:last-child>td { +.pst-table tbody>tr:last-child>td, +.pst-table-soc tbody>tr:last-child>td { border-bottom: 0; } +/* Bottom section */ .pst-bottom { display: flex; flex-direction: row; + justify-content: space-between; border-top: 1px solid #e1e1e1; - margin-top: 10px; - padding-top: 3px; - padding-bottom: 3px; + margin-top: 0; + padding-top: 2px; + padding-bottom: 2px; align-items: flex-end; } @@ -40,23 +184,40 @@ .pst-bottom-progress { text-align: left; + width: 50%; } .pst-bottom-total { text-align: right; - width: 100%; + width: 50%; color: #7c7c7c; - font-size: 17px; + font-size: 10px; } +/* Styling for dot icons */ .dot-td { text-align: center; } .dot { - width: 10px; - height: 10px; + width: 8px; + height: 8px; border-radius: 50%; display: inline-block; vertical-align: middle; } + +/* Remove unnecessary bottom space */ +.pst-container, +.pst-table, +.pst-table-soc { + margin-bottom: 0; + height: 100%; +} + +/* Ensure table fills the entire container */ +.pst-table, .pst-table-soc { + display: flex; + flex-direction: column; + justify-content: space-between; +} From 5d5a38444c0195c0ff68822218a7d6da869d27cd Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 26 Nov 2024 08:59:23 -0800 Subject: [PATCH 2/9] fixing eslint errors on ubuntu --- src/components/Tables/PowerSummaryTable.js | 125 +++++++++++++-------- 1 file changed, 77 insertions(+), 48 deletions(-) diff --git a/src/components/Tables/PowerSummaryTable.js b/src/components/Tables/PowerSummaryTable.js index 8f93f170..f0732ffd 100644 --- a/src/components/Tables/PowerSummaryTable.js +++ b/src/components/Tables/PowerSummaryTable.js @@ -5,7 +5,7 @@ import { Tooltip } from 'antd'; import { PowerCell } from './TableCells'; import { fixed, color } from '../../utils/common'; import { State } from '../ComponentsLib'; -import { api, PATCH, GET, deviceInfo } from '../../utils/serverAPI'; +import { GET, deviceInfo } from '../../utils/serverAPI'; import '../style/PowerSummaryTable.css'; function PowerSummaryTableToolTip({ title, statusColor }) { @@ -18,7 +18,9 @@ function PowerSummaryTableToolTip({ title, statusColor }) { ); } -function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId = 'MPW1' }) { +function PowerSummaryTable({ + title, data = [], total = 0, percent = 0, deviceId = 'MPW1', +}) { const [thermalData, setThermalData] = useState({ ambientTypical: 25, ambientWorstCase: 50, @@ -45,19 +47,20 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId GET(deviceInfo(deviceId), (result) => { if (result && result.specification) { const { specification } = result; - + // Process thermal data setThermalData({ ambientTypical: specification.thermal?.ambient?.typical || 25, ambientWorstCase: specification.thermal?.ambient?.worstcase || 50, thetaJa: specification.thermal?.theta_ja || 10, }); - + // Process power data setPowerData({ powerBudget: specification.power?.budget || 1.0, fpgaScaling: (specification.power?.typical_dynamic_scaling?.fpga_complex || 0) * 100, - pcScaling: (specification.power?.typical_dynamic_scaling?.processing_complex || 0) * 100, + pcScaling: + (specification.power?.typical_dynamic_scaling?.processing_complex || 0) * 100, }); } }); @@ -65,34 +68,34 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId console.error('Error fetching data:', error); } }; - + fetchData(); // Trigger the fetch function - }, [deviceId]); // Re-run effect when deviceId changes + }, [deviceId]); // Re-run effect when deviceId changes - const updateBackend = async (deviceId, thermalData, powerData) => { + const updateBackend = async (deviceIdParam, thermalDataParam, powerDataParam) => { const updatedData = { specification: { - thermal: { - ambient: { - typical: thermalData.ambientTypical || 0, - worsecase: thermalData.ambientWorstCase || 0, // Note: This matches the schema - }, - theta_ja: thermalData.thetaJa || 0, + thermal: { + ambient: { + typical: thermalDataParam.ambientTypical || 0, + worsecase: thermalDataParam.ambientWorstCase || 0, // Matches schema }, - power: { - budget: powerData.powerBudget || 0, - typical_dynamic_scaling: { - fpga_complex: powerData.fpgaScaling || 0, - processing_complex: powerData.pcScaling || 0, - }, + theta_ja: thermalDataParam.thetaJa || 0, + }, + power: { + budget: powerDataParam.powerBudget || 0, + typical_dynamic_scaling: { + fpga_complex: powerDataParam.fpgaScaling || 0, + processing_complex: powerDataParam.pcScaling || 0, }, + }, }, - }; - + }; + console.log('PATCH Payload:', JSON.stringify(updatedData, null, 2)); try { - const response = await fetch(`http://127.0.0.1:5000/devices/${deviceId}`, { + const response = await fetch(`http://127.0.0.1:5000/devices/${deviceIdParam}`, { method: 'PATCH', headers: { 'Content-Type': 'application/json', @@ -116,9 +119,9 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId const updatedPowerData = { ...powerData }; if (field in thermalData) { - updatedThermalData[field] = isNaN(parseFloat(value)) ? 0 : parseFloat(value); + updatedThermalData[field] = Number.isNaN(parseFloat(value)) ? 0 : parseFloat(value); } else { - updatedPowerData[field] = isNaN(parseFloat(value)) ? 0 : parseFloat(value); + updatedPowerData[field] = Number.isNaN(parseFloat(value)) ? 0 : parseFloat(value); } setThermalData(updatedThermalData); @@ -128,7 +131,7 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId }; const enforceNumericInput = (e) => { - const value = e.target.value; + const { value } = e.target; const valid = /^-?\d*\.?\d*%?$/.test(value); if (!valid) { e.target.value = value.slice(0, -1); @@ -141,24 +144,30 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId } }; - const getErrors = (messages) => - messages?.filter((item) => item.some((inner) => inner.type === 'error')) || []; - const getWarnings = (messages) => - messages?.filter((item) => item.some((inner) => inner.type === 'warn')) || []; + const getErrors = (messages) => messages?.filter((item) => item.some((inner) => inner.type === 'error')) || []; + const getWarnings = (messages) => messages?.filter((item) => item.some((inner) => inner.type === 'warn')) || []; - const buildMessage = (messages) => - messages.reduce((acc, item, currentIndex) => { - item.forEach((i, index) => acc.push({i.text}
)); - return acc; - }, []); + const buildMessage = (messages) => messages.reduce((acc, item) => { // Removed `currentIndex` + item.forEach((i) => acc.push( + + {' '} + {/* Replace with the unique property */} + {i.text} +
+
, + )); + return acc; + }, []); const message = (messages) => { const errors = getErrors(messages); return errors.length > 0 ? buildMessage(errors) : buildMessage(getWarnings(messages)); }; - const statusColor = (messages) => - color(getErrors(messages).length > 0, getWarnings(messages).length > 0); + const statusColor = (messages) => color( + getErrors(messages).length > 0, + getWarnings(messages).length > 0, + ); return (
@@ -168,7 +177,7 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId - + @@ -184,7 +193,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId onInput={enforceNumericInput} ref={ambientTypicalRef} onKeyDown={(e) => handleKeyDown(e, ambientWorstCaseRef)} - />{' '} + /> + {' '} °C @@ -209,7 +220,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId onInput={enforceNumericInput} ref={thetaJaRef} onKeyDown={(e) => handleKeyDown(e, powerBudgetRef)} - />{' '} + /> + {' '} °C/W @@ -229,7 +241,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId onInput={enforceNumericInput} ref={powerBudgetRef} onKeyDown={(e) => handleKeyDown(e, fpgaScalingRef)} - />{' '} + /> + {' '} W @@ -244,7 +257,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId onInput={enforceNumericInput} ref={fpgaScalingRef} onKeyDown={(e) => handleKeyDown(e, pcScalingRef)} - />{' '} + /> + {' '} % @@ -268,8 +283,10 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId
Typical Worst-Case
@@ -195,7 +205,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId onInput={enforceNumericInput} ref={ambientWorstCaseRef} onKeyDown={(e) => handleKeyDown(e, thetaJaRef)} - />{' '} + /> + {' '} °C
@@ -255,7 +269,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId onChange={(e) => handleFieldUpdate('pcScaling', e.target.value)} onInput={enforceNumericInput} ref={pcScalingRef} - />{' '} + /> + {' '} %
- {data.map((item, index) => ( - + {data.map((item) => ( + + {' '} + {/* Use a unique property like `id` */} @@ -279,7 +296,8 @@ function PowerSummaryTable({ title, data = [], total = 0, percent = 0, deviceId {`${fixed(item.percent || 0, 0)} %`} - + @@ -192,7 +192,7 @@ function PowerSummaryTable({ onChange={(e) => handleFieldUpdate('ambientTypical', e.target.value)} onInput={enforceNumericInput} ref={ambientTypicalRef} - onKeyDown={(e) => handleKeyDown(e, ambientWorstCaseRef)} + onKeyDown={(e) => handleKeyDown(e, ambientWorseCaseRef)} /> {' '} °C @@ -200,10 +200,10 @@ function PowerSummaryTable({
- {(getErrors(item.messages).length > 0 || getWarnings(item.messages).length > 0) && ( + {(getErrors(item.messages).length > 0 + || getWarnings(item.messages).length > 0) && ( Date: Fri, 29 Nov 2024 18:56:00 -0800 Subject: [PATCH 3/9] Update PowerSummaryTable.js --- src/components/Tables/PowerSummaryTable.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Tables/PowerSummaryTable.js b/src/components/Tables/PowerSummaryTable.js index f0732ffd..2beb67cb 100644 --- a/src/components/Tables/PowerSummaryTable.js +++ b/src/components/Tables/PowerSummaryTable.js @@ -23,7 +23,7 @@ function PowerSummaryTable({ }) { const [thermalData, setThermalData] = useState({ ambientTypical: 25, - ambientWorstCase: 50, + ambientWorseCase: 50, thetaJa: 10, }); @@ -34,7 +34,7 @@ function PowerSummaryTable({ }); const ambientTypicalRef = useRef(null); - const ambientWorstCaseRef = useRef(null); + const ambientWorseCaseRef = useRef(null); const thetaJaRef = useRef(null); const powerBudgetRef = useRef(null); const fpgaScalingRef = useRef(null); @@ -51,7 +51,7 @@ function PowerSummaryTable({ // Process thermal data setThermalData({ ambientTypical: specification.thermal?.ambient?.typical || 25, - ambientWorstCase: specification.thermal?.ambient?.worstcase || 50, + ambientWorseCase: specification.thermal?.ambient?.worsecase || 50, thetaJa: specification.thermal?.theta_ja || 10, }); @@ -78,7 +78,7 @@ function PowerSummaryTable({ thermal: { ambient: { typical: thermalDataParam.ambientTypical || 0, - worsecase: thermalDataParam.ambientWorstCase || 0, // Matches schema + worsecase: thermalDataParam.ambientWorseCase || 0, // Matches schema }, theta_ja: thermalDataParam.thetaJa || 0, }, @@ -179,7 +179,7 @@ function PowerSummaryTable({
TypicalWorst-CaseWorse-Case
handleFieldUpdate('ambientWorstCase', e.target.value)} + value={thermalData.ambientWorseCase} + onChange={(e) => handleFieldUpdate('ambientWorseCase', e.target.value)} onInput={enforceNumericInput} - ref={ambientWorstCaseRef} + ref={ambientWorseCaseRef} onKeyDown={(e) => handleKeyDown(e, thetaJaRef)} /> {' '} From 3ec1810239e4c5e75e117e2f7df657f0fbd81020 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Dec 2024 18:42:22 -0800 Subject: [PATCH 4/9] updating global state provider for thermal and power specification --- src/GlobalStateProvider.js | 71 +++++++++++++++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) diff --git a/src/GlobalStateProvider.js b/src/GlobalStateProvider.js index 6746dc57..e4ce912c 100644 --- a/src/GlobalStateProvider.js +++ b/src/GlobalStateProvider.js @@ -38,6 +38,16 @@ export function GlobalStateProvider({ children, fetch }) { // TODO temp fix for const [bcpuNames, setBcpuNames] = useState([]); const [connectivityNames, setConnectivityNames] = useState([]); const [dmaNames, setDmaNames] = useState([]); + const [thermalData, setThermalData] = useState({ + ambientTypical: 25, + ambientWorseCase: 50, + thetaJa: 10, + }); + const [powerData, setPowerData] = useState({ + powerBudget: 1.0, + fpgaScaling: 25, + pcScaling: 25, + }); let peripheralsMessages = {}; @@ -128,6 +138,22 @@ export function GlobalStateProvider({ children, fetch }) { // TODO temp fix for updatePeripherals(device, item.href, item.type); }); }); + + server.GET(server.deviceInfo(device), (result) => { + if (result && result.specification) { + const { specification } = result; + setThermalData({ + ambientTypical: specification.thermal?.ambient?.typical || 25, + ambientWorseCase: specification.thermal?.ambient?.worsecase || 50, + thetaJa: specification.thermal?.theta_ja || 10, + }); + setPowerData({ + powerBudget: specification.power?.budget || 1.0, + fpgaScaling: (specification.power?.typical_dynamic_scaling?.fpga_complex || 0) * 100, + pcScaling: (specification.power?.typical_dynamic_scaling?.processing_complex || 0) * 100, + }); + } + }); } else { setClockingState([]); setFleState([]); @@ -136,9 +162,49 @@ export function GlobalStateProvider({ children, fetch }) { // TODO temp fix for setIoState([]); setSocState({}); setPeripherals([]); + setThermalData({ + ambientTypical: 25, + ambientWorseCase: 50, + thetaJa: 10, + }); + setPowerData({ + powerBudget: 1.0, + fpgaScaling: 25, + pcScaling: 25, + }); } } + function updateThermalAndPowerData(device, newThermalData, newPowerData) { + const updatedData = { + specification: { + thermal: { + ambient: { + typical: newThermalData.ambientTypical, + worsecase: newThermalData.ambientWorseCase, + }, + theta_ja: newThermalData.thetaJa, + }, + power: { + budget: newPowerData.powerBudget, + typical_dynamic_scaling: { + fpga_complex: newPowerData.fpgaScaling / 100, + processing_complex: newPowerData.pcScaling / 100, + }, + }, + }, + }; + + server.PATCH(server.deviceInfo(device), updatedData, (response) => { + if (response.ok) { + setThermalData(newThermalData); + setPowerData(newPowerData); + } else { + console.error('Error updating thermal and power data:', response.statusText); + } + }); + } + function GetOptions(id) { const found = attributes.find((elem) => id === elem.id); return (found === undefined) ? [] : found.options; @@ -150,6 +216,7 @@ export function GlobalStateProvider({ children, fetch }) { // TODO temp fix for const values = useMemo(() => ({ updateGlobalState, + updateThermalAndPowerData, clockingState, fleState, bramState, @@ -163,8 +230,10 @@ export function GlobalStateProvider({ children, fetch }) { // TODO temp fix for connectivityNames, dmaNames, fetchAttributes, + thermalData, + powerData, // eslint-disable-next-line react-hooks/exhaustive-deps - }), [bramState, clockingState, dspState, fleState, ioState, socState]); + }), [bramState, clockingState, dspState, fleState, ioState, socState, thermalData, powerData]); return ( From 989c452af16d64a29b0fcbb7fb2dc45983306e6b Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Dec 2024 18:47:10 -0800 Subject: [PATCH 5/9] fixing unit tests for globalstateprovider.js --- src/tests/GlobalStateProvider.test.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/tests/GlobalStateProvider.test.js b/src/tests/GlobalStateProvider.test.js index 8a4f5f43..a1ab3ab6 100644 --- a/src/tests/GlobalStateProvider.test.js +++ b/src/tests/GlobalStateProvider.test.js @@ -6,6 +6,7 @@ import * as server from '../utils/serverAPI'; jest.mock('../utils/serverAPI', () => ({ GET: jest.fn(), + PATCH: jest.fn(), api: { fetch: jest.fn((elem, device) => `/mock-api/${elem}/${device}`), }, @@ -19,17 +20,25 @@ jest.mock('../utils/serverAPI', () => ({ }, peripheralPath: jest.fn((device, path) => `/mock-api/peripheral/${device}/${path}`), attributes: jest.fn(() => '/mock-api/attributes'), + deviceInfo: jest.fn((device) => `/mock-api/device-info/${device}`), // Mock `deviceInfo` })); const TestComponent = () => { - const { updateGlobalState, clockingState, peripherals, acpuNames, fetchAttributes, GetOptions } = useGlobalState(); + const { + updateGlobalState, + clockingState, + peripherals, + acpuNames, + fetchAttributes, + GetOptions, + } = useGlobalState(); const options = GetOptions('mock-attribute'); return (
{clockingState.join(', ')}
{peripherals.length}
-
{acpuNames.map(acpu => acpu.text).join(', ')}
+
{acpuNames.map((acpu) => acpu.text).join(', ')}
{options.join(', ')}
@@ -60,6 +69,8 @@ describe('GlobalStateProvider', () => { callback([{ href: '/mock-peripheral', type: 'DMA' }]); } else if (url.includes('mock-peripheral')) { callback({ consumption: { messages: 'DMA Message' }, targets: 8 }); + } else if (url.includes('device-info')) { + callback({ specification: { thermal: {}, power: {} } }); // Mock device info response } }); From 3221d15618a00c3ece90a8affae4a5f51ddf062f Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 1 Dec 2024 18:55:20 -0800 Subject: [PATCH 6/9] fixing eslint error --- src/GlobalStateProvider.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/GlobalStateProvider.js b/src/GlobalStateProvider.js index e4ce912c..71634f95 100644 --- a/src/GlobalStateProvider.js +++ b/src/GlobalStateProvider.js @@ -149,8 +149,11 @@ export function GlobalStateProvider({ children, fetch }) { // TODO temp fix for }); setPowerData({ powerBudget: specification.power?.budget || 1.0, - fpgaScaling: (specification.power?.typical_dynamic_scaling?.fpga_complex || 0) * 100, - pcScaling: (specification.power?.typical_dynamic_scaling?.processing_complex || 0) * 100, + fpgaScaling: + (specification.power?.typical_dynamic_scaling?.fpga_complex || 0) * 100, + pcScaling: + (specification.power?.typical_dynamic_scaling?.processing_complex || 0) + * 100, }); } }); From f1b3d14a45830c3b72bb3c4653dfc2ee77a2ec8a Mon Sep 17 00:00:00 2001 From: Shiva Ahir Date: Mon, 2 Dec 2024 07:18:57 -0800 Subject: [PATCH 7/9] Update GlobalStateProvider.test.js --- src/tests/GlobalStateProvider.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tests/GlobalStateProvider.test.js b/src/tests/GlobalStateProvider.test.js index a1ab3ab6..be412656 100644 --- a/src/tests/GlobalStateProvider.test.js +++ b/src/tests/GlobalStateProvider.test.js @@ -20,7 +20,7 @@ jest.mock('../utils/serverAPI', () => ({ }, peripheralPath: jest.fn((device, path) => `/mock-api/peripheral/${device}/${path}`), attributes: jest.fn(() => '/mock-api/attributes'), - deviceInfo: jest.fn((device) => `/mock-api/device-info/${device}`), // Mock `deviceInfo` + deviceInfo: jest.fn((device) => `/mock-api/device-info/${device}`), })); const TestComponent = () => { @@ -70,7 +70,7 @@ describe('GlobalStateProvider', () => { } else if (url.includes('mock-peripheral')) { callback({ consumption: { messages: 'DMA Message' }, targets: 8 }); } else if (url.includes('device-info')) { - callback({ specification: { thermal: {}, power: {} } }); // Mock device info response + callback({ specification: { thermal: {}, power: {} } }); } }); From 448ebb18bab02d1789187548c9c1dc1720e39c25 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 5 Dec 2024 05:29:01 -0800 Subject: [PATCH 8/9] adding fix for updating the thermal and power spec updates --- backend/api/device.py | 1 + 1 file changed, 1 insertion(+) diff --git a/backend/api/device.py b/backend/api/device.py index 4b840231..d949dbbc 100644 --- a/backend/api/device.py +++ b/backend/api/device.py @@ -312,6 +312,7 @@ def patch(self, device_id : str): device = device_mgr.get_device(device_id) schema = DeviceSchema() device.update_spec(schema.load(request.json)['specification']) + device.compute_output_power() from submodule.rs_project import RsProjectManager RsProjectManager.get_instance().set_modified(True) return schema.dump(device), 200 From 632f4f46bee6cd662c377eabd48a678f157d1136 Mon Sep 17 00:00:00 2001 From: Shiva Ahir Date: Fri, 13 Dec 2024 10:19:07 -0800 Subject: [PATCH 9/9] Update PowerSummaryTable.js --- src/components/Tables/PowerSummaryTable.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Tables/PowerSummaryTable.js b/src/components/Tables/PowerSummaryTable.js index 2beb67cb..304de319 100644 --- a/src/components/Tables/PowerSummaryTable.js +++ b/src/components/Tables/PowerSummaryTable.js @@ -19,7 +19,7 @@ function PowerSummaryTableToolTip({ title, statusColor }) { } function PowerSummaryTable({ - title, data = [], total = 0, percent = 0, deviceId = 'MPW1', + title, data = [], total = 0, percent = 0, deviceId = 'MPW1', #TODO }) { const [thermalData, setThermalData] = useState({ ambientTypical: 25,