Skip to content

Commit eaa3999

Browse files
authored
Merge pull request #153 from ISISComputingGroup/subscribe_in_one_go
subscribe in one go
2 parents 0eca6a6 + 73b8e7b commit eaa3999

File tree

3 files changed

+96
-74
lines changed

3 files changed

+96
-74
lines changed

app/components/Instrument.test.ts

Lines changed: 50 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@ import {
77
RC_INRANGE,
88
SP_RBV,
99
storePrecision,
10-
subscribeToBlockPVs,
10+
getExtraPVsForBlock,
1111
toPrecision,
1212
yesToBoolean,
13+
Instrument,
1314
} from "@/app/components/Instrument";
1415
import {
1516
ConfigOutput,
@@ -18,8 +19,6 @@ import {
1819
IfcGroup,
1920
IfcPV,
2021
IfcPVWSMessage,
21-
IfcPVWSRequest,
22-
PVWSRequestType,
2322
} from "@/app/types";
2423

2524
test("findPVinDashboard finds a pv in the dashboard and returns it", () => {
@@ -109,20 +108,6 @@ test("findPVInGroups returns a block when it finds one", () => {
109108
findPVInGroups(groups, prefix, prefix + CSSB + blockName);
110109
});
111110

112-
test("subscribeToBlockPVs subscribes to all run control PVs", () => {
113-
const mockSendJsonMessage = jest.fn();
114-
const aBlock = "INST:CS:SB:SomeBlock";
115-
subscribeToBlockPVs(mockSendJsonMessage, aBlock);
116-
expect(mockSendJsonMessage.mock.calls.length).toBe(1);
117-
const expectedCall: IfcPVWSRequest = {
118-
type: PVWSRequestType.subscribe,
119-
pvs: [aBlock, aBlock + RC_ENABLE, aBlock + RC_INRANGE, aBlock + SP_RBV],
120-
};
121-
expect(JSON.stringify(mockSendJsonMessage.mock.calls[0][0])).toBe(
122-
JSON.stringify(expectedCall),
123-
);
124-
});
125-
126111
test("toPrecision does nothing to string value ", () => {
127112
const expectedValue = "untouched";
128113
const aBlock: IfcBlock = {
@@ -165,8 +150,6 @@ test("yesToBoolean works with NO as value", () => {
165150
test("getGroupsWithBlocksFromConfigOutput gets blocks from blockserver groups", () => {
166151
const blockNameToTest = "aBlock";
167152
const groupNameToTest = "aGroup";
168-
const prefix = "TESTING";
169-
const mockSendJsonMessage = jest.fn();
170153

171154
const configOutput: ConfigOutput = {
172155
groups: [{ blocks: [blockNameToTest], name: groupNameToTest }],
@@ -198,22 +181,14 @@ test("getGroupsWithBlocksFromConfigOutput gets blocks from blockserver groups",
198181
component_iocs: [],
199182
history: [],
200183
};
201-
const groups = getGroupsWithBlocksFromConfigOutput(
202-
configOutput,
203-
mockSendJsonMessage,
204-
prefix,
205-
);
184+
const groups = getGroupsWithBlocksFromConfigOutput(configOutput);
206185
expect(groups[0].name).toBe(groupNameToTest);
207186
expect(groups[0].blocks[0].human_readable_name).toBe(blockNameToTest);
208187
});
209188

210189
test("subscribeToBlockPVs subscribes to blocks, their run control and their SP:RBV PVs", () => {
211-
const mockSendJsonMessage = jest.fn();
212190
const blockAddress = "IN:INST:CS:SB:Block1";
213-
subscribeToBlockPVs(mockSendJsonMessage, blockAddress);
214-
expect(mockSendJsonMessage).toBeCalledTimes(1);
215-
const call: Array<string> = mockSendJsonMessage.mock.calls[0][0].pvs;
216-
expect(call).toEqual(
191+
expect(getExtraPVsForBlock(blockAddress)).toEqual(
217192
expect.arrayContaining([
218193
blockAddress,
219194
blockAddress + RC_ENABLE,
@@ -234,3 +209,49 @@ test("storePrecision adds precision to a block if it is the first update", () =>
234209
storePrecision(message, blockWithoutPrecision);
235210
expect(blockWithoutPrecision.precision).toEqual(precision);
236211
});
212+
213+
test("getAllBlockPVs returns flat list of blocks, their RC and SPRBV pvs", () => {
214+
const block1Name = "blockName";
215+
const block2Name = "block2Name";
216+
const prefix = "IN:TEST:";
217+
218+
let inst = new Instrument(prefix);
219+
220+
inst.groups = [
221+
{
222+
name: "aGroup",
223+
blocks: [
224+
{
225+
human_readable_name: block1Name,
226+
pvaddress: "some:underlying:pv:name",
227+
},
228+
],
229+
},
230+
{
231+
name: "aDifferentGroup",
232+
blocks: [
233+
{
234+
human_readable_name: block2Name,
235+
pvaddress: "someother:underlying:pv:name",
236+
},
237+
],
238+
},
239+
];
240+
241+
const res = inst.getAllBlockPVs();
242+
243+
expect(res.length).toBe(2 * 4); // 2 blocks, which means 4 PVs to subscribe to
244+
245+
expect(res).toEqual(
246+
expect.arrayContaining([
247+
prefix + CSSB + block1Name,
248+
prefix + CSSB + block1Name + RC_ENABLE,
249+
prefix + CSSB + block1Name + RC_INRANGE,
250+
prefix + CSSB + block1Name + SP_RBV,
251+
prefix + CSSB + block2Name,
252+
prefix + CSSB + block2Name + RC_ENABLE,
253+
prefix + CSSB + block2Name + RC_INRANGE,
254+
prefix + CSSB + block2Name + SP_RBV,
255+
]),
256+
);
257+
});

app/components/Instrument.ts

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,6 @@ import {
66
IfcGroup,
77
IfcPV,
88
IfcPVWSMessage,
9-
IfcPVWSRequest,
10-
PVWSRequestType,
119
} from "@/app/types";
1210
import {
1311
ExponentialOnThresholdFormat,
@@ -188,6 +186,16 @@ export class Instrument {
188186
},
189187
];
190188
}
189+
190+
getAllBlockPVs(): Array<string> {
191+
return this.groups
192+
.map((g: IfcGroup) => g.blocks)
193+
.flat(1) // flatten to a big array of blocks
194+
.map((b: IfcBlock) =>
195+
getExtraPVsForBlock(this.prefix + CSSB + b.human_readable_name),
196+
)
197+
.flat(1); //flatten block, rc, sp_rbv pvs for every block to a 1d array
198+
}
191199
}
192200

193201
export function findPVInDashboard(
@@ -211,34 +219,31 @@ export function toPrecision(
211219
: pvVal;
212220
}
213221

214-
export function storePrecision(updatedPV: IfcPVWSMessage, block: IfcBlock) {
222+
export function storePrecision(
223+
updatedPV: IfcPVWSMessage,
224+
block: IfcBlock,
225+
): void {
215226
const prec = updatedPV.precision;
216227
if (prec != null && prec > 0 && !block.precision) {
217228
// this is likely the first update, and contains precision information which is not repeated on a normal value update - store this in the block for later truncation (see below)
218229
block.precision = prec;
219230
}
220231
}
221232

222-
export function yesToBoolean(pvVal: string | number) {
233+
export function yesToBoolean(pvVal: string | number): boolean {
223234
return pvVal == "YES";
224235
}
225236

226-
export function subscribeToBlockPVs(
227-
sendJsonMessage: (a: IfcPVWSRequest) => void,
228-
block_address: string,
229-
) {
237+
export function getExtraPVsForBlock(block_address: string): Array<string> {
230238
/**
231-
* Subscribes to a block and its associated run control PVs
239+
* Given a block name, give the run control and sp_rbv PVs.
232240
*/
233-
sendJsonMessage({
234-
type: PVWSRequestType.subscribe,
235-
pvs: [
236-
block_address,
237-
block_address + RC_ENABLE,
238-
block_address + RC_INRANGE,
239-
block_address + SP_RBV,
240-
],
241-
});
241+
return [
242+
block_address,
243+
block_address + RC_ENABLE,
244+
block_address + RC_INRANGE,
245+
block_address + SP_RBV,
246+
];
242247
}
243248

244249
/**
@@ -247,17 +252,15 @@ export function subscribeToBlockPVs(
247252
*/
248253
export function getGroupsWithBlocksFromConfigOutput(
249254
configOutput: ConfigOutput,
250-
sendJsonMessage: (a: IfcPVWSRequest) => void,
251-
prefix: string,
252255
): Array<IfcGroup> {
253-
const groups = configOutput.groups;
256+
const configOutputGroups = configOutput.groups;
254257
let newGroups: Array<IfcGroup> = [];
255-
for (const group of groups) {
256-
const groupName = group.name;
258+
for (const configOutputGroup of configOutputGroups) {
259+
const groupName = configOutputGroup.name;
257260
let blocks: Array<IfcBlock> = [];
258-
for (const block of group.blocks) {
261+
for (const configOutputBlock of configOutputGroup.blocks) {
259262
const newBlock = configOutput.blocks.find(
260-
(b: ConfigOutputBlock) => b.name === block,
263+
(b: ConfigOutputBlock) => b.name === configOutputBlock,
261264
);
262265
if (newBlock) {
263266
blocks.push({
@@ -267,8 +270,6 @@ export function getGroupsWithBlocksFromConfigOutput(
267270
high_rc: newBlock.highlimit,
268271
visible: newBlock.visible,
269272
});
270-
const fullyQualifiedBlockPVAddress = prefix + CSSB + newBlock.name;
271-
subscribeToBlockPVs(sendJsonMessage, fullyQualifiedBlockPVAddress);
272273
}
273274
}
274275
newGroups.push({

app/components/InstrumentData.tsx

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
"use client";
22
import { useEffect, useState } from "react";
3-
import { IfcPVWSMessage, IfcPVWSRequest, PVWSRequestType } from "@/app/types";
3+
import {
4+
IfcPV,
5+
IfcPVWSMessage,
6+
IfcPVWSRequest,
7+
PVWSRequestType,
8+
} from "@/app/types";
49
import {
510
findPVInDashboard,
611
findPVInGroups,
@@ -69,25 +74,18 @@ export function InstrumentData({ instrumentName }: { instrumentName: string }) {
6974
const updatedPVbytes: string | null | undefined = updatedPV.b64byt;
7075

7176
if (updatedPVName == instListPV && updatedPVbytes != null) {
72-
const instlist = instListFromBytes(updatedPVbytes);
73-
const prefix = getPrefix(instlist, instName);
77+
const prefix = getPrefix(instListFromBytes(updatedPVbytes), instName);
7478
const instrument = new Instrument(prefix);
7579
setCurrentInstrument(instrument);
7680

81+
// subscribe to dashboard and run info PVs
7782
sendJsonMessage({
7883
type: PVWSRequestType.subscribe,
79-
pvs: [`${prefix}${CONFIG_DETAILS}`],
84+
pvs: instrument.runInfoPVs
85+
.concat(instrument.dashboard.flat(3))
86+
.map((v: IfcPV) => v.pvaddress)
87+
.concat([`${prefix}${CONFIG_DETAILS}`]),
8088
});
81-
82-
// subscribe to dashboard and run info PVs
83-
for (const pv of instrument.runInfoPVs.concat(
84-
instrument.dashboard.flat(3),
85-
)) {
86-
sendJsonMessage({
87-
type: PVWSRequestType.subscribe,
88-
pvs: [pv.pvaddress],
89-
});
90-
}
9189
return;
9290
}
9391

@@ -105,12 +103,14 @@ export function InstrumentData({ instrumentName }: { instrumentName: string }) {
105103
return;
106104
}
107105
setLastUpdate(updatedPVbytes);
108-
const res = dehex_and_decompress(atob(updatedPVbytes));
109106
currentInstrument.groups = getGroupsWithBlocksFromConfigOutput(
110-
JSON.parse(res),
111-
sendJsonMessage,
112-
currentInstrument.prefix,
107+
JSON.parse(dehex_and_decompress(atob(updatedPVbytes))),
113108
);
109+
110+
sendJsonMessage({
111+
type: PVWSRequestType.subscribe,
112+
pvs: currentInstrument.getAllBlockPVs(),
113+
});
114114
} else {
115115
const pvVal = getPvValue(updatedPV);
116116

0 commit comments

Comments
 (0)