@diamondlightsource/cs-web-lib
v0.10.20
Published
Control system web library
Keywords
Readme
cs-web-lib
cs-web-lib is a React component library for EPICS Control Systems web applications, based off CSStudio Phoebus.
Features
cs-web-lib does not contain the full suite of features and widgets provided by Phoebus. The tables below describes which features are currently included, are planned to be added, and which will not be added.
Widgets
| Category | Widget | Included | Reason | | :---------------- | :---------------: | :------: | :-----------------: | | Graphics | Arc | ✅ | | | | Ellipse | ✅ | | | | Label | ✅ | | | | Picture | ✅ | | | | Polygon | ✅ | | | | Polyline | ✅ | | | | Rectangle | ✅ | | | Monitors | Byte Monitor | ✅ | | | | LED | ✅ | | | | Linear Meter | ✅ | | | | Multi State LED | ❌ | Add later | | | Meter | ✅ | | | | Progress Bar | ✅ | | | | Symbol | ✅ | | | | Table | ✅ | | | | Tank | ✅ | | | | Text Symbol | ❌ | Add later | | | Text Update | ✅ | | | | Thermometer | ✅ | | | Controls | Action Button | ✅ | | | | Boolean Button | ✅ | | | | Check Box | ✅ | | | | Choice Button | ✅ | | | | Combo Box | ✅ | | | | File Selector | ❌ | Add later | | | Radio Button | ✅ | | | | Scaled Slider | ✅ | | | | Scrollbar | ❌ | Add later | | | Slide Button | ❌ | Add later (date unknown, low priority) | | | Spinner | ❌ | Add later (date unknown, low priority) | | | Text Entry | ✅ | | | | Thumbwheel | ❌ | Add later (date unknown, low priority) | | Plots | Data Browser | ✅ | Basic Implementation | | | Image | ❌ | Unknown | | | Stripchart | ✅ | | | | XY Plot | ✅ | | | Structure | Array | ❌ | Add later | | | Embedded Display | ✅ | | | | Group | ✅ | | | | Navigation Tabs | ✅ | | | | Tabs | ✅ | | | | Template/Instance | ❌ | Unknown |
Methods
| Widget | Included | Reason |
| :---------: | :------: | :---------------------: |
| Actions | ✅ | Some actions may not be supported. Please open an issue for any issues noticed. |
| Formulas | ✅ | sim://, eq:// and loc:// PVs are supported. |
| Rules | ✅ | Partial support. Please open an issue for any issues noticed.|
| Scripts | ❌ | Basic PoC for scripting is currently implemented, which works for background colour and position ONLY. |
Installation
Install via npm:
npm install @diamondlightsource/cs-web-lib
To use cs-web-lib in a client project, you will need:
- React 18
- Vite
- A separate running instance of PVWS
Configuring PVWS
To make use of PVs in cs-web-lib widgets, you need to connect to PVWS. The basic configuration parameters for this will be loaded at runtime from a JSON file. This should be located somewhere accessible at runtime such as /public directory. The schema/structure of the configuration file is:
{
storeMode: "DEV" | PROD",
classFile: string,
defaultMjpgEndpoint: string,
csWebLibFeatureFlags: {
enableDynamicScripts: boolean
},
PVWS_SOCKET: string,
PVWS_SSL: boolean,
THROTTLE_PERIOD: integer
}The configuration parameters are:
| Parameter | type | Description |
|- | -| - |
| storeMode | string | Either DEV or PROD, default is PROD. In DEV mode the redux store devTools, immutable & serializable checks are switched on; in prod mode they are switch off to improve performance. |
| classFile | string | A URL that points towards the location of a .bcf, or .bob class file. This file will be used to apply style via classes like Phoebus does to all files. |
| defaultMjpgEndpoint | string | A URL that points towards the Mjpeg endpoint for the Image widget. This endpoint combined with a PV name returns an MJPEG stream to be displayed. |
| enableDynamicScripts | boolean | Either enables or disables the dynamic scripting functionality. It is false by default. |
| PVWS_SOCKET | string | The fully qualified hostname and port of the instance of the PVWS web service |
| PVWS_SSL | boolean | If true use https, if false use http for connecting to the PVWS web service |
| THROTTLE_PERIOD | integer | The period in milliseconds between updates of the PV state variables |
At the root of your client app, create a config.ts file to load the config from this file.
import { CsWebLibConfig } from "@diamondlightsource/cs-web-lib";
export const loadConfig = async (): Promise<CsWebLibConfig> => {
if (config) {
return config;
}
try {
// Point towards your file location
const response = await fetch("/config/config.json");
config = await response.json();
} catch (error) {
console.warn("Configuration not found falling back to defaults", error);
// Set defaults here if necessary
config = {
PVWS_SOCKET: undefined,
PVWS_SSL: undefined,
THROTTLE_PERIOD: undefined,
storeMode: undefined,
defaultMjpgEndpoint: undefined,
csWebLibFeatureFlags: {
enableDynamicScripts: false
},
classFile: undefined
};
}
return config as CsWebLibConfig;
};The final step is to wrap your application in a Redux Provider and pass in the loaded config and cs-web-lib PV store. This allows your application to access the store which handles subscribing to PVs and storing updates to values.
import { store, CsWebLibConfig } from "@diamondlightsource/cs-web-lib";
import { Provider } from "react-redux";
import { loadConfig } from "./config";
function App({}) {
const [config, setConfig] = useState<CsWebLibConfig | null>(null);
useEffect(() => {
loadConfig().then(config => {
setConfig(config);
});
}, []);
return (
<Provider store={store(config)}>
// Your app goes here
</Provider>
);
}
export default App;Now you can use cs-web-lib to display .bob files and see updates to PV values.
If you're making use of a widget such as the Image widget, you can provide a default disconnected symbol for this widget to use by creating a file /public/images/disconnectedImage.svg. If the stream fails to connect, it will instead show this image.
Displaying a .bob file
To view a file in the client application, make use of the display components. These are:
- Embedded Display
This displays a single screen, passed in via a filepath.
<EmbeddedDisplay file={{ path: "/my/file.bob", defaultProtocol: "ca" // Or "pva", macros: {} }} position={newRelativePosition("0", "0", "100%", "100%")} scroll={false} resize={"scroll-content"} /> - Dynamic Page
This component allows dynamic loading of different files, using a FileContext to store which file is currently displayed. The application must be wrapped in the FileProvider to access this context. The executeAction function can be called to trigger changes in displayed files.
import { FileProvider } from "@diamondlightsource/cs-web-lib"; const INITIAL_SCREEN_STATE = { main: { path: "/my/file.bob", macros: {}, defaultProtocol: "ca" } }; function DemoDynamicPage() { const fileContext = useContext(FileContext); // Use executeAction to update the displayed file const handleClick = () => { executeAction( { type: "OPEN_PAGE", dynamicInfo: { name: "new", location: "main", description: undefined, pvwsHost: "pvws-host.diamond.ac.uk" file: { path: "/my/new_file.bob macros: {}, defaultProtocol: "ca" } } }, // our action to execute fileContext, // the file context undefined, //files {}, //macros "browser-url.diamond.ac.uk" //url address ); }; return ( <FileProvider initialPageState={INITIAL_SCREEN_STATE}> <Button onClick={handleClick}> <DynamicPageWidget location={"main"} position={newRelativePosition()} scroll={false} showCloseButton={false} /> </FileProvider> ); }
Using Standalone widgets
cs-web-lib widgets can also be used independently of an Embedded Display or Dynamic Page widget, simply by treating them as any other React component. These must be initialised with a position, using either an AbsolutePosition or a RelativePosition object, and can be passed other properties.
Development
Install Node
Install Node.js version 22+, if it is not already installed on your machine.
Clone the repository
git clone https://github.com/DiamondLightSource/cs-web-lib.gitInstall the dependencies, from the root folder of the repo run:
npm ciTo run the unit tests:
npm run testTo run the static analysis and code style checks:
npm run all-checksTo test your development version
You can install a local version of cs-web-lib into a project to test out any changes:
npm run rollup
npm pack
cd <PROJECT_REPO_DIR>
npm install <CS_WEB_LIB_REPO_DIR>/cs-web-lib/diamondlightsource-cs-web-lib-*.*.*.tar.gzPublishing to NPM
Workflow A GitHub workflow has been setup to automatically publish a new package version to the NPM registry on the push of a new tag. This should be used as the preferred method of release a new package.
Increment the package version in package.json
npm version <major|minor|patch> -no-git-tag-versionCommit and push this to GitHub:
git add package.json
git commit -m "..." package.json
git push <remote> <branch>- Create a new tag and push to GitHub
git tag -a vX.XX.xx -m "..."
git push tag <remote> vX.XX.xx This will trigger a job on GitHub to publish a new version of the cs-web-lib to NPM. Check that this job passes.
Locally To publish a new version of the @diamondlightsource/cs-web-lib package you must first have an npm account and be a member of the DiamondLightSource organisation. Then:
- Update the package version in package.json (follow the major.minor.patch versioning terminology).
- Run the rollup command to package the library:
npm run rollup. - Login to your npm account:
npm adduser - Publish as a public-scoped packages:
npm publish --access public --registry=https://registry.npmjs.org
