Skip to content

Commit 6424b43

Browse files
authored
Merge pull request #2320 from ControlSystemStudio/patches
Adding a system time pv, with an offset and multiple format options
2 parents af9800c + 6671491 commit 6424b43

File tree

3 files changed

+126
-2
lines changed

3 files changed

+126
-2
lines changed

core/pv/doc/index.rst

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,5 +135,19 @@ If the VType is omitted, 'double' is assumed. Examples::
135135
mqtt://some_topic<VString>
136136
mqtt://some/nested/topic
137137

138+
System
139+
------
140+
System process variables are useful for representing some system attributes. They do not communicate with the control system.::
138141

142+
* sys://time
143+
* sys://timeOffset(offset, format, update_seconds)
139144

145+
The `timeOffset` pv allows you to represent a time instant offset from `now`. The optional parameters are:
146+
*offset* which is described as 1 min, 1 hour, 1 day prior to the current instant.
147+
*format* which describes how to represent the instance, the supported formats are full, milli, seconds, datetime, date, or time.
148+
*update_seconds* the update rate / period.
149+
150+
Examples ::
151+
152+
sys://timeOffset(12 hours)
153+
sys://timeOffset(1hour, time, 1)

core/pv/src/main/java/org/phoebus/pv/sys/SysPVFactory.java

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@
1010
import org.phoebus.pv.PV;
1111
import org.phoebus.pv.PVFactory;
1212

13+
import java.util.List;
14+
import java.util.stream.Collectors;
15+
1316
/** PV Factory for system PVs
14-
* @author Kay Kasemir
17+
* @author Kay Kasemir, Kunal Shroff
1518
*/
1619
@SuppressWarnings("nls")
1720
public class SysPVFactory implements PVFactory
@@ -28,8 +31,27 @@ public String getType()
2831
@Override
2932
public PV createPV(final String name, final String base_name) throws Exception
3033
{
31-
if (base_name.equals("time"))
34+
// Determine system pv function name and (optional) parameters
35+
final String func, parameters;
36+
int sep = base_name.indexOf('(');
37+
if (sep < 0)
38+
{
39+
func = base_name;
40+
parameters = "";
41+
}
42+
else
43+
{
44+
final int end = base_name.lastIndexOf(')');
45+
if (end < 0)
46+
throw new Exception("Missing closing bracket for parameters in '" + name + "'");
47+
func = base_name.substring(0, sep);
48+
parameters = base_name.substring(sep+1, end);
49+
}
50+
51+
if (func.equals("time"))
3252
return new TimePV(name);
53+
else if (func.equals("timeOffset"))
54+
return TimeOffsetPV.forParameters(name, List.of(parameters.split(",")).stream().map(String::strip).collect(Collectors.toList()));
3355
else
3456
throw new Exception("Unknown system PV " + base_name);
3557
}
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2022 Oak Ridge National Laboratory.
3+
* Copyright (c) 2022 Brookhaven National Laboratory.
4+
* All rights reserved. This program and the accompanying materials
5+
* are made available under the terms of the Eclipse Public License v1.0
6+
* which accompanies this distribution, and is available at
7+
* http://www.eclipse.org/legal/epl-v10.html
8+
******************************************************************************/
9+
package org.phoebus.pv.sys;
10+
11+
import org.phoebus.pv.sim.SimulatedStringPV;
12+
import org.phoebus.util.time.TimeParser;
13+
import org.phoebus.util.time.TimestampFormats;
14+
15+
import java.time.Instant;
16+
import java.time.format.DateTimeFormatter;
17+
import java.time.temporal.TemporalAmount;
18+
import java.util.List;
19+
20+
/** System "time" PV
21+
* @author Kunal Shroff, Kay Kasemir, based on similar code in diirt
22+
*/
23+
public class TimeOffsetPV extends SimulatedStringPV
24+
{
25+
private DateTimeFormatter formatter;
26+
private TemporalAmount temporalAmount;
27+
private double updateRate;
28+
29+
/**
30+
* Factory method for creating a time pv with user defined offset, format, and update rate.
31+
*
32+
* @param name pv name
33+
* @param parameters a list of optional parameters defining timeoffset, format, update rate
34+
* @return a new TimeOffsetPV
35+
*/
36+
public static TimeOffsetPV forParameters(final String name, final List<String> parameters) throws Exception {
37+
if(parameters != null && !parameters.isEmpty()) {
38+
if(parameters.size() == 1) {
39+
return new TimeOffsetPV(name, parameters.get(0), TimestampFormats.SECONDS_FORMAT, 1.0);
40+
} else if (parameters.size() == 2) {
41+
return new TimeOffsetPV(name, parameters.get(0), TimestampFormats.SECONDS_FORMAT, Double.valueOf(parameters.get(1)));
42+
} else if (parameters.size() == 3) {
43+
DateTimeFormatter formatter;
44+
switch (parameters.get(1).toLowerCase()) {
45+
case "full":
46+
formatter = TimestampFormats.FULL_FORMAT;
47+
break;
48+
case "milli":
49+
formatter = TimestampFormats.MILLI_FORMAT;
50+
break;
51+
case "seconds":
52+
formatter = TimestampFormats.SECONDS_FORMAT;
53+
break;
54+
case "datetime":
55+
formatter = TimestampFormats.DATETIME_FORMAT;
56+
break;
57+
case "date":
58+
formatter = TimestampFormats.DATE_FORMAT;
59+
break;
60+
case "time":
61+
formatter = TimestampFormats.TIME_FORMAT;
62+
break;
63+
default:
64+
formatter = TimestampFormats.SECONDS_FORMAT;
65+
break;
66+
}
67+
return new TimeOffsetPV(name, parameters.get(0), formatter, Double.valueOf(parameters.get(2)));
68+
}
69+
} else {
70+
return new TimeOffsetPV(name, "now", TimestampFormats.SECONDS_FORMAT, 1.0);
71+
}
72+
throw new Exception("sim://timeOffset needs no parameters or (offset, update_seconds) or (offset, format, update_seconds)");
73+
}
74+
75+
public TimeOffsetPV(final String name, final String offset, final DateTimeFormatter formatter, final double updateRate) {
76+
super(name);
77+
this.temporalAmount = TimeParser.parseTemporalAmount(offset);
78+
this.formatter = formatter;
79+
this.updateRate = updateRate;
80+
start(updateRate);
81+
}
82+
83+
@Override
84+
public String compute()
85+
{
86+
return formatter.format(Instant.now().minus(temporalAmount));
87+
}
88+
}

0 commit comments

Comments
 (0)