Browse code

minor revisions 20180303

fractalxaos authored on 03/04/2018 01:14:48
Showing 3 changed files
1 1
old mode 100644
2 2
new mode 100755
... ...
@@ -8,7 +8,7 @@
8 8
 # device and the Internet web server.  The agent periodically sends an http
9 9
 # request to the radiation monitoring device and processes the response from
10 10
 # the device and performs a number of operations:
11
-#     - conversion of data items
11
+#     - conversion of data itemsq
12 12
 #     - update a round robin (rrdtool) database with the radiation data
13 13
 #     - periodically generate graphic charts for display in html documents
14 14
 #     - forward the radiation data to other services
... ...
@@ -32,6 +32,7 @@
32 32
 # Revision History
33 33
 #   * v20 released 15 Sep 2015 by J L Owrey; first release
34 34
 #   * v21 released 27 Nov 2017 by J L Owrey; bug fixes; updates
35
+#   * v22 released 03 Mar 2018 by J L Owrey; improved code readability
35 36
 #
36 37
 
37 38
 _MIRROR_SERVER = False
... ...
@@ -49,10 +50,9 @@ _USER = os.environ['USER']
49 50
    ### DEFAULT WEATHER STATION URL ###
50 51
 
51 52
 # ip address of radiation monitoring device
52
-_RADIATION_MONITOR_URL = "http://YOUR_RADIATION_MONITOR_IP_ADDRESS"
53
+_DEFAULT_RADIATION_MONITOR_URL = '{your radiation monitor device url}'
53 54
 # url if this is a mirror server
54
-_PRIMARY_SERVER_URL = \
55
-    "http://YOUR_PRIMARY_SERVER/USER/radmon/dynamic/radmonInputData.dat"
55
+_PRIMARY_SERVER_URL = '{your primary server radmon data url}'
56 56
 
57 57
     ### FILE AND FOLDER LOCATIONS ###
58 58
 
... ...
@@ -63,7 +63,7 @@ _CHARTS_DIRECTORY = _DOCROOT_PATH + "dynamic/"
63 63
  # database that stores weather data
64 64
 _RRD_FILE = "/home/%s/database/radmonData.rrd" % _USER
65 65
 # location of data input file
66
-INPUT_DATA_FILE = _DOCROOT_PATH + "dynamic/radmonInputData.dat"
66
+_INPUT_DATA_FILE = _DOCROOT_PATH + "dynamic/radmonInputData.dat"
67 67
 # location of data output file
68 68
 _OUTPUT_DATA_FILE = _DOCROOT_PATH + "dynamic/radmonOutputData.js"
69 69
 
... ...
@@ -77,7 +77,7 @@ _DATABASE_UPDATE_INTERVAL = 30
77 77
 # number seconds to wait for a response to HTTP request
78 78
 _HTTP_REQUEST_TIMEOUT = 3
79 79
 # max number of failed data requests allowed
80
-_MAX_RADIATION_MONITOR_OFFLINE_COUNT = 2
80
+_MAX_FAILED_DATA_REQUESTS = 2
81 81
 # radmon chart dimensions
82 82
 _CHART_WIDTH = 600
83 83
 _CHART_HEIGHT = 150
... ...
@@ -89,11 +89,11 @@ debugOption = False
89 89
 # online status of radiation monitor
90 90
 radiationMonitorOnline = True
91 91
 # number of unsuccessful http requests
92
-radiationMonitorOfflineCount = 0
92
+failedDataRequestCount = 0
93 93
 # status of reset command to radiation monitor
94 94
 remoteDeviceReset = False
95 95
 # ip address of radiation monitor
96
-radiationMonitorUrl = _RADIATION_MONITOR_URL
96
+radiationMonitorUrl = _DEFAULT_RADIATION_MONITOR_URL
97 97
 # web update frequency
98 98
 dataRequestInterval = _DEFAULT_DATA_REQUEST_INTERVAL
99 99
 
... ...
@@ -115,27 +115,29 @@ def setOfflineStatus(dData):
115 115
            dData - dictionary object containing weather data
116 116
        Returns nothing.
117 117
     """
118
-    global radiationMonitorOnline, radiationMonitorOfflineCount
118
+    global radiationMonitorOnline, failedDataRequestCount
119 119
 
120
-    radiationMonitorOfflineCount += 1
120
+    if os.path.exists(_INPUT_DATA_FILE):
121
+        os.remove(_INPUT_DATA_FILE)
121 122
 
122
-    if radiationMonitorOfflineCount < _MAX_RADIATION_MONITOR_OFFLINE_COUNT:
123
+    if failedDataRequestCount < _MAX_FAILED_DATA_REQUESTS - 1:
124
+        failedDataRequestCount += 1
123 125
         return
124 126
 
125 127
     # If the radiation monitor was previously online, then send a message
126 128
     # that we are now offline.
127 129
     if radiationMonitorOnline:
128 130
         print "%s: radiation monitor offline" % getTimeStamp()
129
-        if os.path.exists(INPUT_DATA_FILE):
130
-            os.remove(INPUT_DATA_FILE)
131 131
         radiationMonitorOnline = False
132 132
 
133
-    for key in dData:
134
-        dData[key] = ''
135
-
136
-    dData['status'] = 'offline'
133
+        dData['UTC'] = ''
134
+        dData['Mode'] = ''
135
+        dData['uSvPerHr'] = ''
136
+        dData['CPM'] = ''
137
+        dData['CPS'] = ''
138
+        dData['status'] = 'offline'
137 139
 
138
-    writeOutputDataFile(dData)
140
+        writeOutputDataFile(dData)
139 141
     return
140 142
 ##end def
141 143
 
... ...
@@ -152,7 +154,7 @@ def getRadiationData():
152 154
     Returns a string containing the radiation data, or None if
153 155
     not successful.
154 156
     """
155
-    global radiationMonitorOnline, radiationMonitorOfflineCount, \
157
+    global radiationMonitorOnline, failedDataRequestCount, \
156 158
            remoteDeviceReset
157 159
 
158 160
     if _MIRROR_SERVER:
... ...
@@ -179,15 +181,13 @@ def getRadiationData():
179 181
             print "http error: %s" % exError
180 182
         return None
181 183
 
182
-    radiationMonitorOfflineCount = 0
183
-
184 184
     # If the radiation monitor was previously offline, then send a message
185 185
     # that we are now online.
186 186
     if not radiationMonitorOnline:
187 187
         print "%s radiation monitor online" % getTimeStamp()
188 188
         radiationMonitorOnline = True
189 189
 
190
-    #print content
190
+    failedDataRequestCount = 0
191 191
     return content
192 192
 ##end def
193 193
 
... ...
@@ -250,6 +250,8 @@ def convertData(dData):
250 250
         
251 251
         dData['CPM'] = int(dData.pop('CPM'))
252 252
 
253
+        dData['CPS'] = int(dData.pop('CPS'))
254
+
253 255
     except Exception, exError:
254 256
         print "%s convertData: %s" % (getTimeStamp(), exError)
255 257
         result = False
... ...
@@ -258,7 +260,8 @@ def convertData(dData):
258 260
 ##end def
259 261
 
260 262
 def writeOutputDataFile(dData):
261
-    """Convert individual weather string data items as necessary.
263
+    """Write radiation data items to a JSON formatted file for use by
264
+       HTML documents.
262 265
        Parameters:
263 266
            lsData - a list object containing the data to be written
264 267
                     to the JSON file
... ...
@@ -282,17 +285,20 @@ def writeOutputDataFile(dData):
282 285
         print "%s writeOutputDataFile: %s" % (getTimeStamp(), exError)
283 286
         return False
284 287
 
285
-    if debugOption and 0:
286
-        print sData
287
-
288 288
     return True
289 289
 ## end def
290 290
 
291 291
 def writeInputDataFile(sData):
292
-    # Write the string to the output data file for use by html documents.
292
+    """Write raw data from radiation monitor to file for use by mirror
293
+       servers.
294
+       Parameters:
295
+           sData - a string object containing the data string from
296
+                   the radiation monitor
297
+       Returns true if successful, false otherwise.
298
+    """
293 299
     sData += "\n"
294 300
     try:
295
-        fc = open(INPUT_DATA_FILE, "w")
301
+        fc = open(_INPUT_DATA_FILE, "w")
296 302
         fc.write(sData)
297 303
         fc.close()
298 304
     except Exception, exError:
... ...
@@ -314,13 +320,12 @@ def updateDatabase(dData):
314 320
     global remoteDeviceReset
315 321
 
316 322
     # The RR database stores whole units, so convert uSv to Sv.
317
-    #Svvalue = float(dData['uSvPerHr']) * 1.0E-06
318
-    Svvalue = dData['uSvPerHr'] * 1.0E-06 
323
+    SvPerHr = dData['uSvPerHr'] * 1.0E-06 
319 324
 
320 325
     # Create the rrdtool update command.
321 326
     strCmd = "rrdtool update %s %s:%s:%s" % \
322
-                       (_RRD_FILE, dData['UTC'], dData['CPM'], Svvalue)
323
-    if debugOption:
327
+                       (_RRD_FILE, dData['UTC'], dData['CPM'], SvPerHr)
328
+    if debugOption and False:
324 329
         print "%s" % strCmd # DEBUG
325 330
 
326 331
     # Run the command as a subprocess.
... ...
@@ -329,15 +334,15 @@ def updateDatabase(dData):
329 334
                              stderr=subprocess.STDOUT)
330 335
     except subprocess.CalledProcessError, exError:
331 336
         print "%s: rrdtool update failed: %s" % \
332
-                                 (getTimeStamp(), exError.output)
337
+                    (getTimeStamp(), exError.output)
333 338
         if exError.output.find("illegal attempt to update using time") > -1:
334 339
             remoteDeviceReset = True
335
-            print "%s: rebooting radiation monitor" % \
336
-                                 (getTimeStamp())
337
-
340
+            print "%s: rebooting radiation monitor" % (getTimeStamp())
338 341
         return False
339
-
340
-    return True
342
+    else:
343
+        if debugOption:
344
+            print 'database update sucessful'
345
+        return True
341 346
 ##end def
342 347
 
343 348
 def createGraph(fileName, dataItem, gLabel, gTitle, gStart,
... ...
@@ -392,7 +397,7 @@ def createGraph(fileName, dataItem, gLabel, gTitle, gStart,
392 397
         strCmd += "CDEF:smoothed=dSeries,%s,TREND LINE3:smoothed#ff0000 " \
393 398
                   % trendWindow[gStart]
394 399
      
395
-    if debugOption:
400
+    if debugOption and False:
396 401
         print "%s\n" % strCmd # DEBUG
397 402
     
398 403
     # Run the formatted rrdtool command as a subprocess.
... ...
@@ -475,9 +480,6 @@ def main():
475 480
     # last time the rrdtool database updated
476 481
     lastDatabaseUpdateTime = -1
477 482
 
478
-    # define empty dictionary object for radmon data
479
-    dData = {}
480
-
481 483
     ## Get command line arguments.
482 484
     getCLarguments()
483 485
 
... ...
@@ -496,6 +498,7 @@ def main():
496 498
         # monitor and process the received data.
497 499
         if currentTime - lastDataRequestTime > dataRequestInterval:
498 500
             lastDataRequestTime = currentTime
501
+            dData = {}
499 502
             result = True
500 503
 
501 504
             # Get the data string from the device.
... ...
@@ -506,14 +509,13 @@ def main():
506 509
 
507 510
             # If successful parse the data.
508 511
             if result:
509
-                dData = {}
510 512
                 result = parseDataString(sData, dData)
511 513
 
512 514
             # If parsing successful, convert the data.
513 515
             if result:
514 516
                 result = convertData(dData)
515 517
 
516
-            # If conversion successful, write data to output file.
518
+            # If conversion successful, write data to data files.
517 519
             if result:
518 520
                 writeInputDataFile(sData)
519 521
                 writeOutputDataFile(dData)
... ...
@@ -547,5 +549,11 @@ def main():
547 549
 ## end def
548 550
 
549 551
 if __name__ == '__main__':
550
-    main()
551
-        
552
+    try:
553
+        main()
554
+    except KeyboardInterrupt:
555
+        print '\nInterrupted'
556
+        if os.path.exists(_OUTPUT_DATA_FILE):
557
+            os.remove(_OUTPUT_DATA_FILE)
558
+        if os.path.exists(_INPUT_DATA_FILE):
559
+            os.remove(_INPUT_DATA_FILE)
552 560
old mode 100644
553 561
new mode 100755
... ...
@@ -1,11 +1,24 @@
1 1
 #!/bin/bash
2
+# Stop the radmon agent process and clean up environment.
2 3
 
3
-# Next stop the database update process.
4
+# Set path to radmon input data file
5
+RADMON_INPUT_DATA_FILE="/home/$USER/public_html/radmon/dynamic/radmonInputData.dat"
6
+RADMON_OUTPUT_DATA_FILE="/home/$USER/public_html/radmon/dynamic/radmonOutputData.js"
4 7
 
5 8
 PROCESS_ID="$(ps x | awk '/[r]admonAgent.py/{print $1}')"
9
+
6 10
 if [ -n "$PROCESS_ID" ]; then
7 11
   printf "killing radmon agent [%s]\n" $PROCESS_ID
8 12
   kill $PROCESS_ID
13
+
14
+  # Remove input data file to alert mirror servers
15
+  if [ -e $RADMON_INPUT_DATA_FILE ]; then
16
+    rm $RADMON_INPUT_DATA_FILE
17
+  fi
18
+  # Remove output data file to alert web clients
19
+  if [ -e $RADMON_OUTPUT_DATA_FILE ]; then
20
+    rm $RADMON_OUTPUT_DATA_FILE
21
+  fi
9 22
 else
10 23
   echo radmon agent not running
11 24
 fi
... ...
@@ -162,16 +162,17 @@ Radiation Dose Chart</a> by Randall Monroe.</li>
162 162
 
163 163
 <script>
164 164
 
165
-/* Globals */
165
+/* Global constants */
166
+
166 167
 var radmonDataUrl = "dynamic/radmonOutputData.js";
167
-var httpRequest = new XMLHttpRequest();
168
-var graphPeriod = 1;
169 168
 
170
-/* Chart elements */
169
+/* Global DOM objects */
170
+
171
+// Chart elements
171 172
 var cpmChart_g = document.getElementById("cpmChart");
172 173
 var uSvChart_g = document.getElementById("uSvChart");
173 174
 
174
-/* Text elements */
175
+// Text elements
175 176
 var date_e = document.getElementById("date");    
176 177
 var time_e = document.getElementById("time"); 
177 178
 var cpm_e = document.getElementById("cpm");    
... ...
@@ -180,16 +181,28 @@ var uSvPerHr_e = document.getElementById("uSvPerHr");
180 181
 var mode_e = document.getElementById("mode");    
181 182
 var status_e = document.getElementById("status");    
182 183
 
184
+/* Global objects */
185
+
186
+var httpRequest = new XMLHttpRequest();
187
+
188
+/* Global variables */
189
+
190
+var graphPeriod;
191
+
192
+
183 193
 function main() {
184 194
     /* Register call back function to process http requests */
185 195
     httpRequest.onreadystatechange = function() {
186 196
         if (httpRequest.readyState == 4 && httpRequest.status == 200) {
187 197
             var dataArray = JSON.parse(httpRequest.responseText);
188 198
             displayData(dataArray[0]);
199
+        } else if (httpRequest.readyState == 4 && httpRequest.status == 404) {
200
+            displayOfflineStatus();
189 201
         }
190 202
     };
191 203
 
192 204
     getRadmonData();
205
+    graphPeriod = 1;
193 206
     getRadmonGraphs();
194 207
     setInterval(getRadmonData, 5000);
195 208
     setInterval(getRadmonGraphs, 300000);
... ...
@@ -251,6 +264,20 @@ function displayData(dataItem) {
251 264
     }
252 265
 }
253 266
 
267
+function displayOfflineStatus(dataItem) {
268
+    var d = new Date();
269
+    localTimeZone = d.getTimezoneOffset() / 60;
270
+    date_e.innerHTML = (d.getMonth() + 1) + "/" + d.getDate() + "/" + d.getFullYear();    
271
+    time_e.innerHTML = d.getHours() + ":" + d.getMinutes() + "  <small>(GMT+" + 
272
+                       localTimeZone + ")</small>";
273
+    cpm_e.innerHTML = "";    
274
+    cps_e.innerHTML = "";    
275
+    uSvPerHr_e.innerHTML = "";    
276
+    mode_e.innerHTML = "";    
277
+    status_e.innerHTML = "offline";    
278
+    status_e.style.color = "red";
279
+}
280
+
254 281
 </script>
255 282
 
256 283
 </body>