... | ... |
@@ -24,16 +24,21 @@ |
24 | 24 |
# along with this program. If not, see http://www.gnu.org/license. |
25 | 25 |
# |
26 | 26 |
# Revision History |
27 |
-# * v10 released 15 Sep 2015 by J L Owrey |
|
27 |
+# * v11 released 24 Jul 2018 by J L Owrey |
|
28 | 28 |
# |
29 |
+# Example of rrdtool command line executed by this program: |
|
30 |
+# |
|
31 |
+# rrdtool create radmonData.rrd --step 30 DS:CPM:GAUGE:60:U:U |
|
32 |
+# DS:SvperHr:GAUGE:60:U:U RRA:LAST:0.5:1:2880 RRA:LAST:0.5:30:35520 |
|
33 |
+# |
|
34 |
+ |
|
29 | 35 |
import os |
30 |
-import time |
|
31 | 36 |
import subprocess |
32 | 37 |
|
33 | 38 |
### DEFINE FILE LOCATIONS ### |
34 | 39 |
|
35 | 40 |
_USER = os.environ['USER'] |
36 |
-_RRD_FILE = "/home/%s/database/radmonData.rrd" % _USER # the file that stores the data |
|
41 |
+_RRD_FILE = "/home/%s/database/radmonData.rrd" % _USER # rrd database file |
|
37 | 42 |
_RRD_SIZE_IN_DAYS = 370 # days |
38 | 43 |
_1YR_RRA_STEPS_PER_DAY = 96 |
39 | 44 |
_DATABASE_UPDATE_INTERVAL = 30 |
... | ... |
@@ -51,7 +56,8 @@ def createRrdFile(): |
51 | 56 |
## Calculate database size |
52 | 57 |
|
53 | 58 |
heartBeat = 2 * _DATABASE_UPDATE_INTERVAL |
54 |
- rra1yrNumPDP = int(round(86400 / (_1YR_RRA_STEPS_PER_DAY * _DATABASE_UPDATE_INTERVAL))) |
|
59 |
+ rra1yrNumPDP = int(round(86400 / (_1YR_RRA_STEPS_PER_DAY * \ |
|
60 |
+ _DATABASE_UPDATE_INTERVAL))) |
|
55 | 61 |
rrd24hrNumRows = int(round(86400 / _DATABASE_UPDATE_INTERVAL)) |
56 | 62 |
rrd1yearNumRows = _1YR_RRA_STEPS_PER_DAY * _RRD_SIZE_IN_DAYS |
57 | 63 |
|
... | ... |
@@ -69,8 +75,7 @@ def createRrdFile(): |
69 | 75 |
subprocess.check_output(strCmd, stderr=subprocess.STDOUT, \ |
70 | 76 |
shell=True) |
71 | 77 |
except subprocess.CalledProcessError, exError: |
72 |
- print "%s rrdtool create failed: %s" % \ |
|
73 |
- (getTimeStamp(), exError.output) |
|
78 |
+ print "rrdtool create failed: %s" % (exError.output) |
|
74 | 79 |
return False |
75 | 80 |
return True |
76 | 81 |
##end def |
... | ... |
@@ -4,12 +4,14 @@ |
4 | 4 |
# something linke http://radiationMonitor.domain.com depending on |
5 | 5 |
# whether your local network uses a domain name server. |
6 | 6 |
# |
7 |
-MONITOR_URL="{your monitor url}" |
|
8 | 7 |
|
9 | 8 |
APP_PATH="/home/$USER/bin" |
10 | 9 |
LOG_PATH="/home/$USER/log" |
11 | 10 |
|
12 |
-PROCESS_ID="$(ps x | awk '/[r]admonAgent.py/{print $1}')" |
|
11 |
+AGENT_NAME="[r]admonAgent.py" |
|
12 |
+SOURCE_URL="{your radiation monitor url}" |
|
13 |
+ |
|
14 |
+PROCESS_ID="$(ps x | awk -v a=$AGENT_NAME '$7 ~ a {print $1}')" |
|
13 | 15 |
|
14 | 16 |
if [ -n "$PROCESS_ID" ]; then |
15 | 17 |
if [ "$1" != "-q" ]; then |
... | ... |
@@ -18,5 +20,10 @@ if [ -n "$PROCESS_ID" ]; then |
18 | 20 |
else |
19 | 21 |
printf "starting up radmon agent\n" |
20 | 22 |
cd $APP_PATH |
21 |
- ./radmonAgent.py -t 10 -u $MONITOR_URL >> $LOG_PATH/radmonAgent.log 2>&1 & |
|
23 |
+ if [ "$1" != "" ]; then |
|
24 |
+ ./$AGENT_NAME $1 -u $SOURCE_URL |
|
25 |
+ else |
|
26 |
+ ./$AGENT_NAME -u $SOURCE_URL >> \ |
|
27 |
+ $LOG_PATH/radmonAgent.log 2>&1 & |
|
28 |
+ fi |
|
22 | 29 |
fi |
... | ... |
@@ -1,7 +1,9 @@ |
1 | 1 |
#!/bin/bash |
2 |
-# Stop the radmon agent process and clean up environment. |
|
2 |
+# Stop the radmon agent process. |
|
3 | 3 |
|
4 |
-PROCESS_ID="$(ps x | awk '/[r]admonAgent.py/{print $1}')" |
|
4 |
+AGENT_NAME="[r]admonAgent.py" |
|
5 |
+ |
|
6 |
+PROCESS_ID="$(ps x | awk -v a=$AGENT_NAME '$7 ~ a {print $1}')" |
|
5 | 7 |
|
6 | 8 |
if [ -n "$PROCESS_ID" ]; then |
7 | 9 |
printf "killing radmon agent [%s]\n" $PROCESS_ID |
8 | 10 |
old mode 100644 |
9 | 11 |
new mode 100755 |
... | ... |
@@ -56,10 +56,10 @@ img.chart { |
56 | 56 |
text-align: left; |
57 | 57 |
padding: 10px; |
58 | 58 |
} |
59 |
-span.chartNav { |
|
59 |
+span.chartSelectors { |
|
60 | 60 |
margin: auto; |
61 | 61 |
} |
62 |
-ul.chartNav { |
|
62 |
+ul.selectorElement { |
|
63 | 63 |
list-style-type: none; |
64 | 64 |
margin: 10px; |
65 | 65 |
padding: 0; |
... | ... |
@@ -67,20 +67,25 @@ ul.chartNav { |
67 | 67 |
background-color: #bbb; |
68 | 68 |
text-align: center; |
69 | 69 |
} |
70 |
-li.chartNav { |
|
70 |
+li.selectorElement { |
|
71 | 71 |
display: inline-block; |
72 | 72 |
font: bold 18px arial, sans-serif; |
73 | 73 |
color: black; |
74 | 74 |
} |
75 |
-text.chartNav:hover { |
|
75 |
+span.selectorElement:hover { |
|
76 | 76 |
background-color: #333; |
77 | 77 |
cursor: pointer; |
78 | 78 |
color: white; |
79 | 79 |
} |
80 |
-text.chartNav { |
|
80 |
+span.selectorElement { |
|
81 | 81 |
display: inline-block; |
82 | 82 |
padding: 8px 12px; |
83 | 83 |
} |
84 |
+#iframe_a { |
|
85 |
+ border:none; |
|
86 |
+ width:100%; |
|
87 |
+ height:450px; |
|
88 |
+} |
|
84 | 89 |
</style> |
85 | 90 |
</head> |
86 | 91 |
|
... | ... |
@@ -94,9 +99,9 @@ DIY Radiation Monitor</a></h2> |
94 | 99 |
<h4>Albany, Oregon</h4> |
95 | 100 |
|
96 | 101 |
<div class="datetime"> |
97 |
-<text id="date"></text> |
|
102 |
+<span id="date"></span> |
|
98 | 103 |
|
99 |
-<text id="time"></text> |
|
104 |
+<span id="time"></span> |
|
100 | 105 |
</div> |
101 | 106 |
|
102 | 107 |
<div class="rowContainer"> |
... | ... |
@@ -108,9 +113,9 @@ Counts per second:<br> |
108 | 113 |
uSv per hour: |
109 | 114 |
</div> |
110 | 115 |
<div class="dataItems"> |
111 |
-<text id="cpm"></text><br> |
|
112 |
-<text id="cps"></text><br> |
|
113 |
-<text id="uSvPerHr"></text> |
|
116 |
+<span id="cpm"></span><br> |
|
117 |
+<span id="cps"></span><br> |
|
118 |
+<span id="uSvPerHr"></span> |
|
114 | 119 |
</div> |
115 | 120 |
</div> |
116 | 121 |
|
... | ... |
@@ -121,32 +126,57 @@ Status:<br> |
121 | 126 |
Mode: |
122 | 127 |
</div> |
123 | 128 |
<div class="dataItems"> |
124 |
-<text id="status"></text><br> |
|
125 |
-<text id="mode"></text> |
|
129 |
+<span id="status"></span><br> |
|
130 |
+<span id="mode"></span> |
|
126 | 131 |
</div> |
127 | 132 |
</div> |
128 | 133 |
</div> |
129 | 134 |
|
130 |
-<span class="chartNav"> |
|
131 |
-<ul class="chartNav"> |
|
132 |
-<li class="chartNav">Select charts:</li> |
|
133 |
-<li class="chartNav"><text class="chartNav" onclick="setChartPeriod(1)"> |
|
134 |
-24 hours</text></li> |
|
135 |
-<li class="chartNav"><text class="chartNav" onclick="setChartPeriod(2)"> |
|
136 |
-4 weeks</text></li> |
|
137 |
-<li class="chartNav"><text class="chartNav" onclick="setChartPeriod(3)"> |
|
138 |
-12 months</text></li> |
|
135 |
+<span class="chartSelectors"> |
|
136 |
+<ul class="selectorElement"> |
|
137 |
+<li class="selectorElement">Select charts:</li> |
|
138 |
+<li class="selectorElement"><span class="selectorElement" |
|
139 |
+ onclick="setChartPeriod(1)"> |
|
140 |
+24 hours</span></li> |
|
141 |
+<li class="selectorElement"><span class="selectorElement" |
|
142 |
+ onclick="setChartPeriod(2)"> |
|
143 |
+4 weeks</span></li> |
|
144 |
+<li class="selectorElement"><span class="selectorElement" |
|
145 |
+ onclick="setChartPeriod(3)">12 months</span></li> |
|
146 |
+<li id="customSelector" class="selectorElement" style="visibility:hidden;"> |
|
147 |
+<span class="selectorElement" |
|
148 |
+ onclick="setChartPeriod(0)">Custom...</span></li> |
|
139 | 149 |
</ul> |
140 | 150 |
</span> |
151 |
+ |
|
152 |
+<div class="rowContainer" id="customChartsContainer" style="display:none;"> |
|
153 |
+<div class="currentDataCell"> |
|
154 |
+<form id="fmDateSelector" action="radmon.php" method="post" |
|
155 |
+ target="iframe_a"> |
|
156 |
+<label for="beginDate">Begin Date: </label> |
|
157 |
+<input id="beginDate" name="beginDate" type="date" value="mm/dd/yyyy" /> |
|
158 |
+<label for="endDate">End Date: </label> |
|
159 |
+<input id="endDate" name="endDate" type="date" value="mm/dd/yyyy" /> |
|
160 |
+<br><br> |
|
161 |
+<input type="button" onclick="getCustomCharts()" value="Get Charts"> |
|
162 |
+</form> |
|
163 |
+<span id="errorMsg"></span><br> |
|
164 |
+<iframe id="iframe_a" name="iframe_a"></iframe> |
|
165 |
+</div> |
|
166 |
+</div> |
|
167 |
+ |
|
141 | 168 |
<br> |
142 | 169 |
|
170 |
+ |
|
171 |
+ |
|
172 |
+<div class="rowContainer" id="stockChartsContainer"> |
|
143 | 173 |
<div class="chartContainer"> |
144 | 174 |
<img class="chart" id="cpmChart"> |
145 | 175 |
</div> |
146 |
- |
|
147 | 176 |
<div class="chartContainer"> |
148 | 177 |
<img class="chart" id="uSvChart"> |
149 | 178 |
</div> |
179 |
+</div> |
|
150 | 180 |
|
151 | 181 |
<div class="notes"> |
152 | 182 |
<b>NOTES:</b> |
... | ... |
@@ -166,10 +196,10 @@ Radiation Dose Chart</a> by Randall Monroe.</li> |
166 | 196 |
<br> |
167 | 197 |
|
168 | 198 |
<script> |
169 |
- |
|
199 |
+"use strick"; |
|
170 | 200 |
/* Global constants */ |
171 | 201 |
|
172 |
-var radmonDataUrl = "dynamic/radmonOutputData.js"; |
|
202 |
+var radmonDataUrl = "dynamic/radmonData.js"; |
|
173 | 203 |
|
174 | 204 |
/* Global DOM objects */ |
175 | 205 |
|
... | ... |
@@ -177,7 +207,7 @@ var radmonDataUrl = "dynamic/radmonOutputData.js"; |
177 | 207 |
var cpmChart_g = document.getElementById("cpmChart"); |
178 | 208 |
var uSvChart_g = document.getElementById("uSvChart"); |
179 | 209 |
|
180 |
-// Text elements |
|
210 |
+// Document elements |
|
181 | 211 |
var date_e = document.getElementById("date"); |
182 | 212 |
var time_e = document.getElementById("time"); |
183 | 213 |
var cpm_e = document.getElementById("cpm"); |
... | ... |
@@ -186,16 +216,25 @@ var uSvPerHr_e = document.getElementById("uSvPerHr"); |
186 | 216 |
var mode_e = document.getElementById("mode"); |
187 | 217 |
var status_e = document.getElementById("status"); |
188 | 218 |
|
219 |
+// Custom charts document elements |
|
220 |
+var customChartsContainer = document.getElementById("customChartsContainer"); |
|
221 |
+var stockChartsContainer = document.getElementById("stockChartsContainer"); |
|
222 |
+var fmDateSelector = document.getElementById("fmDateSelector"); |
|
223 |
+var errorMsg = document.getElementById("errorMsg"); |
|
224 |
+var customSelector = document.getElementById("customSelector"); |
|
225 |
+ |
|
226 |
+ |
|
189 | 227 |
/* Global objects */ |
190 | 228 |
|
191 | 229 |
var httpRequest = new XMLHttpRequest(); |
192 | 230 |
|
193 | 231 |
/* Global variables */ |
194 | 232 |
|
195 |
-var graphPeriod; |
|
196 |
- |
|
233 |
+var chartPeriod = 1; |
|
197 | 234 |
|
198 | 235 |
function main() { |
236 |
+ httpRequest.timeout = 3000; |
|
237 |
+ |
|
199 | 238 |
/* Register call back function to process http requests */ |
200 | 239 |
httpRequest.onreadystatechange = function() { |
201 | 240 |
if (httpRequest.readyState == 4 && httpRequest.status == 200) { |
... | ... |
@@ -208,30 +247,38 @@ function main() { |
208 | 247 |
httpRequest.ontimeout = function(e) { |
209 | 248 |
displayOfflineStatus(); |
210 | 249 |
}; |
211 |
- |
|
250 |
+ |
|
251 |
+ initializeDateSelector(); |
|
212 | 252 |
getRadmonData(); |
213 |
- graphPeriod = 1; |
|
214 |
- getRadmonGraphs(); |
|
215 |
- setInterval(getRadmonData, 5000); |
|
216 |
- setInterval(getRadmonGraphs, 300000); |
|
253 |
+ getRadmonCharts(); |
|
254 |
+ setInterval(getRadmonData, 2000); |
|
255 |
+ setInterval(getRadmoncharts, 300000); |
|
217 | 256 |
} |
218 | 257 |
|
219 | 258 |
function getRadmonData() { |
220 |
- httpRequest.open("GET", radmonDataUrl, true); |
|
221 |
- httpRequest.timeout = 3000; |
|
259 |
+ httpRequest.open("POST", radmonDataUrl, true); |
|
222 | 260 |
httpRequest.send(); |
223 | 261 |
} |
224 | 262 |
|
225 | 263 |
function setChartPeriod(n) { |
226 |
- graphPeriod = n; |
|
227 |
- getRadmonGraphs(); |
|
264 |
+ /* Show custom charts if custom charts selected, otherwise show |
|
265 |
+ stock charts. */ |
|
266 |
+ chartPeriod = n; |
|
267 |
+ if (n == 0) { |
|
268 |
+ customChartsContainer.style.display = "block"; |
|
269 |
+ stockChartsContainer.style.display = "none"; |
|
270 |
+ } else { |
|
271 |
+ customChartsContainer.style.display = "none"; |
|
272 |
+ stockChartsContainer.style.display = "block"; |
|
273 |
+ getRadmonCharts(); |
|
274 |
+ } |
|
228 | 275 |
} |
229 | 276 |
|
230 |
-function getRadmonGraphs() { |
|
277 |
+function getRadmonCharts() { |
|
231 | 278 |
var d = new Date; |
232 | 279 |
var pfx; |
233 | 280 |
|
234 |
- switch(graphPeriod) { |
|
281 |
+ switch(chartPeriod) { |
|
235 | 282 |
case 1: |
236 | 283 |
pfx = "24hr_"; |
237 | 284 |
break; |
... | ... |
@@ -250,6 +297,12 @@ function displayData(dataItem) { |
250 | 297 |
var timeStamp, date, time, hourminute; |
251 | 298 |
var localDateObj,localTimeZone; |
252 | 299 |
|
300 |
+ // Custom charts can only be generated by the local server, i.e, |
|
301 |
+ // with access to rrdtool database. |
|
302 |
+ if (dataItem.serverMode == "primary") { |
|
303 |
+ customSelector.style.visibility = "visible"; |
|
304 |
+ } |
|
305 |
+ |
|
253 | 306 |
timeStamp = dataItem.date; |
254 | 307 |
date = timeStamp.split(" ")[0]; |
255 | 308 |
time = timeStamp.split(" ")[1]; |
... | ... |
@@ -259,11 +312,11 @@ function displayData(dataItem) { |
259 | 312 |
|
260 | 313 |
date_e.innerHTML = date; |
261 | 314 |
time_e.innerHTML = hourminute + |
262 |
- " <small>(GMT+" + localTimeZone + ")</small>"; |
|
315 |
+ " <small>(UTC-" + localTimeZone + ")</small>"; |
|
263 | 316 |
cpm_e.innerHTML = dataItem.CPM; |
264 | 317 |
cps_e.innerHTML = dataItem.CPS; |
265 | 318 |
uSvPerHr_e.innerHTML = dataItem.uSvPerHr; |
266 |
- mode_e.innerHTML = dataItem.Mode; |
|
319 |
+ mode_e.innerHTML = dataItem.mode; |
|
267 | 320 |
|
268 | 321 |
status_e.innerHTML = dataItem.status; |
269 | 322 |
if (dataItem.status == "online") { |
... | ... |
@@ -277,7 +330,7 @@ function displayOfflineStatus() { |
277 | 330 |
var d = new Date(); |
278 | 331 |
localTimeZone = d.getTimezoneOffset() / 60; |
279 | 332 |
date_e.innerHTML = (d.getMonth() + 1) + "/" + d.getDate() + "/" + d.getFullYear(); |
280 |
- time_e.innerHTML = d.getHours() + ":" + d.getMinutes() + " <small>(GMT+" + |
|
333 |
+ time_e.innerHTML = d.getHours() + ":" + d.getMinutes() + " <small>(UTC-" + |
|
281 | 334 |
localTimeZone + ")</small>"; |
282 | 335 |
cpm_e.innerHTML = ""; |
283 | 336 |
cps_e.innerHTML = ""; |
... | ... |
@@ -287,6 +340,22 @@ function displayOfflineStatus() { |
287 | 340 |
status_e.style.color = "red"; |
288 | 341 |
} |
289 | 342 |
|
343 |
+function initializeDateSelector() { |
|
344 |
+ var d = new Date(); |
|
345 |
+ |
|
346 |
+ var dEnd = new Date(d.getFullYear(), |
|
347 |
+ d.getMonth(), d.getDate() - 0); |
|
348 |
+ |
|
349 |
+ var dBegin = new Date(d.getFullYear(), |
|
350 |
+ d.getMonth(), d.getDate() - 1); |
|
351 |
+ |
|
352 |
+ document.getElementById("beginDate").valueAsDate = dBegin; |
|
353 |
+ document.getElementById("endDate").valueAsDate = dEnd; |
|
354 |
+} |
|
355 |
+ |
|
356 |
+function getCustomCharts() { |
|
357 |
+ fmDateSelector.submit(); |
|
358 |
+} |
|
290 | 359 |
</script> |
291 | 360 |
|
292 | 361 |
</body> |
293 | 362 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,204 @@ |
1 |
+<html> |
|
2 |
+<!-- Courtsey ruler |
|
3 |
+12345678901234567890123456789012345678901234567890123456789012345678901234567890 |
|
4 |
+--> |
|
5 |
+<head> |
|
6 |
+<style> |
|
7 |
+p { |
|
8 |
+ font: 14px ariel, sans serif; |
|
9 |
+} |
|
10 |
+#errorMsg { |
|
11 |
+ font:bold 18px arial,sans-serif; |
|
12 |
+ color:red; |
|
13 |
+ text-align:center; |
|
14 |
+} |
|
15 |
+.chartContainer { |
|
16 |
+ padding: 2px; |
|
17 |
+} |
|
18 |
+img.chart { |
|
19 |
+ width:100%; |
|
20 |
+} |
|
21 |
+</style> |
|
22 |
+</head> |
|
23 |
+<body> |
|
24 |
+ |
|
25 |
+<?php |
|
26 |
+/* |
|
27 |
+ Script: radmon.php |
|
28 |
+ |
|
29 |
+ Description: This scripts generates on the server charts showing |
|
30 |
+ radmon data spanning the period supplied by the user. The script |
|
31 |
+ does the following: |
|
32 |
+ - converts user supplied dates to epoch time |
|
33 |
+ - gets the times of the first and last data point in the round |
|
34 |
+ robin database (RRD) |
|
35 |
+ - from above validates user supplied begin and end dates |
|
36 |
+ - creates charts of the specified period |
|
37 |
+ |
|
38 |
+ Copyright 2020 Jeff Owrey |
|
39 |
+ This program is free software: you can redistribute it and/or modify |
|
40 |
+ it under the terms of the GNU General Public License as published by |
|
41 |
+ the Free Software Foundation, either version 3 of the License, or |
|
42 |
+ (at your option) any later version. |
|
43 |
+ |
|
44 |
+ This program is distributed in the hope that it will be useful, |
|
45 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
46 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
47 |
+ GNU General Public License for more details. |
|
48 |
+ |
|
49 |
+ You should have received a copy of the GNU General Public License |
|
50 |
+ along with this program. If not, see http://www.gnu.org/license. |
|
51 |
+ |
|
52 |
+ Revision History |
|
53 |
+ * v20 released 18 Jan 2020 by J L Owrey; first release |
|
54 |
+*/ |
|
55 |
+ |
|
56 |
+# Define global constants |
|
57 |
+ |
|
58 |
+# round robin database file |
|
59 |
+define("_RRD_FILE", str_replace("public_html/radmon/radmon.php", |
|
60 |
+ "database/radmonData.rrd", |
|
61 |
+ $_SERVER["SCRIPT_FILENAME"])); |
|
62 |
+# charts html directory |
|
63 |
+define("_CHART_DIRECTORY", str_replace("radmon.php", |
|
64 |
+ "dynamic/", |
|
65 |
+ $_SERVER["SCRIPT_FILENAME"])); |
|
66 |
+# standard chart width in pixels |
|
67 |
+define("_CHART_WIDTH", 600); |
|
68 |
+# standard chart height in pixels |
|
69 |
+define("_CHART_HEIGHT", 150); |
|
70 |
+# debug mode |
|
71 |
+define("_DEBUG", false); |
|
72 |
+ |
|
73 |
+# Set error handling modes. |
|
74 |
+error_reporting(E_ALL); |
|
75 |
+ |
|
76 |
+# Get user supplied chart begin and end dates. |
|
77 |
+$beginDate = $_POST["beginDate"]; |
|
78 |
+$endDate = $_POST["endDate"]; |
|
79 |
+ |
|
80 |
+# Convert the user supplied dates to epoch time stamps. |
|
81 |
+$beginDateEp = strtotime($beginDate); |
|
82 |
+$endDateEp = strtotime($endDate); |
|
83 |
+ |
|
84 |
+# Get the time stamp of the earliest data point in the RRD file. |
|
85 |
+$cmd = sprintf("rrdtool first %s --rraindex 1", _RRD_FILE); |
|
86 |
+$firstDP = shell_exec($cmd); |
|
87 |
+ |
|
88 |
+# Get the time stamp of the latest data point in the RRD file. |
|
89 |
+$cmd = sprintf("rrdtool last %s", _RRD_FILE); |
|
90 |
+$lastDP = shell_exec($cmd); |
|
91 |
+ |
|
92 |
+# Determine validity of user supplied dates. User supplied begin |
|
93 |
+# date must be less than user supplied end date. Furthermore both |
|
94 |
+# dates must be within the range of dates stored in the RRD. |
|
95 |
+if ($beginDateEp > $endDateEp) { |
|
96 |
+ echo "<p id=\"errorMsg\">" . |
|
97 |
+ "End date must be after begin date.</p>"; |
|
98 |
+} elseif ($beginDateEp < $firstDP || $endDateEp > $lastDP) { |
|
99 |
+ echo "<p id=\"errorMsg\">" . |
|
100 |
+ "Date range must be between " . |
|
101 |
+ date('m / d / Y', $firstDP) . " and " . |
|
102 |
+ date('m / d / Y', $lastDP) . ".</p>"; |
|
103 |
+} else { |
|
104 |
+ # Generate charts from validated user supplied dates. |
|
105 |
+ if (_DEBUG) { |
|
106 |
+ echo "<p>Date range: " . $beginDateEp . " thru " . |
|
107 |
+ $endDateEp . "</p>"; |
|
108 |
+ } |
|
109 |
+ createChart('custom_cpm', 'CPM', 'counts\ per\ minute', |
|
110 |
+ 'CPM', $beginDateEp, $endDateEp, |
|
111 |
+ 0, 0, 2, false); |
|
112 |
+ createChart('custom_svperhr', 'SvperHr', 'Sv\ per\ hour', |
|
113 |
+ 'Sv/Hr', $beginDateEp, $endDateEp, |
|
114 |
+ 0, 0, 2, false); |
|
115 |
+ # Send html commands to client browser. |
|
116 |
+ echo "<div class=\"chartContainer\">" . |
|
117 |
+ "<img class=\"chart\" src=\"dynamic/custom_cpm.png\">" . |
|
118 |
+ "</div>"; |
|
119 |
+ echo "<div class=\"chartContainer\">" . |
|
120 |
+ "<img class=\"chart\" src=\"dynamic/custom_svperhr.png\">" . |
|
121 |
+ "</div>"; |
|
122 |
+} |
|
123 |
+ |
|
124 |
+function createChart($chartFile, $dataItem, $label, $title, $begin, |
|
125 |
+ $end, $lower, $upper, $addTrend, $autoScale) { |
|
126 |
+ /* |
|
127 |
+ Uses rrdtool to create a chart of specified aredn node data item. |
|
128 |
+ Parameters: |
|
129 |
+ fileName - name of the created chart file |
|
130 |
+ dataItem - data item to be charted |
|
131 |
+ label - string containing a label for the item to be charted |
|
132 |
+ title - string containing a title for the chart |
|
133 |
+ begin - beginning time of the chart data |
|
134 |
+ end - ending time of the data to be charted |
|
135 |
+ lower - lower bound for chart ordinate #NOT USED |
|
136 |
+ upper - upper bound for chart ordinate #NOT USED |
|
137 |
+ addTrend - 0, show only chart data |
|
138 |
+ 1, show only a trend line |
|
139 |
+ 2, show a trend line and the chart data |
|
140 |
+ autoScale - if True, then use vertical axis auto scaling |
|
141 |
+ (lower and upper parameters are ignored), otherwise use |
|
142 |
+ lower and upper parameters to set vertical axis scale |
|
143 |
+ Returns: True if successful, False otherwise |
|
144 |
+ */ |
|
145 |
+ |
|
146 |
+ # Define path on server to chart files. |
|
147 |
+ $chartPath = _CHART_DIRECTORY . $chartFile . ".png"; |
|
148 |
+ |
|
149 |
+ # Format the rrdtool chart command. |
|
150 |
+ |
|
151 |
+ # Set chart file name, start time, end time, height, and width. |
|
152 |
+ $cmdfmt = "rrdtool graph %s -a PNG -s %s -e %s -w %s -h %s "; |
|
153 |
+ $cmd = sprintf($cmdfmt, $chartPath, $begin, $end, _CHART_WIDTH, |
|
154 |
+ _CHART_HEIGHT); |
|
155 |
+ $cmdfmt = "-l %s -u %s -r "; |
|
156 |
+ |
|
157 |
+ # Set upper and lower ordinate bounds. |
|
158 |
+ if ($lower < $upper) { |
|
159 |
+ $cmd .= sprintf($cmdfmt, $lower, $upper); |
|
160 |
+ } elseif ($autoScale) { |
|
161 |
+ $cmd .= "-A "; |
|
162 |
+ } |
|
163 |
+ $cmd .= "-Y "; |
|
164 |
+ |
|
165 |
+ # Set the chart ordinate label and chart title. |
|
166 |
+ $cmdfmt = "-v %s -t %s "; |
|
167 |
+ $cmd .= sprintf($cmdfmt, $label, $title); |
|
168 |
+ |
|
169 |
+ # Define moving average window width. |
|
170 |
+ $trendWindow = floor(($end - $begin) / 12); |
|
171 |
+ |
|
172 |
+ # Show the data, or a moving average trend line over |
|
173 |
+ # the data, or both. |
|
174 |
+ $cmdfmt = "DEF:dSeries=%s:%s:LAST "; |
|
175 |
+ $cmd .= sprintf($cmdfmt, _RRD_FILE, $dataItem); |
|
176 |
+ if ($addTrend == 0) { |
|
177 |
+ $cmd .= "LINE1:dSeries#0400ff "; |
|
178 |
+ } elseif ($addTrend == 1) { |
|
179 |
+ $cmdfmt = "CDEF:smoothed=dSeries,%s,TREND LINE2:smoothed#006600 "; |
|
180 |
+ $cmd .= sprintf($cmdfmt, $trendWindow); |
|
181 |
+ } elseif ($addTrend == 2) { |
|
182 |
+ $cmd .= "LINE1:dSeries#0400ff "; |
|
183 |
+ $cmdfmt = "CDEF:smoothed=dSeries,%s,TREND LINE2:smoothed#006600 "; |
|
184 |
+ $cmd .= sprintf($cmdfmt, $trendWindow); |
|
185 |
+ } |
|
186 |
+ |
|
187 |
+ # Execute the formatted rrdtool command in the shell. The rrdtool |
|
188 |
+ # command will complete execution before the html image tags get |
|
189 |
+ # sent to the browser. This assures that the charts are available |
|
190 |
+ # when the client browser executes the html code that loads the |
|
191 |
+ # charts into the document displayed by the client browser. |
|
192 |
+ if (_DEBUG) { |
|
193 |
+ echo "<p>chart command:<br>" . $cmd . "</p>"; |
|
194 |
+ } |
|
195 |
+ $result = shell_exec($cmd . " 2>&1"); |
|
196 |
+ if (_DEBUG) { |
|
197 |
+ echo "<p>result:<br>" . $result . "</p>"; |
|
198 |
+ } |
|
199 |
+} |
|
200 |
+ |
|
201 |
+?> |
|
202 |
+ |
|
203 |
+</body> |
|
204 |
+</html> |