Skip to content

Commit

Permalink
Merge pull request #86 from ChannelFinder/waveforms
Browse files Browse the repository at this point in the history
Add option to display live value of waveform PVs
  • Loading branch information
tynanford authored Dec 15, 2023
2 parents f61d9fd + edb7edb commit 212f413
Show file tree
Hide file tree
Showing 8 changed files with 90 additions and 20 deletions.
6 changes: 6 additions & 0 deletions .env
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,12 @@ REACT_APP_PVWS_HTTP_URL=http://localhost:8081/pvws/
REACT_APP_LIVE_MONITOR_WARN=50
REACT_APP_LIVE_MONITOR_MAX=100

# By default, PV Info does not allow the user to subscribe to waveform PVs. Switch this to true
# to allow viewing of waveform PVs. Viewing large waveforms isn't useful in PV Info but
# for small waveforms it can be nice to see. PVWS uses EPICS_CA_MAX_ARRAY_BYTES and that
# can be used to limit giant waveforms coming across the websocket connection as a mitigation
REACT_APP_PVWS_ALLOW_WAVEFORMS=false

######################################################################################
# Archiver Web Viewer
######################################################################################
Expand Down
24 changes: 22 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "pvinfo",
"homepage": "https://yourdomainhere/pvinfo",
"version": "2.0.1",
"version": "2.1.0",
"private": true,
"dependencies": {
"@emotion/react": "^11.9.0",
Expand All @@ -13,6 +13,7 @@
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^14.1.1",
"@vitejs/plugin-react": "^4.1.0",
"base64-js": "^1.5.1",
"he": "^1.2.0",
"react": "^18.1.0",
"react-dom": "^18.1.0",
Expand Down
35 changes: 26 additions & 9 deletions src/components/home/queryresults/value/Value.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import useWebSocket from 'react-use-websocket';
import api from '../../../../api';
import colors from '../../../../colors';
import PropTypes from "prop-types";
import { toByteArray } from 'base64-js';

const propTypes = {
pvName: PropTypes.string,
Expand Down Expand Up @@ -34,6 +35,8 @@ function Value(props) {
const severity = jsonMessage.severity;
const units = jsonMessage.units;
const text = jsonMessage.text;
const b64dbl = jsonMessage.b64dbl;
const b64int = jsonMessage.b64int;
const value = jsonMessage.value;
const pv = jsonMessage.pv;
if (pv === undefined) {
Expand All @@ -49,6 +52,18 @@ function Value(props) {
if (text !== undefined) {
setPVValue(text);
}
else if (b64dbl !== undefined) {
let bytes = toByteArray(b64dbl);
let value_array = new Float64Array(bytes.buffer);
value_array = Array.prototype.slice.call(value_array);
setPVValue(value_array);
}
else if (b64int !== undefined) {
let bytes = toByteArray(b64int);
let value_array = new Int32Array(bytes.buffer);
value_array = Array.prototype.slice.call(value_array);
setPVValue(value_array);
}
else if (value !== undefined) {
if ((Number(value) >= 0.01 && Number(value) < 1000000000) || (Number(value) <= -0.01 && Number(value) > -1000000000) || Number(value) === 0) {
setPVValue(Number(value.toFixed(2)));
Expand Down Expand Up @@ -81,15 +96,17 @@ function Value(props) {
}

const severityName = pvSeverity === "UNDEFINED" || pvSeverity === "INVALID" ? ` (${pvSeverity})` : null
if (pvUnit !== undefined) {
return (
<div style={{ color: textColor }}>{`${pvValue} ${pvUnit}`}{severityName}</div>
);
}
else if (pvValue !== undefined) {
return (
<div style={{ color: textColor }}>{pvValue}{severityName}</div>
);
if (pvValue !== undefined) {
if (Array.isArray(pvValue)) {
return (
<div style={{ color: textColor }}>{`[ ${pvValue.join(', ')} ] ${pvUnit}`}{severityName}</div>
)
}
else {
return (
<div style={{ color: textColor }}>{`${pvValue} ${pvUnit}`}{severityName}</div>
);
}
}
else {
return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ const propTypes = {
updateCurrentChecked: PropTypes.func,
}

// TODO - check if these changes make performance better or worse or same
// fix dependency array issues, cleanup
// create PR into current PR branch
// then will need to talk to mitch and get things merged

function ValueCheckbox(props) {
// open web socket for sending subscribe/clear messages
// filter all messages as false since we don't need to read anything in parent component
Expand All @@ -34,7 +29,7 @@ function ValueCheckbox(props) {
}

useEffect(() => {
if (props.pvStatus === "Inactive" || props.recordType === "waveform") {
if (props.pvStatus === "Inactive" || (import.meta.env.REACT_APP_PVWS_ALLOW_WAVEFORMS !== "true" && props.recordType === "waveform")) {
setEnabled(false);
}
}, [props.pvStatus, props.recordType])
Expand All @@ -54,7 +49,7 @@ function ValueCheckbox(props) {
<Tooltip arrow title={<div>Monitor<br />{props.pvName}</div>}>
<Checkbox
checked={props.checked[props.id] && enabled}
disabled={props.pvStatus === "Inactive" || props.recordType === "waveform"}
disabled={props.pvStatus === "Inactive" || (import.meta.env.REACT_APP_PVWS_ALLOW_WAVEFORMS !== "true" && props.recordType === "waveform")}
color="primary"
onChange={handleMonitorPVChange(props.id)} >
</Checkbox>
Expand Down
4 changes: 4 additions & 0 deletions src/components/pv/KeyValuePair.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import PropTypes from 'prop-types';

const propTypes = {
title: PropTypes.string,
url: PropTypes.string,
textColor: PropTypes.string,
value: PropTypes.any,
}

Expand All @@ -27,6 +29,8 @@ function KeyValuePair(props) {
))
) : props.url ? (
<Link component={RouterLink} to={props.url} underline="hover">{props.value}</Link>
) : Array.isArray(props.value) ? (
<Fragment>[{props.value.join(', ')}]</Fragment>
) : (
<Fragment>{props.value}</Fragment>
)}
Expand Down
3 changes: 3 additions & 0 deletions src/components/pv/PV.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ function PV(props) {
</Box>
{
import.meta.env.REACT_APP_USE_PVWS === "true" ?
import.meta.env.REACT_APP_PVWS_ALLOW_WAVEFORMS === "true" ?
<FormControlLabel control={<Checkbox color="primary" checked={pvMonitoring} onChange={handlePVMonitoringChange}></Checkbox>} disabled={pvData?.pvStatus?.value === "Inactive"} label="Enable Live PV Monitoring" />
:
<FormControlLabel control={<Checkbox color="primary" checked={pvMonitoring} onChange={handlePVMonitoringChange}></Checkbox>} disabled={pvData?.pvStatus?.value === "Inactive" || pvData?.recordType?.value === "waveform"} label="Enable Live PV Monitoring" />
: null
}
Expand Down
26 changes: 25 additions & 1 deletion src/components/pv/valuetable/ValueTable.jsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React, { Fragment, useState, useEffect } from "react";
import { Typography } from "@mui/material";
import useWebSocket from 'react-use-websocket';
import { toByteArray } from 'base64-js';
import api from "../../../api";
import colors from "../../../colors";
import PropTypes from "prop-types";
Expand Down Expand Up @@ -60,7 +61,7 @@ function ValueTable(props) {
handleSeverity("warning");
handleOpenErrorAlert(true);
}
else if (props.pvData.recordType?.value === "waveform") {
else if (import.meta.env.REACT_APP_PVWS_ALLOW_WAVEFORMS !== "true" && props.pvData.recordType?.value === "waveform") {
handleErrorMessage("Can't show live PV values - Waveform record type not supported");
handleSeverity("warning");
handleOpenErrorAlert(true);
Expand Down Expand Up @@ -175,6 +176,29 @@ function ValueTable(props) {
}

}
// see "handleMessage" in https://github.com/ornl-epics/pvws/blob/main/src/main/webapp/js/pvws.js
else if ("b64dbl" in message) {
if (!props.snapshot) {
let bytes = toByteArray(message.b64dbl);
let value_array = new Float64Array(bytes.buffer);
value_array = Array.prototype.slice.call(value_array);
setPVValue(value_array);
}
if (snapshot) {
setSnapshot(false);
}
}
else if ("b64int" in message) {
if (!props.snapshot) {
let bytes = toByteArray(message.b64int);
let value_array = new Int32Array(bytes.buffer);
value_array = Array.prototype.slice.call(value_array);
setPVValue(value_array);
}
if (snapshot) {
setSnapshot(false);
}
}
else if ("value" in message) {
if (!props.snapshot) {
// if precision was explicitly set (and badly assume 0 is not explicit) then use that
Expand Down

0 comments on commit 212f413

Please sign in to comment.