epicsdev 3.1.2__tar.gz → 3.1.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {epicsdev-3.1.2 → epicsdev-3.1.3}/PKG-INFO +30 -45
- {epicsdev-3.1.2 → epicsdev-3.1.3}/README.md +29 -44
- epicsdev-3.1.3/docs/modules.md +45 -0
- epicsdev-3.1.3/epicsdev/__init__.py +8 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/epicsdev/epicsdev.py +36 -15
- epicsdev-3.1.3/epicsdev/putlog.py +70 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/pyproject.toml +1 -1
- epicsdev-3.1.2/epicsdev/__init__.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/.github/copilot-instructions.md +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/LICENSE +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/config/epicsSimscope_pp.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/config/epicsdev.bob +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/config/epicsdev_pp.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/config/multiadc1_pp.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/config/multiadc_pp.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/docs/epicsdev_pvplot.jpg +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/docs/epicsdev_pypet.png +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/docs/phoebus_epicsdev.jpg +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/epicsdev/multiadc.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/fallback/epicsdev-300.py +0 -0
- {epicsdev-3.1.2 → epicsdev-3.1.3}/fallback/multiadc.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: epicsdev
|
|
3
|
-
Version: 3.1.
|
|
3
|
+
Version: 3.1.3
|
|
4
4
|
Summary: Helper module for creating EPICS PVAccess servers using p4p
|
|
5
5
|
Project-URL: Homepage, https://github.com/ASukhanov/epicsdev
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/ASukhanov/epicsdev
|
|
@@ -22,13 +22,13 @@ Helper module for building **EPICS PVAccess servers** using [p4p](https://github
|
|
|
22
22
|
* Rapid PVAccess server development
|
|
23
23
|
* High-rate data simulation and stress testing
|
|
24
24
|
* GUI-based monitoring and control
|
|
25
|
+
* Rapid instrument integration
|
|
25
26
|
* AI-assisted automatic device support generation
|
|
26
27
|
|
|
27
28
|
It integrates following EPICS IOC services:<br>
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
|
|
29
|
+
* **Autosave**: automatically saves the values of EPICS process variables (PVs) to files on a server host, and restores those values when the server restarts.
|
|
30
|
+
* **IocStats**: provides support for PVs that show the health and status of the server, plus a few control PVs.
|
|
31
|
+
* **caPutLog**: logging of PVAccess **`put`** operations.
|
|
32
32
|
---
|
|
33
33
|
|
|
34
34
|
## Installation
|
|
@@ -36,9 +36,6 @@ It integrates following EPICS IOC services:<br>
|
|
|
36
36
|
```bash
|
|
37
37
|
python -m pip install epicsdev
|
|
38
38
|
```
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
39
|
## Quick Demo
|
|
43
40
|
|
|
44
41
|
Start the demo PVAccess server:
|
|
@@ -46,10 +43,7 @@ Start the demo PVAccess server:
|
|
|
46
43
|
```bash
|
|
47
44
|
python -m epicsdev.epicsdev
|
|
48
45
|
```
|
|
49
|
-
|
|
50
|
-
---
|
|
51
|
-
|
|
52
|
-
## Control & Visualization
|
|
46
|
+
### Control & Visualization
|
|
53
47
|
|
|
54
48
|
Install optional GUI and plotting tools:
|
|
55
49
|
|
|
@@ -69,52 +63,53 @@ This provides:
|
|
|
69
63
|
* Live waveform plots
|
|
70
64
|
* Real-time parameter monitoring
|
|
71
65
|
|
|
72
|
-
|
|
66
|
+
The screenshots can be seen here: [control page](docs/epicsdev_pypet.png), [plots](docs/epicsdev_pvplot.jpg).
|
|
73
67
|
|
|
74
|
-
|
|
68
|
+
### Phoebus Display
|
|
75
69
|
|
|
76
|
-
|
|
70
|
+
An example Phoebus display is provided: `config/epicsdev.bob`. [Screenshot](docs/phoebus_epicsdev.jpg).
|
|
71
|
+
|
|
72
|
+
## Multi-Channel Waveform Generator
|
|
77
73
|
|
|
78
|
-
|
|
74
|
+
`epicsdev.multiadc` generates high-throughput synthetic data for stress-testing EPICS systems.
|
|
79
75
|
|
|
80
|
-
|
|
76
|
+
For example, the following command :
|
|
77
|
+
```bash
|
|
78
|
+
python -m epicsdev.multiadc -s 0.1 -c 10000 -n 100
|
|
79
|
+
```
|
|
80
|
+
Will start a server, which generates:
|
|
81
81
|
|
|
82
82
|
* **10,000** noisy waveforms per second
|
|
83
83
|
* **100 points per waveform**
|
|
84
84
|
* **40,000 scalar parameters per second**
|
|
85
85
|
|
|
86
|
-
```bash
|
|
87
|
-
python -m epicsdev.multiadc -s 0.1 -c 10000 -n 100
|
|
88
|
-
```
|
|
89
86
|
|
|
90
87
|
### Monitoring GUI
|
|
91
88
|
|
|
92
89
|
```bash
|
|
93
90
|
python -m pypeto -c config -f multiadc
|
|
94
91
|
```
|
|
92
|
+
## Text Put Logger
|
|
95
93
|
|
|
96
|
-
|
|
94
|
+
`epicsdev.putlog` hosts a writable PV named `dump` and appends any written text to a file.
|
|
97
95
|
|
|
98
|
-
|
|
99
|
-
* Real-time waveform plots<br>
|
|
100
|
-
The screenshots can be seen here: [control page](docs/epicsdev_pypet.png), [plots](docs/epicsdev_pvplot.jpg).
|
|
101
|
-
---
|
|
96
|
+
Start the logger server (required argument: output file path):
|
|
102
97
|
|
|
103
|
-
|
|
98
|
+
```bash
|
|
99
|
+
python -m epicsdev.putlog /tmp/putlog.txt
|
|
100
|
+
```
|
|
104
101
|
|
|
105
|
-
|
|
102
|
+
Default PV prefix is `putlog0:`, so write text to:
|
|
106
103
|
|
|
107
|
-
```
|
|
108
|
-
|
|
104
|
+
```bash
|
|
105
|
+
caput -p pva putlog0:dump "hello from client"
|
|
109
106
|
```
|
|
110
107
|
---
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
# AI-Assisted Device Support Development
|
|
108
|
+
## AI-Assisted Device Support Development
|
|
114
109
|
|
|
115
110
|
`epicsdev` is structured to enable automated server generation using AI tools such as GitHub Copilot.
|
|
116
111
|
|
|
117
|
-
|
|
112
|
+
### Workflow Example
|
|
118
113
|
|
|
119
114
|
1. Create a new GitHub repository.
|
|
120
115
|
|
|
@@ -132,24 +127,14 @@ config/epicsdev.bob<br>
|
|
|
132
127
|
|
|
133
128
|
### Real-World Example
|
|
134
129
|
|
|
135
|
-
Using this method, a server implementation for
|
|
130
|
+
Using this method, a server implementation for [Tektronix MSO oscilloscopes](https://github.com/ASukhanov/epicsdev_tektronix) was:
|
|
136
131
|
|
|
137
132
|
* ~99% correct on first generation
|
|
138
133
|
* Required only minor adjustments
|
|
139
134
|
|
|
140
135
|
---
|
|
141
136
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
* EPICS PVAccess server prototyping
|
|
145
|
-
* High-rate data simulation
|
|
146
|
-
* Control system stress testing
|
|
147
|
-
* Rapid instrument integration
|
|
148
|
-
* AI-driven device support generation
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
# Requirements
|
|
137
|
+
## Requirements
|
|
153
138
|
|
|
154
139
|
* Python 3.8+
|
|
155
140
|
* p4p 4.2.2+
|
|
@@ -7,13 +7,13 @@ Helper module for building **EPICS PVAccess servers** using [p4p](https://github
|
|
|
7
7
|
* Rapid PVAccess server development
|
|
8
8
|
* High-rate data simulation and stress testing
|
|
9
9
|
* GUI-based monitoring and control
|
|
10
|
+
* Rapid instrument integration
|
|
10
11
|
* AI-assisted automatic device support generation
|
|
11
12
|
|
|
12
13
|
It integrates following EPICS IOC services:<br>
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
|
|
14
|
+
* **Autosave**: automatically saves the values of EPICS process variables (PVs) to files on a server host, and restores those values when the server restarts.
|
|
15
|
+
* **IocStats**: provides support for PVs that show the health and status of the server, plus a few control PVs.
|
|
16
|
+
* **caPutLog**: logging of PVAccess **`put`** operations.
|
|
17
17
|
---
|
|
18
18
|
|
|
19
19
|
## Installation
|
|
@@ -21,9 +21,6 @@ It integrates following EPICS IOC services:<br>
|
|
|
21
21
|
```bash
|
|
22
22
|
python -m pip install epicsdev
|
|
23
23
|
```
|
|
24
|
-
|
|
25
|
-
---
|
|
26
|
-
|
|
27
24
|
## Quick Demo
|
|
28
25
|
|
|
29
26
|
Start the demo PVAccess server:
|
|
@@ -31,10 +28,7 @@ Start the demo PVAccess server:
|
|
|
31
28
|
```bash
|
|
32
29
|
python -m epicsdev.epicsdev
|
|
33
30
|
```
|
|
34
|
-
|
|
35
|
-
---
|
|
36
|
-
|
|
37
|
-
## Control & Visualization
|
|
31
|
+
### Control & Visualization
|
|
38
32
|
|
|
39
33
|
Install optional GUI and plotting tools:
|
|
40
34
|
|
|
@@ -54,52 +48,53 @@ This provides:
|
|
|
54
48
|
* Live waveform plots
|
|
55
49
|
* Real-time parameter monitoring
|
|
56
50
|
|
|
57
|
-
|
|
51
|
+
The screenshots can be seen here: [control page](docs/epicsdev_pypet.png), [plots](docs/epicsdev_pvplot.jpg).
|
|
58
52
|
|
|
59
|
-
|
|
53
|
+
### Phoebus Display
|
|
60
54
|
|
|
61
|
-
|
|
55
|
+
An example Phoebus display is provided: `config/epicsdev.bob`. [Screenshot](docs/phoebus_epicsdev.jpg).
|
|
56
|
+
|
|
57
|
+
## Multi-Channel Waveform Generator
|
|
62
58
|
|
|
63
|
-
|
|
59
|
+
`epicsdev.multiadc` generates high-throughput synthetic data for stress-testing EPICS systems.
|
|
64
60
|
|
|
65
|
-
|
|
61
|
+
For example, the following command :
|
|
62
|
+
```bash
|
|
63
|
+
python -m epicsdev.multiadc -s 0.1 -c 10000 -n 100
|
|
64
|
+
```
|
|
65
|
+
Will start a server, which generates:
|
|
66
66
|
|
|
67
67
|
* **10,000** noisy waveforms per second
|
|
68
68
|
* **100 points per waveform**
|
|
69
69
|
* **40,000 scalar parameters per second**
|
|
70
70
|
|
|
71
|
-
```bash
|
|
72
|
-
python -m epicsdev.multiadc -s 0.1 -c 10000 -n 100
|
|
73
|
-
```
|
|
74
71
|
|
|
75
72
|
### Monitoring GUI
|
|
76
73
|
|
|
77
74
|
```bash
|
|
78
75
|
python -m pypeto -c config -f multiadc
|
|
79
76
|
```
|
|
77
|
+
## Text Put Logger
|
|
80
78
|
|
|
81
|
-
|
|
79
|
+
`epicsdev.putlog` hosts a writable PV named `dump` and appends any written text to a file.
|
|
82
80
|
|
|
83
|
-
|
|
84
|
-
* Real-time waveform plots<br>
|
|
85
|
-
The screenshots can be seen here: [control page](docs/epicsdev_pypet.png), [plots](docs/epicsdev_pvplot.jpg).
|
|
86
|
-
---
|
|
81
|
+
Start the logger server (required argument: output file path):
|
|
87
82
|
|
|
88
|
-
|
|
83
|
+
```bash
|
|
84
|
+
python -m epicsdev.putlog /tmp/putlog.txt
|
|
85
|
+
```
|
|
89
86
|
|
|
90
|
-
|
|
87
|
+
Default PV prefix is `putlog0:`, so write text to:
|
|
91
88
|
|
|
92
|
-
```
|
|
93
|
-
|
|
89
|
+
```bash
|
|
90
|
+
caput -p pva putlog0:dump "hello from client"
|
|
94
91
|
```
|
|
95
92
|
---
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
# AI-Assisted Device Support Development
|
|
93
|
+
## AI-Assisted Device Support Development
|
|
99
94
|
|
|
100
95
|
`epicsdev` is structured to enable automated server generation using AI tools such as GitHub Copilot.
|
|
101
96
|
|
|
102
|
-
|
|
97
|
+
### Workflow Example
|
|
103
98
|
|
|
104
99
|
1. Create a new GitHub repository.
|
|
105
100
|
|
|
@@ -117,24 +112,14 @@ config/epicsdev.bob<br>
|
|
|
117
112
|
|
|
118
113
|
### Real-World Example
|
|
119
114
|
|
|
120
|
-
Using this method, a server implementation for
|
|
115
|
+
Using this method, a server implementation for [Tektronix MSO oscilloscopes](https://github.com/ASukhanov/epicsdev_tektronix) was:
|
|
121
116
|
|
|
122
117
|
* ~99% correct on first generation
|
|
123
118
|
* Required only minor adjustments
|
|
124
119
|
|
|
125
120
|
---
|
|
126
121
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
* EPICS PVAccess server prototyping
|
|
130
|
-
* High-rate data simulation
|
|
131
|
-
* Control system stress testing
|
|
132
|
-
* Rapid instrument integration
|
|
133
|
-
* AI-driven device support generation
|
|
134
|
-
|
|
135
|
-
---
|
|
136
|
-
|
|
137
|
-
# Requirements
|
|
122
|
+
## Requirements
|
|
138
123
|
|
|
139
124
|
* Python 3.8+
|
|
140
125
|
* p4p 4.2.2+
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Runnable Modules
|
|
2
|
+
|
|
3
|
+
This page lists the main runnable programs in `epicsdev`.
|
|
4
|
+
|
|
5
|
+
## `epicsdev.epicsdev`
|
|
6
|
+
|
|
7
|
+
Generic/demo PVAccess server framework.
|
|
8
|
+
|
|
9
|
+
Run:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
python -m epicsdev.epicsdev
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## `epicsdev.multiadc`
|
|
16
|
+
|
|
17
|
+
Multi-channel waveform generator for load and stress testing.
|
|
18
|
+
|
|
19
|
+
Run:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python -m epicsdev.multiadc
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## `epicsdev.putlog`
|
|
26
|
+
|
|
27
|
+
Hosts writable PV `dump`; every value written to it is appended to a file.
|
|
28
|
+
|
|
29
|
+
Run:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
python -m epicsdev.putlog /tmp/putlog.txt
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Default writable PV name:
|
|
36
|
+
|
|
37
|
+
```text
|
|
38
|
+
putlog0:dump
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Example write:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
caput -p pva putlog0:dump "hello from client"
|
|
45
|
+
```
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Helper functions for creating EPICS PVAccess server"""
|
|
2
2
|
# pylint: disable=invalid-name
|
|
3
|
-
__version__= 'v3.1.
|
|
3
|
+
__version__= 'v3.1.3 26-03-04'# putlog functionality added, some refactoring, new features of epicsdev v3.1.0 used, some bugs fixed.
|
|
4
4
|
# SPV removed, PvDefs definitions simplified, new features added.
|
|
5
5
|
#TODO: add support for autosave, (feature 'A'), caputLog (feature 'H') and access rights
|
|
6
6
|
|
|
7
7
|
import sys
|
|
8
8
|
import time
|
|
9
9
|
from time import perf_counter as timer
|
|
10
|
+
from datetime import datetime
|
|
10
11
|
import os
|
|
11
12
|
#import shelve
|
|
12
13
|
import json
|
|
@@ -23,6 +24,7 @@ PeriodicUpdateInterval = 10. # seconds
|
|
|
23
24
|
AutosaveInterval = 10. #
|
|
24
25
|
AutosaveDefaultDirectory = '/operations/app_store/pvCache/' # Directory to save
|
|
25
26
|
# autosave files. The actual file name will be <directory><prefix>.cache
|
|
27
|
+
IFace = Context('pva')# client context for getting values from other servers
|
|
26
28
|
|
|
27
29
|
dtype2p4p = {# mapping from numpy dtype to p4p type code
|
|
28
30
|
's8':'b', 'u8':'B', 's16':'h', 'u16':'H', 'i32':'i', 'u32':'I', 'i64':'l',
|
|
@@ -51,6 +53,7 @@ class C_():
|
|
|
51
53
|
cachefd = None
|
|
52
54
|
lastPutTime = time.time()# last time when a put operation was performed.
|
|
53
55
|
lastAutosaveTime = 0.# last time when the cache was saved to a file.
|
|
56
|
+
putlogPV = None # name of the PV where put operations are logged. If None, then put operations are not logged.
|
|
54
57
|
|
|
55
58
|
#```````````````````Helper methods````````````````````````````````````````````
|
|
56
59
|
def serverState():
|
|
@@ -223,16 +226,17 @@ def create_PVs(pvDefs, pvcache=None):
|
|
|
223
226
|
spv.name = pname
|
|
224
227
|
spv.setter = extra.get('setter')
|
|
225
228
|
|
|
226
|
-
# add put handler
|
|
229
|
+
# add a put handler
|
|
227
230
|
@spv.put
|
|
228
231
|
def handle(spv, op):
|
|
229
232
|
vv = op.value()
|
|
230
233
|
vr = vv.raw.value
|
|
231
234
|
ntNamedTuples = spv._wrap(spv.current())
|
|
235
|
+
oldvr = ntNamedTuples['value']
|
|
232
236
|
#print(f'Put request for {spv.name} = {repr(vv)}, current value: {repr(ntNamedTuples)}')
|
|
233
237
|
# check limits, if they are defined. That will be a good
|
|
234
238
|
# example of using control structure and valueAlarm.
|
|
235
|
-
|
|
239
|
+
#print(f'Put request for {spv.name} = {repr(vr)}, value: {ntNamedTuples["value"]}, peer: {op.name()}, {op.peer()}, {op.account()}, {op.roles()}')
|
|
236
240
|
try:
|
|
237
241
|
limitLow = ntNamedTuples['control.limitLow']
|
|
238
242
|
limitHigh = ntNamedTuples['control.limitHigh']
|
|
@@ -253,6 +257,19 @@ def create_PVs(pvDefs, pvcache=None):
|
|
|
253
257
|
ct = time.time()
|
|
254
258
|
C_.lastPutTime = ct
|
|
255
259
|
spv.post(vr, timestamp=ct) # update subscribers
|
|
260
|
+
|
|
261
|
+
if C_.putlogPV is not None:
|
|
262
|
+
dt = datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3].split()
|
|
263
|
+
ip = op.peer().split(':')[3][:-1]# peer looks like: [::ffff:192.168.27.6]:46362
|
|
264
|
+
jmsg = {"date":dt[0], "time":dt[1],
|
|
265
|
+
"host":ip, "user":op.account(),
|
|
266
|
+
"pv":op.name(), "new":vr, "old":oldvr}
|
|
267
|
+
s = json.dumps(jmsg)
|
|
268
|
+
try:
|
|
269
|
+
IFace.put(C_.putlogPV, "'"+s+"'", timeout=0.5)# quote the string to avoid interpreting it as JSON
|
|
270
|
+
except TimeoutError:
|
|
271
|
+
printw(f'WARNING: caPutLog feature will be disabled: PV {C_.putlogPV} not accessible.')
|
|
272
|
+
C_.putlogPV = None
|
|
256
273
|
op.done()
|
|
257
274
|
#,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
|
258
275
|
#``````````````````Setters
|
|
@@ -343,14 +360,8 @@ def create_pvDefs(pvDefs=None, pvcache=None):
|
|
|
343
360
|
create_PVs(C_.PVDefs, pvcache)
|
|
344
361
|
return C_.PVs
|
|
345
362
|
|
|
346
|
-
def
|
|
347
|
-
|
|
348
|
-
server is already running, or to get values from other servers."""
|
|
349
|
-
ctxt = Context('pva')
|
|
350
|
-
return ctxt.get(pvName, timeout=timeout)
|
|
351
|
-
|
|
352
|
-
def init_epicsdev(prefix:str, pvDefs:list, verbose=0,
|
|
353
|
-
serverStateChanged=None, listDir=None, autosaveDir=None, recall = True):
|
|
363
|
+
def init_epicsdev(prefix:str, pvDefs:list, verbose=0, serverStateChanged=None,
|
|
364
|
+
listDir=None, autosaveDir=None, recall = True, putlogPV=None):
|
|
354
365
|
"""Initialize epicsdev with given prefix and PV definitions.
|
|
355
366
|
prefix is a string that will be prepended to all PV names. It should end with ':'.
|
|
356
367
|
pvDefs is a list of PV definitions, each definition is a list of 3 or 4 items:
|
|
@@ -386,7 +397,7 @@ def init_epicsdev(prefix:str, pvDefs:list, verbose=0,
|
|
|
386
397
|
if serverStateChanged is not None:# set custom serverStateChanged function
|
|
387
398
|
C_.serverStateChanged = serverStateChanged
|
|
388
399
|
try: # check if server is already running
|
|
389
|
-
host = repr(
|
|
400
|
+
host = repr(IFace.get(prefix+'HOSTNAME', timeout=0.5)).replace("'",'')
|
|
390
401
|
print(f'ERROR: Server for {prefix} already running at {host}. Exiting.')
|
|
391
402
|
sys.exit(1)
|
|
392
403
|
except TimeoutError:
|
|
@@ -430,6 +441,14 @@ def init_epicsdev(prefix:str, pvDefs:list, verbose=0,
|
|
|
430
441
|
printi(f'Hosting {len(pvs)} PVs')
|
|
431
442
|
C_.startTime = time.time()
|
|
432
443
|
|
|
444
|
+
try:
|
|
445
|
+
if putlogPV is not None:
|
|
446
|
+
_ = IFace.get(putlogPV, timeout=0.5)
|
|
447
|
+
C_.putlogPV = putlogPV
|
|
448
|
+
except TimeoutError:
|
|
449
|
+
printw(f'WARNING: caPutLog feature will not work: PV {putlogPV} not accessible.')
|
|
450
|
+
C_.putlogPV = None
|
|
451
|
+
|
|
433
452
|
threading.Thread(target=_heartbeat_thread, daemon=True).start()
|
|
434
453
|
return pvs
|
|
435
454
|
|
|
@@ -561,15 +580,17 @@ if __name__ == "__main__":
|
|
|
561
580
|
# The rest of options are not essential, they can be controlled at runtime using PVs.
|
|
562
581
|
parser.add_argument('-n', '--npoints', type=int, default=nPoints, help=
|
|
563
582
|
'Number of points in the waveform')
|
|
583
|
+
parser.add_argument('-p', '--putlogPV', default='putlog:dump', help=
|
|
584
|
+
'Name of the PV where put operations are logged. If None, then put operations are not logged.')
|
|
564
585
|
parser.add_argument('-v', '--verbose', action='count', default=0, help=
|
|
565
586
|
'Show more log messages (-vv: show even more)')
|
|
566
587
|
pargs = parser.parse_args()
|
|
567
|
-
|
|
588
|
+
print(pargs)
|
|
568
589
|
|
|
569
590
|
# Initialize epicsdev and PVs
|
|
570
591
|
pargs.prefix = f'{pargs.device}{pargs.index}:'
|
|
571
592
|
PVs = init_epicsdev(pargs.prefix, myPVDefs(), pargs.verbose, None,
|
|
572
|
-
|
|
593
|
+
pargs.list, pargs.autosave, pargs.recall, pargs.putlogPV)
|
|
573
594
|
# Initialize the device using pargs if needed.
|
|
574
595
|
init(pargs.npoints)
|
|
575
596
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""PVAccess text logger server: writes text from PV `dump` to a file."""
|
|
2
|
+
# pylint: disable=invalid-name
|
|
3
|
+
__version__= 'v0.0.2 26-03-04'
|
|
4
|
+
|
|
5
|
+
import argparse
|
|
6
|
+
import threading
|
|
7
|
+
|
|
8
|
+
from .epicsdev import Server, init_epicsdev, publish, printi, set_server, serverState, sleep
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class C_:
|
|
12
|
+
"""Module-local storage."""
|
|
13
|
+
logfile = None
|
|
14
|
+
server = None
|
|
15
|
+
lock = threading.Lock()
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def set_dump(value, *_):
|
|
19
|
+
"""Append text written to `dump` PV into the selected log file."""
|
|
20
|
+
text = str(value)
|
|
21
|
+
with C_.lock:
|
|
22
|
+
C_.logfile.write(text)
|
|
23
|
+
if not text.endswith("\n"):
|
|
24
|
+
C_.logfile.write("\n")
|
|
25
|
+
C_.logfile.flush()
|
|
26
|
+
publish('dump', text)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def myPVDefs():
|
|
30
|
+
"""PV definitions for putlog server."""
|
|
31
|
+
F = 'features'
|
|
32
|
+
T = 'type'
|
|
33
|
+
SET = 'setter'
|
|
34
|
+
return [
|
|
35
|
+
['dump', 'Text to append to log file', '', {F: 'W', T: str, SET: set_dump}],
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def main():
|
|
40
|
+
"""Program entry point."""
|
|
41
|
+
parser = argparse.ArgumentParser(
|
|
42
|
+
description=__doc__,
|
|
43
|
+
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
|
44
|
+
)
|
|
45
|
+
parser.add_argument('logfile', nargs='?', default='/tmp/putlog.log', help=
|
|
46
|
+
'Path to file where text written to the dump PV is appended.')
|
|
47
|
+
parser.add_argument('-p', '--prefix', default='putlog:', help='PV prefix')
|
|
48
|
+
parser.add_argument('-v', '--verbose', action='count', default=0, help=
|
|
49
|
+
'Show more log messages (-vv: more).')
|
|
50
|
+
pargs = parser.parse_args()
|
|
51
|
+
|
|
52
|
+
C_.logfile = open(pargs.logfile, 'a', encoding='utf-8')
|
|
53
|
+
|
|
54
|
+
pvs = init_epicsdev(pargs.prefix, myPVDefs(), pargs.verbose, listDir='')
|
|
55
|
+
|
|
56
|
+
set_server('Start')
|
|
57
|
+
|
|
58
|
+
C_.server = Server(providers=[pvs])
|
|
59
|
+
printi(f'Server started with prefix {pargs.prefix}, writing dump text to {pargs.logfile}')
|
|
60
|
+
try:
|
|
61
|
+
while True:
|
|
62
|
+
if serverState().startswith('Exit'):
|
|
63
|
+
break
|
|
64
|
+
sleep()
|
|
65
|
+
finally:
|
|
66
|
+
C_.logfile.close()
|
|
67
|
+
printi('Server has exited')
|
|
68
|
+
|
|
69
|
+
if __name__ == '__main__':
|
|
70
|
+
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|