SpecLog 0.0.3__tar.gz → 0.0.5__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.
- speclog-0.0.5/LICENSE +21 -0
- speclog-0.0.5/PKG-INFO +178 -0
- speclog-0.0.5/README.md +159 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/SpecLog.py +27 -44
- speclog-0.0.5/SpecLog/SpecLogger.py +199 -0
- speclog-0.0.5/SpecLog/SpecMonitor.py +58 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/config/config.cfg +3 -1
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/config/config.py +15 -11
- speclog-0.0.5/SpecLog/config_editor.py +818 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/debugLog.py +11 -0
- speclog-0.0.5/SpecLog/device.py +334 -0
- speclog-0.0.5/SpecLog/history.py +195 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/loggerConfig.py +47 -7
- speclog-0.0.5/SpecLog/logger_status.py +32 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/monitor.py +426 -204
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/run_logger.pyw +25 -12
- speclog-0.0.5/SpecLog/run_monitor.pyw +39 -0
- speclog-0.0.5/SpecLog/startup_task.py +62 -0
- speclog-0.0.5/SpecLog/ui/config_editor.py +251 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/ui/plotting.py +69 -38
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/ui/plotting.ui +83 -57
- speclog-0.0.5/SpecLog/version.py +1 -0
- speclog-0.0.5/SpecLog.egg-info/PKG-INFO +178 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog.egg-info/SOURCES.txt +9 -1
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog.egg-info/entry_points.txt +2 -2
- {speclog-0.0.3 → speclog-0.0.5}/pyproject.toml +4 -4
- speclog-0.0.5/tests/test_core.py +484 -0
- speclog-0.0.3/PKG-INFO +0 -19
- speclog-0.0.3/README.md +0 -2
- speclog-0.0.3/SpecLog/SpecLogger.py +0 -128
- speclog-0.0.3/SpecLog/device.py +0 -156
- speclog-0.0.3/SpecLog/run_monitor.pyw +0 -27
- speclog-0.0.3/SpecLog/version.py +0 -1
- speclog-0.0.3/SpecLog.egg-info/PKG-INFO +0 -19
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/__init__.py +0 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/config/__init__.py +0 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog/ui/__init__.py +0 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog.egg-info/dependency_links.txt +0 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog.egg-info/requires.txt +0 -0
- {speclog-0.0.3 → speclog-0.0.5}/SpecLog.egg-info/top_level.txt +0 -0
- {speclog-0.0.3 → speclog-0.0.5}/setup.cfg +0 -0
speclog-0.0.5/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Yen-Chun Huang
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
speclog-0.0.5/PKG-INFO
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: SpecLog
|
|
3
|
+
Version: 0.0.5
|
|
4
|
+
Summary: A Python Package for logging data from instrumentations
|
|
5
|
+
Author-email: Yen-Chun Huang <yen-chun.huang@bruker.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
9
|
+
Requires-Python: >=3.10
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: matplotlib>=3.7.1
|
|
13
|
+
Requires-Dist: numpy>=1.24.3
|
|
14
|
+
Requires-Dist: PySide6>=6.9.0
|
|
15
|
+
Requires-Dist: pyqtgraph>=0.13.3
|
|
16
|
+
Requires-Dist: spinlab>=1.1.3
|
|
17
|
+
Requires-Dist: pyserial>=3.5
|
|
18
|
+
Dynamic: license-file
|
|
19
|
+
|
|
20
|
+
# SpecLog
|
|
21
|
+
|
|
22
|
+
SpecLog records data from connected spectrometer instruments and provides a
|
|
23
|
+
desktop monitor for viewing live and historical measurements.
|
|
24
|
+
|
|
25
|
+
## Quick start
|
|
26
|
+
|
|
27
|
+
Start the logger:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
SpecLogger
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Open the monitor:
|
|
34
|
+
|
|
35
|
+
```text
|
|
36
|
+
SpecMonitor
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Keep the logger running while using the monitor. The logger collects and saves
|
|
40
|
+
instrument data; the monitor reads and displays those saved measurements.
|
|
41
|
+
|
|
42
|
+
## Configure SpecLog
|
|
43
|
+
|
|
44
|
+
Open the configuration editor:
|
|
45
|
+
|
|
46
|
+
```text
|
|
47
|
+
SpecLogger --config
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
The shared configuration is saved at:
|
|
51
|
+
|
|
52
|
+
```text
|
|
53
|
+
C:\Users\Public\LOG_Config\config.cfg
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Use the section list on the left to select global settings or a device.
|
|
57
|
+
|
|
58
|
+
### Global settings
|
|
59
|
+
|
|
60
|
+
The **SETTINGS** section contains options such as:
|
|
61
|
+
|
|
62
|
+
- Logging interval
|
|
63
|
+
- Log-folder location
|
|
64
|
+
- Maximum log-file size
|
|
65
|
+
|
|
66
|
+
### Device communication
|
|
67
|
+
|
|
68
|
+
For each device, use the **Communication** tab to configure its connection:
|
|
69
|
+
|
|
70
|
+
- Enable or disable the device
|
|
71
|
+
- Protocol
|
|
72
|
+
- Address or COM port
|
|
73
|
+
- Baud rate
|
|
74
|
+
- Termination
|
|
75
|
+
- Other serial communication attributes
|
|
76
|
+
|
|
77
|
+
### Device commands
|
|
78
|
+
|
|
79
|
+
Use **Commands > Values** for ordinary measurements. Each command can contain:
|
|
80
|
+
|
|
81
|
+
- Variable name
|
|
82
|
+
- Instrument command
|
|
83
|
+
- Display alias
|
|
84
|
+
- Minimum and maximum limits
|
|
85
|
+
- Expected static value
|
|
86
|
+
|
|
87
|
+
Use **Commands > Status Indicators** for commands that return status bits.
|
|
88
|
+
Click the indicators button to add, remove, reorder, or reverse individual
|
|
89
|
+
indicators. The editor calculates `bits` and `bit_static` automatically.
|
|
90
|
+
|
|
91
|
+
Click **Save** after making changes. The editor validates the configuration and
|
|
92
|
+
keeps the previous file as `config.cfg.bak`. Restart the logger and monitor to
|
|
93
|
+
apply the updated configuration.
|
|
94
|
+
|
|
95
|
+
## Control the logger
|
|
96
|
+
|
|
97
|
+
Start or stop the logger from a terminal:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
SpecLogger start
|
|
101
|
+
SpecLogger stop
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
You can also use **Start** and **Stop** at the bottom of the configuration
|
|
105
|
+
editor. Current status is shown as **Running**, **Stopped**, or **Status
|
|
106
|
+
unavailable**. Operation results and errors appear in the **Messages** area.
|
|
107
|
+
|
|
108
|
+
For troubleshooting, start the logger with a visible debug console:
|
|
109
|
+
|
|
110
|
+
```text
|
|
111
|
+
SpecLogger -debug True
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Start logging automatically without login
|
|
115
|
+
|
|
116
|
+
Open a terminal as Administrator and enable system startup:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
SpecLogger -startup True
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The logger will start automatically after the next computer boot. A 30-second
|
|
123
|
+
delay allows USB and serial drivers to initialize first.
|
|
124
|
+
|
|
125
|
+
To run it immediately without rebooting:
|
|
126
|
+
|
|
127
|
+
```text
|
|
128
|
+
SpecLogger start
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Disable automatic startup from an Administrator terminal:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
SpecLogger -startup False
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
The configuration editor also provides **Enable** and **Disable** startup
|
|
138
|
+
buttons. Administrator permission is normally required to use them.
|
|
139
|
+
|
|
140
|
+
If the startup task was created by another administrator, a standard account
|
|
141
|
+
may show startup as **Unavailable**. If new log data is still being written, the
|
|
142
|
+
logger status displays **Running (log activity)**. Start and Stop remain disabled
|
|
143
|
+
until the editor is opened with sufficient permission.
|
|
144
|
+
|
|
145
|
+
## Use the monitor
|
|
146
|
+
|
|
147
|
+
Open the monitor normally:
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
SpecMonitor
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Use the monitoring-item controls to select which measurements are plotted. Use
|
|
154
|
+
the data-selection controls to choose a start time and duration.
|
|
155
|
+
|
|
156
|
+
To load all available history, leave the date fields at their defaults and click
|
|
157
|
+
**Ok**. The first import may take longer; later queries load only new or changed
|
|
158
|
+
files.
|
|
159
|
+
|
|
160
|
+
Start the monitor with a visible debug console when troubleshooting:
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
SpecMonitor -debug True
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
## Common status messages
|
|
167
|
+
|
|
168
|
+
- **Running**: The logger is active and directly detectable.
|
|
169
|
+
- **Running (log activity)**: New data confirms that the logger is active, but
|
|
170
|
+
the current Windows account cannot query the system startup task.
|
|
171
|
+
- **Stopped**: The logger is not running.
|
|
172
|
+
- **Status unavailable**: The current account cannot verify the logger state and
|
|
173
|
+
no recent log activity was detected.
|
|
174
|
+
- **Startup Enabled**: Automatic logging is configured for system boot.
|
|
175
|
+
- **Startup Disabled**: The startup task exists but automatic boot startup is
|
|
176
|
+
disabled.
|
|
177
|
+
- **Startup Unavailable**: Open the configuration editor as Administrator to
|
|
178
|
+
inspect or control a task created by another administrator.
|
speclog-0.0.5/README.md
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
# SpecLog
|
|
2
|
+
|
|
3
|
+
SpecLog records data from connected spectrometer instruments and provides a
|
|
4
|
+
desktop monitor for viewing live and historical measurements.
|
|
5
|
+
|
|
6
|
+
## Quick start
|
|
7
|
+
|
|
8
|
+
Start the logger:
|
|
9
|
+
|
|
10
|
+
```text
|
|
11
|
+
SpecLogger
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Open the monitor:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
SpecMonitor
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Keep the logger running while using the monitor. The logger collects and saves
|
|
21
|
+
instrument data; the monitor reads and displays those saved measurements.
|
|
22
|
+
|
|
23
|
+
## Configure SpecLog
|
|
24
|
+
|
|
25
|
+
Open the configuration editor:
|
|
26
|
+
|
|
27
|
+
```text
|
|
28
|
+
SpecLogger --config
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
The shared configuration is saved at:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
C:\Users\Public\LOG_Config\config.cfg
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Use the section list on the left to select global settings or a device.
|
|
38
|
+
|
|
39
|
+
### Global settings
|
|
40
|
+
|
|
41
|
+
The **SETTINGS** section contains options such as:
|
|
42
|
+
|
|
43
|
+
- Logging interval
|
|
44
|
+
- Log-folder location
|
|
45
|
+
- Maximum log-file size
|
|
46
|
+
|
|
47
|
+
### Device communication
|
|
48
|
+
|
|
49
|
+
For each device, use the **Communication** tab to configure its connection:
|
|
50
|
+
|
|
51
|
+
- Enable or disable the device
|
|
52
|
+
- Protocol
|
|
53
|
+
- Address or COM port
|
|
54
|
+
- Baud rate
|
|
55
|
+
- Termination
|
|
56
|
+
- Other serial communication attributes
|
|
57
|
+
|
|
58
|
+
### Device commands
|
|
59
|
+
|
|
60
|
+
Use **Commands > Values** for ordinary measurements. Each command can contain:
|
|
61
|
+
|
|
62
|
+
- Variable name
|
|
63
|
+
- Instrument command
|
|
64
|
+
- Display alias
|
|
65
|
+
- Minimum and maximum limits
|
|
66
|
+
- Expected static value
|
|
67
|
+
|
|
68
|
+
Use **Commands > Status Indicators** for commands that return status bits.
|
|
69
|
+
Click the indicators button to add, remove, reorder, or reverse individual
|
|
70
|
+
indicators. The editor calculates `bits` and `bit_static` automatically.
|
|
71
|
+
|
|
72
|
+
Click **Save** after making changes. The editor validates the configuration and
|
|
73
|
+
keeps the previous file as `config.cfg.bak`. Restart the logger and monitor to
|
|
74
|
+
apply the updated configuration.
|
|
75
|
+
|
|
76
|
+
## Control the logger
|
|
77
|
+
|
|
78
|
+
Start or stop the logger from a terminal:
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
SpecLogger start
|
|
82
|
+
SpecLogger stop
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
You can also use **Start** and **Stop** at the bottom of the configuration
|
|
86
|
+
editor. Current status is shown as **Running**, **Stopped**, or **Status
|
|
87
|
+
unavailable**. Operation results and errors appear in the **Messages** area.
|
|
88
|
+
|
|
89
|
+
For troubleshooting, start the logger with a visible debug console:
|
|
90
|
+
|
|
91
|
+
```text
|
|
92
|
+
SpecLogger -debug True
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Start logging automatically without login
|
|
96
|
+
|
|
97
|
+
Open a terminal as Administrator and enable system startup:
|
|
98
|
+
|
|
99
|
+
```text
|
|
100
|
+
SpecLogger -startup True
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
The logger will start automatically after the next computer boot. A 30-second
|
|
104
|
+
delay allows USB and serial drivers to initialize first.
|
|
105
|
+
|
|
106
|
+
To run it immediately without rebooting:
|
|
107
|
+
|
|
108
|
+
```text
|
|
109
|
+
SpecLogger start
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Disable automatic startup from an Administrator terminal:
|
|
113
|
+
|
|
114
|
+
```text
|
|
115
|
+
SpecLogger -startup False
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The configuration editor also provides **Enable** and **Disable** startup
|
|
119
|
+
buttons. Administrator permission is normally required to use them.
|
|
120
|
+
|
|
121
|
+
If the startup task was created by another administrator, a standard account
|
|
122
|
+
may show startup as **Unavailable**. If new log data is still being written, the
|
|
123
|
+
logger status displays **Running (log activity)**. Start and Stop remain disabled
|
|
124
|
+
until the editor is opened with sufficient permission.
|
|
125
|
+
|
|
126
|
+
## Use the monitor
|
|
127
|
+
|
|
128
|
+
Open the monitor normally:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
SpecMonitor
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
Use the monitoring-item controls to select which measurements are plotted. Use
|
|
135
|
+
the data-selection controls to choose a start time and duration.
|
|
136
|
+
|
|
137
|
+
To load all available history, leave the date fields at their defaults and click
|
|
138
|
+
**Ok**. The first import may take longer; later queries load only new or changed
|
|
139
|
+
files.
|
|
140
|
+
|
|
141
|
+
Start the monitor with a visible debug console when troubleshooting:
|
|
142
|
+
|
|
143
|
+
```text
|
|
144
|
+
SpecMonitor -debug True
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Common status messages
|
|
148
|
+
|
|
149
|
+
- **Running**: The logger is active and directly detectable.
|
|
150
|
+
- **Running (log activity)**: New data confirms that the logger is active, but
|
|
151
|
+
the current Windows account cannot query the system startup task.
|
|
152
|
+
- **Stopped**: The logger is not running.
|
|
153
|
+
- **Status unavailable**: The current account cannot verify the logger state and
|
|
154
|
+
no recent log activity was detected.
|
|
155
|
+
- **Startup Enabled**: Automatic logging is configured for system boot.
|
|
156
|
+
- **Startup Disabled**: The startup task exists but automatic boot startup is
|
|
157
|
+
disabled.
|
|
158
|
+
- **Startup Unavailable**: Open the configuration editor as Administrator to
|
|
159
|
+
inspect or control a task created by another administrator.
|
|
@@ -17,7 +17,7 @@ from .debugLog import *
|
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
class SpecLog:
|
|
20
|
-
def __init__(self, config_file: str = None):
|
|
20
|
+
def __init__(self, config_file: str = None, protocols=None):
|
|
21
21
|
self.config = loggerConfig(config_file)
|
|
22
22
|
self.debugLogger = debugLog(config_file).logger
|
|
23
23
|
self.settings = self.config.settings
|
|
@@ -25,6 +25,7 @@ class SpecLog:
|
|
|
25
25
|
self.config.commands
|
|
26
26
|
) # dictionary {model: {variable: {command, alias, min, max, static}}}
|
|
27
27
|
self.device_config = self.config.devices
|
|
28
|
+
self.protocols = protocols
|
|
28
29
|
|
|
29
30
|
self.log_dir = self.settings["log_folder_location"] + "/LOG/"
|
|
30
31
|
self._checkDirectory()
|
|
@@ -60,14 +61,12 @@ class SpecLog:
|
|
|
60
61
|
if not self.last_query_time or now - self.last_query_time > self.delay:
|
|
61
62
|
warning_level = 0
|
|
62
63
|
self._setTimeInDataDictByVariable() # update time
|
|
63
|
-
|
|
64
|
-
self.devices.
|
|
64
|
+
device_info = (
|
|
65
|
+
self.devices.device_info
|
|
65
66
|
) # dictionary: {model: {status, config_status, device, id_command}}
|
|
66
67
|
for name, info in self.commands.items():
|
|
67
68
|
delimiter = self.device_config[name]["delimiter"]
|
|
68
69
|
index = self.device_config[name]["index"]
|
|
69
|
-
device = devices_info[name]["device"]
|
|
70
|
-
termination = self.device_config[name]["termination"]
|
|
71
70
|
for variable in info.keys():
|
|
72
71
|
info[variable]['min'], info[variable]['max'], info[variable]['static']
|
|
73
72
|
if self.devices.checkDeviceStatus(
|
|
@@ -75,13 +74,12 @@ class SpecLog:
|
|
|
75
74
|
): # check the connection of a device
|
|
76
75
|
try:
|
|
77
76
|
command = info[variable]["command"]
|
|
78
|
-
|
|
79
|
-
data_string = device.read_until(termination.encode()).decode()
|
|
77
|
+
data_string = self.devices.query(name, command)
|
|
80
78
|
data = self._returnStringConverter(
|
|
81
79
|
data_string, delimiter, index
|
|
82
80
|
)
|
|
83
81
|
except Exception as err:
|
|
84
|
-
self.
|
|
82
|
+
self.debugLogger.error(err)
|
|
85
83
|
data = "nan"
|
|
86
84
|
|
|
87
85
|
else:
|
|
@@ -92,22 +90,25 @@ class SpecLog:
|
|
|
92
90
|
if data == "nan":
|
|
93
91
|
warning_level = 2
|
|
94
92
|
|
|
95
|
-
elif
|
|
93
|
+
elif (
|
|
94
|
+
info[variable]['static'] is not None
|
|
95
|
+
and float(data) != info[variable]['static']
|
|
96
|
+
):
|
|
96
97
|
warning_level = 2
|
|
97
98
|
|
|
98
99
|
else:
|
|
99
|
-
if info[variable]['min']:
|
|
100
|
-
if float(data)
|
|
101
|
-
warning_level = max(warning_level, 1)
|
|
102
|
-
elif float(data) < info[variable]['min']:
|
|
100
|
+
if info[variable]['min'] is not None:
|
|
101
|
+
if float(data) < info[variable]['min']:
|
|
103
102
|
warning_level = 2
|
|
103
|
+
elif float(data) <= info[variable]['min'] * 1.05:
|
|
104
|
+
warning_level = max(warning_level, 1)
|
|
104
105
|
|
|
105
106
|
|
|
106
|
-
if info[variable]['max']:
|
|
107
|
-
if float(data)
|
|
108
|
-
warning_level = max(warning_level, 1)
|
|
109
|
-
elif float(data) > info[variable]['max']:
|
|
107
|
+
if info[variable]['max'] is not None:
|
|
108
|
+
if float(data) > info[variable]['max']:
|
|
110
109
|
warning_level = 2
|
|
110
|
+
elif float(data) >= info[variable]['max'] * 0.95:
|
|
111
|
+
warning_level = max(warning_level, 1)
|
|
111
112
|
self.warning = warning_level
|
|
112
113
|
|
|
113
114
|
self.last_query_time = now
|
|
@@ -122,37 +123,18 @@ class SpecLog:
|
|
|
122
123
|
"""
|
|
123
124
|
Call DEVICE
|
|
124
125
|
"""
|
|
125
|
-
self.devices = DEVICE(
|
|
126
|
+
self.devices = DEVICE(
|
|
127
|
+
self.config, self.debugLogger, protocols=self.protocols
|
|
128
|
+
) # establish communication
|
|
126
129
|
self.devices._getPorts()
|
|
127
130
|
self.available_addresses = self.devices.deviceAddresses
|
|
128
131
|
return True
|
|
129
132
|
|
|
130
133
|
def reconnectDevices(self):
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
address not in self.devices.deviceAddresses
|
|
138
|
-
and address in self.available_addresses
|
|
139
|
-
): # when a connection is loss
|
|
140
|
-
# This step is to prevent the moment when the device is shown in the resource manager but connection fails
|
|
141
|
-
self.available_addresses.remove(address)
|
|
142
|
-
|
|
143
|
-
if (
|
|
144
|
-
address in self.devices.deviceAddresses
|
|
145
|
-
and address not in self.available_addresses
|
|
146
|
-
and not self.devices.devices_info[name]["status"]
|
|
147
|
-
):
|
|
148
|
-
restart_DEVICE = True
|
|
149
|
-
|
|
150
|
-
if restart_DEVICE:
|
|
151
|
-
del self.devices # delete the DEVICE class
|
|
152
|
-
return self.connectDevices()
|
|
153
|
-
|
|
154
|
-
else:
|
|
155
|
-
return False
|
|
134
|
+
return self.devices.reconnectDevices()
|
|
135
|
+
|
|
136
|
+
def close(self):
|
|
137
|
+
self.devices.close()
|
|
156
138
|
|
|
157
139
|
def _checkDirectory(self):
|
|
158
140
|
if not os.path.exists(self.log_dir):
|
|
@@ -249,6 +231,7 @@ class SpecLog:
|
|
|
249
231
|
Returns:
|
|
250
232
|
data (string): return data in str
|
|
251
233
|
"""
|
|
234
|
+
data = "nan"
|
|
252
235
|
try:
|
|
253
236
|
if delimiter:
|
|
254
237
|
data = string.split(delimiter)[index]
|
|
@@ -259,7 +242,7 @@ class SpecLog:
|
|
|
259
242
|
data = data.replace("\t", "")
|
|
260
243
|
data = data.replace("\r", "")
|
|
261
244
|
data = data.strip()
|
|
262
|
-
except:
|
|
245
|
+
except (IndexError, AttributeError):
|
|
263
246
|
self.debugLogger.error("String Convert Fail: recived: %s, delimiter: %s, index: %s" %(string, delimiter, index))
|
|
264
247
|
return data
|
|
265
248
|
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This is the python program to control SpecLog
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
import sys
|
|
7
|
+
import argparse
|
|
8
|
+
import shutil
|
|
9
|
+
import subprocess
|
|
10
|
+
from .SpecLog import *
|
|
11
|
+
from .logger_status import is_logger_running
|
|
12
|
+
from .startup_task import (
|
|
13
|
+
TASK_SCHEDULER,
|
|
14
|
+
control_arguments,
|
|
15
|
+
create_arguments,
|
|
16
|
+
disable_arguments,
|
|
17
|
+
query_arguments,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
# System-start task and desktop shortcuts (public)
|
|
21
|
+
desktop_folder = os.path.join(os.environ["USERPROFILE"], "Desktop")
|
|
22
|
+
|
|
23
|
+
source_running_logger = os.path.join(
|
|
24
|
+
os.path.dirname(sys.executable), "scripts", "SpecLogger_running.exe"
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
source_monitor = os.path.join(
|
|
28
|
+
os.path.dirname(sys.executable), "scripts", "SpecMonitor_running.exe"
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def _run_task_scheduler(arguments, runner=None):
|
|
33
|
+
runner = runner or subprocess.run
|
|
34
|
+
return runner(
|
|
35
|
+
[TASK_SCHEDULER, *arguments],
|
|
36
|
+
capture_output=True,
|
|
37
|
+
text=True,
|
|
38
|
+
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0),
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def configure_startup(enabled, executable=None, runner=None):
|
|
43
|
+
"""Create/enable or disable the no-login SpecLogger startup task."""
|
|
44
|
+
executable = os.path.abspath(executable or source_running_logger)
|
|
45
|
+
if enabled:
|
|
46
|
+
if not os.path.isfile(executable):
|
|
47
|
+
raise RuntimeError(f"SpecLogger runner was not found: {executable}")
|
|
48
|
+
result = _run_task_scheduler(
|
|
49
|
+
create_arguments(executable),
|
|
50
|
+
runner,
|
|
51
|
+
)
|
|
52
|
+
success_message = "SpecLogger will run at system startup without login."
|
|
53
|
+
else:
|
|
54
|
+
query = _run_task_scheduler(
|
|
55
|
+
query_arguments(), runner
|
|
56
|
+
)
|
|
57
|
+
if query.returncode:
|
|
58
|
+
return "SpecLogger startup task is not installed."
|
|
59
|
+
result = _run_task_scheduler(
|
|
60
|
+
disable_arguments(), runner
|
|
61
|
+
)
|
|
62
|
+
success_message = "SpecLogger startup task is disabled."
|
|
63
|
+
|
|
64
|
+
if result.returncode:
|
|
65
|
+
details = (result.stderr or result.stdout).strip()
|
|
66
|
+
raise RuntimeError(
|
|
67
|
+
details
|
|
68
|
+
or "Windows Task Scheduler rejected the request. Run as administrator."
|
|
69
|
+
)
|
|
70
|
+
return success_message
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def control_scheduled_logger(action, runner=None):
|
|
74
|
+
"""Start/stop the startup task, or return None when it is not installed."""
|
|
75
|
+
query = _run_task_scheduler(
|
|
76
|
+
query_arguments(), runner
|
|
77
|
+
)
|
|
78
|
+
if query.returncode:
|
|
79
|
+
return None
|
|
80
|
+
result = _run_task_scheduler(
|
|
81
|
+
control_arguments(action), runner
|
|
82
|
+
)
|
|
83
|
+
if result.returncode:
|
|
84
|
+
details = (result.stderr or result.stdout).strip()
|
|
85
|
+
raise RuntimeError(
|
|
86
|
+
details
|
|
87
|
+
or "Windows Task Scheduler rejected the request. Run as administrator."
|
|
88
|
+
)
|
|
89
|
+
return (
|
|
90
|
+
"SpecLogger scheduled task start requested."
|
|
91
|
+
if action == "start"
|
|
92
|
+
else "SpecLogger scheduled task stopped."
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
def _build_parser():
|
|
96
|
+
parser = argparse.ArgumentParser(prog="SpecLogger")
|
|
97
|
+
parser.add_argument(
|
|
98
|
+
"status",
|
|
99
|
+
type=str,
|
|
100
|
+
nargs="?",
|
|
101
|
+
default=None,
|
|
102
|
+
choices=["start", "stop"],
|
|
103
|
+
help="To start/stop SpecLogger. If no argument, the SpecLogger will start by default",
|
|
104
|
+
)
|
|
105
|
+
parser.add_argument(
|
|
106
|
+
"-desktop",
|
|
107
|
+
type=str,
|
|
108
|
+
default=False,
|
|
109
|
+
choices=["True", "False"],
|
|
110
|
+
help="To create desktop icons",
|
|
111
|
+
)
|
|
112
|
+
parser.add_argument(
|
|
113
|
+
"-startup",
|
|
114
|
+
type=str,
|
|
115
|
+
default=None,
|
|
116
|
+
choices=["True", "False"],
|
|
117
|
+
help="To enable/disable SpecLogger at startup without login.",
|
|
118
|
+
)
|
|
119
|
+
parser.add_argument(
|
|
120
|
+
"-debug",
|
|
121
|
+
type=str,
|
|
122
|
+
default="False",
|
|
123
|
+
choices=["True", "False"],
|
|
124
|
+
help="To start debug console SpecLogger.",
|
|
125
|
+
)
|
|
126
|
+
parser.add_argument(
|
|
127
|
+
"--config",
|
|
128
|
+
action="store_true",
|
|
129
|
+
help="Open the public SpecLog configuration editor.",
|
|
130
|
+
)
|
|
131
|
+
return parser
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def main_func(argv=None):
|
|
135
|
+
args = _build_parser().parse_args(argv)
|
|
136
|
+
|
|
137
|
+
if args.config:
|
|
138
|
+
from .config_editor import main_func as open_config_editor
|
|
139
|
+
|
|
140
|
+
return open_config_editor()
|
|
141
|
+
|
|
142
|
+
if args.startup is not None:
|
|
143
|
+
try:
|
|
144
|
+
print(configure_startup(args.startup == "True"))
|
|
145
|
+
except RuntimeError as error:
|
|
146
|
+
print(f"Could not configure SpecLogger startup: {error}", file=sys.stderr)
|
|
147
|
+
return 1
|
|
148
|
+
|
|
149
|
+
if args.desktop == "True":
|
|
150
|
+
target_logger = os.path.join(desktop_folder, "SpecLogger_running.exe")
|
|
151
|
+
target_monitor = os.path.join(desktop_folder, "SpecMonitor.exe")
|
|
152
|
+
|
|
153
|
+
if not os.path.exists(target_logger):
|
|
154
|
+
shutil.copy(source_running_logger, target_logger)
|
|
155
|
+
print("Create SpecLogger_running.exe on the desktop.")
|
|
156
|
+
else:
|
|
157
|
+
print("SpecLogger_running.exe is on desktop already.")
|
|
158
|
+
|
|
159
|
+
if not os.path.exists(target_monitor):
|
|
160
|
+
shutil.copy(source_monitor, target_monitor)
|
|
161
|
+
print("Create SpecMonitor.exe on the desktop.")
|
|
162
|
+
else:
|
|
163
|
+
print("SpecMonitor.exe is on desktop already.")
|
|
164
|
+
|
|
165
|
+
if not args.startup and not args.desktop and not args.status: # not arguments
|
|
166
|
+
args.status = "start"
|
|
167
|
+
|
|
168
|
+
if args.status in {"start", "stop"}:
|
|
169
|
+
try:
|
|
170
|
+
task_message = control_scheduled_logger(args.status)
|
|
171
|
+
except RuntimeError as error:
|
|
172
|
+
print(f"Could not control SpecLogger scheduled task: {error}", file=sys.stderr)
|
|
173
|
+
return 1
|
|
174
|
+
if task_message is not None:
|
|
175
|
+
print(task_message)
|
|
176
|
+
return 0
|
|
177
|
+
|
|
178
|
+
if args.status == "start":
|
|
179
|
+
if is_logger_running():
|
|
180
|
+
print("SpecLogger has started already.")
|
|
181
|
+
return
|
|
182
|
+
if args.debug == "False":
|
|
183
|
+
subprocess.Popen(
|
|
184
|
+
"SpecLogger_running.exe", creationflags=subprocess.CREATE_NO_WINDOW
|
|
185
|
+
)
|
|
186
|
+
print("SpecLogger started")
|
|
187
|
+
elif args.debug == "True":
|
|
188
|
+
os.startfile("SpecLogger_running.exe")
|
|
189
|
+
print("SpecLogger debug mode started")
|
|
190
|
+
|
|
191
|
+
elif args.status == "stop":
|
|
192
|
+
os.system("taskkill /im SpecLogger_running.exe /F /t")
|
|
193
|
+
print("SpecLogger stopped")
|
|
194
|
+
else: # ignore
|
|
195
|
+
return
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
if __name__ == "__main__":
|
|
199
|
+
main_func()
|