gandolf authored on 12/23/2022 22:17:04
Showing 14 changed files
1 1
deleted file mode 100755
... ...
@@ -1,93 +0,0 @@
1
-#!/usr/bin/python -u
2
-## The -u option above turns off block buffering of python output. This assures
3
-## that each error message gets individually printed to the log file.
4
-#
5
-# Module: createPowerRrd.py
6
-#
7
-# Description: Creates a rrdtool database for use by the power agent to
8
-# store the data from the power and temperature sensors.  The agent uses
9
-# the data in the database to generate graphic charts for display in the
10
-# node power web page.
11
-#
12
-# Copyright 2021 Jeff Owrey
13
-#    This program is free software: you can redistribute it and/or modify
14
-#    it under the terms of the GNU General Public License as published by
15
-#    the Free Software Foundation, either version 3 of the License, or
16
-#    (at your option) any later version.
17
-#
18
-#    This program is distributed in the hope that it will be useful,
19
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
20
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21
-#    GNU General Public License for more details.
22
-#
23
-#    You should have received a copy of the GNU General Public License
24
-#    along with this program.  If not, see http://www.gnu.org/license.
25
-#
26
-# Revision History
27
-#   * v10 released 01 Jun 2021 by J L Owrey
28
-#
29
-#2345678901234567890123456789012345678901234567890123456789012345678901234567890
30
-
31
-import os
32
-import time
33
-import subprocess
34
-
35
-    ### DEFINE DATABASE FILE LOCATION ###
36
-
37
-_USER = os.environ['USER']
38
-# the file that stores the data
39
-_RRD_FILE = "/home/%s/database/powerData.rrd" % _USER
40
-
41
-   ### DEFINE DATABASE SIZE AND GRANULARITY
42
-
43
-_RRD_SIZE_IN_DAYS = 740 # days
44
-_1YR_RRA_STEPS_PER_DAY = 1440
45
-_DATABASE_UPDATE_INTERVAL = 30
46
-
47
-def createRrdFile():
48
-    """Create the rrd file if it does not exist.
49
-       Parameters: none
50
-       Returns: True, if successful
51
-    """
52
-
53
-    if os.path.exists(_RRD_FILE):
54
-        print "power database already exists"
55
-        return True
56
-
57
-     ## Calculate database size
58
- 
59
-    heartBeat = 2 * _DATABASE_UPDATE_INTERVAL
60
-    rra1yrNumPDP =  int(round(86400 / (_1YR_RRA_STEPS_PER_DAY * \
61
-                    _DATABASE_UPDATE_INTERVAL)))
62
-    rrd24hrNumRows = int(round(86400 / _DATABASE_UPDATE_INTERVAL))
63
-    rrd1yearNumRows = _1YR_RRA_STEPS_PER_DAY * _RRD_SIZE_IN_DAYS
64
-       
65
-    strFmt = ("rrdtool create %s --start now-1day --step %s "
66
-              "DS:CUR:GAUGE:%s:U:U DS:VOLT:GAUGE:%s:U:U "
67
-              "DS:PWR:GAUGE:%s:U:U DS:BTMP:GAUGE:%s:U:U "
68
-              "DS:ATMP:GAUGE:%s:U:U "
69
-              "RRA:LAST:0.5:1:%s RRA:LAST:0.5:%s:%s")
70
-
71
-    strCmd = strFmt % (_RRD_FILE, _DATABASE_UPDATE_INTERVAL,           \
72
-                heartBeat, heartBeat, heartBeat, heartBeat, heartBeat, \
73
-                rrd24hrNumRows, rra1yrNumPDP, rrd1yearNumRows)
74
-
75
-    print "creating power database...\n\n%s\n" % strCmd
76
-
77
-    # Spawn a sub-shell and run the command
78
-    try:
79
-        subprocess.check_output(strCmd, stderr=subprocess.STDOUT, \
80
-                                shell=True)
81
-    except subprocess.CalledProcessError, exError:
82
-        print "rrdtool create failed: %s" % (exError.output)
83
-        return False
84
-    return True
85
-##end def
86
-
87
-def main():
88
-    createRrdFile()
89
-## end def
90
-
91
-if __name__ == '__main__':
92
-    main()
93
-        
94 0
deleted file mode 100755
... ...
@@ -1,200 +0,0 @@
1
-#!/usr/bin/python
2
-#
3
-# Module: ina260.py
4
-#
5
-# Description: This module acts as an interface between the INA260 sensor
6
-# and downstream applications that use the data.  Class methods get
7
-# current, voltage, and power data from the INA260 sensor.  It acts as a
8
-# library module that can be imported into and called from other Python
9
-# programs.
10
-#
11
-# Copyright 2021 Jeff Owrey
12
-#    This program is free software: you can redistribute it and/or modify
13
-#    it under the terms of the GNU General Public License as published by
14
-#    the Free Software Foundation, either version 3 of the License, or
15
-#    (at your option) any later version.
16
-#
17
-#    This program is distributed in the hope that it will be useful,
18
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
19
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20
-#    GNU General Public License for more details.
21
-#
22
-#    You should have received a copy of the GNU General Public License
23
-#    along with this program.  If not, see http://www.gnu.org/license.
24
-#
25
-# Revision History
26
-#   * v10 released 01 June 2021 by J L Owrey; first release
27
-#
28
-#2345678901234567890123456789012345678901234567890123456789012345678901234567890
29
-
30
-# Import the I2C interface library
31
-import smbus
32
-import time
33
-
34
-# Define Device Registers
35
-CONFIG_REG = 0x0
36
-ID_REG = 0xFE
37
-CUR_REG = 0x1
38
-VOLT_REG = 0x2
39
-PWR_REG = 0x3
40
-
41
-# Define default sm bus address.
42
-DEFAULT_BUS_ADDRESS = 0x40
43
-DEFAULT_BUS_NUMBER = 1
44
-
45
-# Define the default sensor configuration.  See the INA260 data sheet
46
-# for meaning of each bit.  The following bytes are written to the
47
-# configuration register
48
-#     byte 1: 11100000
49
-#     byte 2: 00100111
50
-DEFAULT_CONFIG = 0xE027
51
-
52
-class ina260:
53
-    # Initialize the INA260 sensor at the supplied address (default
54
-    # address is 0x40), and supplied bus (default is 1).  Creates
55
-    # a new SMBus object for each instance of this class.  Writes
56
-    # configuration data (two bytes) to the INA260 configuration
57
-    # register.
58
-    def __init__(self, sAddr=DEFAULT_BUS_ADDRESS,
59
-                       sbus=DEFAULT_BUS_NUMBER,
60
-                       config=DEFAULT_CONFIG,
61
-                       debug=False):
62
-        # Instantiate a smbus object.
63
-        self.sensorAddr = sAddr
64
-        self.bus = smbus.SMBus(sbus)
65
-        self.debugMode = debug
66
-
67
-        # Initialize INA260 sensor.  
68
-        initData = [(config >> 8), (config & 0x00FF)]
69
-        self.bus.write_i2c_block_data(self.sensorAddr, CONFIG_REG, initData)
70
-
71
-        if self.debugMode:
72
-            data = self.getInfo()
73
-            print(self)
74
-            print("manufacturer ID: %s %s\n"\
75
-                  "INA260 configuration register: %s %s\n" % data)
76
-    ## end def
77
-
78
-    def getInfo(self):
79
-        # Read manufacture identification data.
80
-        mfcid = self.bus.read_i2c_block_data(self.sensorAddr, ID_REG, 2)
81
-        mfcidB1 = format(mfcid[0], "08b")
82
-        mfcidB2 = format(mfcid[1], "08b")
83
-        # Read configuration data.
84
-        config = self.bus.read_i2c_block_data(self.sensorAddr, CONFIG_REG, 2)
85
-        configB1 = format(config[0], "08b")
86
-        configB2 = format(config[1], "08b")
87
-        return (mfcidB1, mfcidB2, configB1, configB2)
88
-    ## end def
89
-
90
-    def getCurrentReg(self):
91
-        # Read current register and return raw binary data for test and
92
-        # debug.
93
-        data = self.bus.read_i2c_block_data(self.sensorAddr, CUR_REG, 2)
94
-        dataB1 = format(data[0], "08b")
95
-        dataB2 = format(data[1], "08b")
96
-        return (dataB1, dataB2)
97
-    ## end def
98
-
99
-    def getCurrent(self):
100
-        # Get the current data from the sensor.
101
-        # INA260 returns the data in two bytes formatted as follows
102
-        #        -------------------------------------------------
103
-        #    bit |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
104
-        #        -------------------------------------------------
105
-        # byte 1 | d15 | d14 | d13 | d12 | d11 | d10 | d9  | d8  |
106
-        #        -------------------------------------------------
107
-        # byte 2 | d7  | d6  | d5  | d4  | d3  |  d2 | d1  | d0  |
108
-        #        -------------------------------------------------
109
-        # The current is returned in d15-d0, a two's complement,
110
-        # 16 bit number.  This means that d15 is the sign bit.        
111
-        data=self.bus.read_i2c_block_data(self.sensorAddr, CUR_REG, 2)
112
-
113
-        if self.debugMode:
114
-            dataB1 = format(data[0], "08b")
115
-            dataB2 = format(data[1], "08b")
116
-            print("current register: %s %s" % (dataB1, dataB2))
117
-
118
-        # Format into a 16 bit word.
119
-        bdata = data[0] << 8 | data[1]
120
-        # Convert from two's complement to integer.
121
-        # If d15 is 1, the the number is a negative two's complement
122
-        # number.  The absolute value is 2^16 - 1 minus the value
123
-        # of d15-d0 taken as a positive number.
124
-        if bdata > 0x7FFF:
125
-            bdata = -(0xFFFF - bdata) # 0xFFFF equals 2^16 - 1
126
-        # Convert integer data to mAmps.
127
-        mAmps = bdata * 1.25  # LSB is 1.25 mA
128
-        return mAmps
129
-    ## end def
130
-
131
-    def getVoltageReg(self):
132
-        # Read voltage register and return raw binary data for test
133
-        # and debug.
134
-        data = self.bus.read_i2c_block_data(self.sensorAddr, VOLT_REG, 2)
135
-        dataB1 = format(data[0], "08b")
136
-        dataB2 = format(data[1], "08b")
137
-        return (dataB1, dataB2)
138
-    ## end def
139
-
140
-    def getVoltage(self):
141
-        # Get the voltage data from the sensor.
142
-        # INA260 returns the data in two bytes formatted as follows
143
-        #        -------------------------------------------------
144
-        #    bit |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
145
-        #        -------------------------------------------------
146
-        # byte 1 | d15 | d14 | d13 | d12 | d11 | d10 | d9  | d8  |
147
-        #        -------------------------------------------------
148
-        # byte 2 | d7  | d6  | d5  | d4  | d3  |  d2 | d1  | d0  |
149
-        #        -------------------------------------------------
150
-        # The voltage is returned in d15-d0 as an unsigned integer.
151
-        data=self.bus.read_i2c_block_data(self.sensorAddr, VOLT_REG, 2)
152
-
153
-        if self.debugMode:
154
-            dataB1 = format(data[0], "08b")
155
-            dataB2 = format(data[1], "08b")
156
-            print("voltage register: %s %s" % (dataB1, dataB2))
157
-
158
-        # Convert data to volts.
159
-        volts = (data[0] << 8 | data[1]) * 0.00125 # LSB is 1.25 mV
160
-        return volts
161
-    ## end def
162
-
163
-    def getPower(self):
164
-        # Get the wattage data from the sensor.
165
-        # INA260 returns the data in two bytes formatted as follows
166
-        #        -------------------------------------------------
167
-        #    bit | 7   |  6  |  5  |  4  |  3  |  2  |  1  |  0  |
168
-        #        -------------------------------------------------
169
-        # byte 1 | d15 | d14 | d13 | d12 | d11 | d10 | d9  | d8  |
170
-        #        -------------------------------------------------
171
-        # byte 2 | d7  | d6  | d5  | d4  | d3  |  d2 | d1  | d0  |
172
-        #        -------------------------------------------------
173
-        # The wattage is returned in d15-d0 as an unsigned integer.
174
-        data=self.bus.read_i2c_block_data(self.sensorAddr, PWR_REG, 2)
175
-
176
-        if self.debugMode:
177
-            dataB1 = format(data[0], "08b")
178
-            dataB2 = format(data[1], "08b")
179
-            print("power register: %s %s" % (dataB1, dataB2))
180
-
181
-        # Convert data to milliWatts. 
182
-        mW = (data[0] << 8 | data[1]) * 10.0  # LSB is 10.0 mW
183
-        return mW
184
-   ## end def
185
-## end class
186
-
187
-def test():
188
-    # Initialize the smbus and INA260 sensor.
189
-    pwr1 = ina260(0x40, 1, debug=True)
190
-    # Print out sensor values.
191
-    while True:
192
-        print("%6.2f mA" % pwr1.getCurrent())
193
-        print("%6.2f V" % pwr1.getVoltage())
194
-        print("%6.2f mW\n" % pwr1.getPower())
195
-        time.sleep(2)
196
-## end def
197
-
198
-if __name__ == '__main__':
199
-    test()
200
-
201 0
deleted file mode 100755
... ...
@@ -1,645 +0,0 @@
1
-#!/usr/bin/python2 -u
2
-# The -u option above turns off block buffering of python output. This 
3
-# assures that each error message gets individually printed to the log file.
4
-#
5
-# Module: nodepowerAgent.py
6
-#
7
-# Description: This module acts as an agent between the mesh network and
8
-# node power and enviromental sensors.  The agent periodically polls the
9
-# sensors and processes the data returned from the sensors, including
10
-#     - conversion of data items
11
-#     - update a round robin (rrdtool) database with the sensor data
12
-#     - periodically generate graphic charts for display in html documents
13
-#     - write the processed node status to a JSON file for use by html
14
-#       documents
15
-#
16
-# Copyright 2021 Jeff Owrey
17
-#    This program is free software: you can redistribute it and/or modify
18
-#    it under the terms of the GNU General Public License as published by
19
-#    the Free Software Foundation, either version 3 of the License, or
20
-#    (at your option) any later version.
21
-#
22
-#    This program is distributed in the hope that it will be useful,
23
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
24
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25
-#    GNU General Public License for more details.
26
-#
27
-#    You should have received a copy of the GNU General Public License
28
-#    along with this program.  If not, see http://www.gnu.org/license.
29
-#
30
-# Revision History
31
-#   * v10 released 01 June 2021 by J L Owrey; first release
32
-#   * v11 released 02 July 2021 by J L Owrey; improved sensor fault
33
-#     handling; improved code readability
34
-#   * v12 released 06 July 2021 by J L Owrey; improved debug mode
35
-#     handling; debug mode state now passed to sensor object constructors
36
-#
37
-#2345678901234567890123456789012345678901234567890123456789012345678901234567890
38
-
39
-# Import required python libraries.
40
-import os
41
-import sys
42
-import signal
43
-import subprocess
44
-import multiprocessing
45
-import time
46
-import json
47
-
48
-# Import sensor libraries.
49
-import ina260 # power sensor
50
-import tmp102 # temperature sensor
51
-
52
-# Import custom libraries
53
-import smsalert
54
-
55
-    ### ENVIRONMENT ###
56
-
57
-_USER = os.environ['USER']
58
-_HOSTNAME = os.uname()[1]
59
-
60
-    ### SMS RECIPIENTS ###
61
-
62
-_SMS_CALLSIGN = '{your callsign}'
63
-_SMS_PASSCODE = '{your passcode}'
64
-_SMS_PHONE_NUMBER = '{your phone number}'
65
-
66
-    ### SENSOR BUS ADDRESSES ###
67
-
68
-# Set bus addresses of sensors.
69
-_PWR_SENSOR_ADDR = 0X40
70
-_BAT_TMP_SENSOR_ADDR = 0x48
71
-_AMB_TMP_SENSOR_ADDR = 0x4B
72
-# Set bus selector.
73
-_BUS_NUMBER = 1
74
-
75
-    ### FILE AND FOLDER LOCATIONS ###
76
-
77
-# folder to contain html
78
-_DOCROOT_PATH = "/home/%s/public_html/power/" % _USER
79
-# folder to contain charts and output data file
80
-_CHARTS_DIRECTORY = _DOCROOT_PATH + "dynamic/"
81
-# location of JSON output data file
82
-_OUTPUT_DATA_FILE = _DOCROOT_PATH + "dynamic/powerData.js"
83
-# database that stores node data
84
-_RRD_FILE = "/home/%s/database/powerData.rrd" % _USER
85
-
86
-    ### GLOBAL CONSTANTS ###
87
-
88
-# sensor data request interval in seconds
89
-_DEFAULT_SENSOR_POLLING_INTERVAL = 2
90
-# rrdtool database update interval in seconds
91
-_DATABASE_UPDATE_INTERVAL = 30
92
-# max number of failed attempts to get sensor data
93
-_MAX_FAILED_DATA_REQUESTS = 2
94
-
95
-# chart update interval in seconds
96
-_CHART_UPDATE_INTERVAL = 600
97
-# standard chart width in pixels
98
-_CHART_WIDTH = 600
99
-# standard chart height in pixels
100
-_CHART_HEIGHT = 150
101
-# chart average line color
102
-_AVERAGE_LINE_COLOR = '#006600'
103
-# low voltage alert threshold
104
-_DEFAULT_CRITICAL_LOW_VOLTAGE = 12.0
105
-
106
-   ### GLOBAL VARIABLES ###
107
-
108
-# Sensor instance objects.
109
-power1 = None
110
-battemp = None
111
-ambtemp = None
112
-sms = None
113
-
114
-# turns on or off extensive debugging messages
115
-debugMode = False
116
-verboseMode = False
117
-
118
-# frequency of data requests to sensors
119
-dataRequestInterval = _DEFAULT_SENSOR_POLLING_INTERVAL
120
-# how often charts get updated
121
-chartUpdateInterval = _CHART_UPDATE_INTERVAL
122
-# number of failed attempts to get sensor data
123
-failedUpdateCount = 0
124
-# sensor status
125
-deviceOnline = False
126
-# sms message sent status
127
-bSMSmsgSent = False
128
-
129
-  ###  PRIVATE METHODS  ###
130
-
131
-def getTimeStamp():
132
-    """
133
-    Get the local time and format as a text string.
134
-    Parameters: none
135
-    Returns: string containing the time stamp
136
-    """
137
-    return time.strftime( "%m/%d/%Y %T", time.localtime() )
138
-## end def
139
-
140
-def getEpochSeconds(sTime):
141
-    """
142
-    Convert the time stamp to seconds since 1/1/1970 00:00:00.
143
-    Parameters: 
144
-        sTime - the time stamp to be converted must be formatted
145
-                   as %m/%d/%Y %H:%M:%S
146
-    Returns: epoch seconds
147
-    """
148
-    try:
149
-        t_sTime = time.strptime(sTime, '%m/%d/%Y %H:%M:%S')
150
-    except Exception as exError:
151
-        print('%s getEpochSeconds: %s' % (getTimeStamp(), exError))
152
-        return None
153
-    tSeconds = int(time.mktime(t_sTime))
154
-    return tSeconds
155
-## end def
156
-
157
-def setStatusToOffline():
158
-    """Set the detected status of the device to
159
-       "offline" and inform downstream clients by removing input
160
-       and output data files.
161
-       Parameters: none
162
-       Returns: nothing
163
-    """
164
-    global deviceOnline
165
-
166
-    # Inform downstream clients by removing output data file.
167
-    if os.path.exists(_OUTPUT_DATA_FILE):
168
-       os.remove(_OUTPUT_DATA_FILE)
169
-    # If the sensor or  device was previously online, then send
170
-    # a message that we are now offline.
171
-    if deviceOnline:
172
-        print('%s device offline' % getTimeStamp())
173
-    deviceOnline = False
174
-##end def
175
-
176
-def terminateAgentProcess(signal, frame):
177
-    """Send a message to log when the agent process gets killed
178
-       by the operating system.  Inform downstream clients
179
-       by removing input and output data files.
180
-       Parameters:
181
-           signal, frame - dummy parameters
182
-       Returns: nothing
183
-    """
184
-    print('%s terminating agent process' % getTimeStamp())
185
-    setStatusToOffline()
186
-    sys.exit(0)
187
-##end def
188
-
189
-  ###  PUBLIC METHODS  ###
190
-
191
-def getSensorData(dData):
192
-    """
193
-    Poll sensors for data. Store the data in a dictionary object for
194
-    use by other subroutines.  The dictionary object passed in should
195
-    an empty dictionary, i.e., dData = { }.
196
-    Parameters: dData - a dictionary object to contain the sensor data
197
-                dSensors - a dictionary containing sensor objects
198
-    Returns: True if successful, False otherwise
199
-    """
200
-    dData["time"] = getTimeStamp()
201
- 
202
-    try:
203
-        dData["current"] = power1.getCurrent()
204
-        dData["voltage"] = power1.getVoltage()
205
-        dData["power"] =   power1.getPower()
206
-        dData["battemp"] = battemp.getTempF()
207
-        dData["ambtemp"] = ambtemp.getTempF()
208
-    except Exception as exError:
209
-        print("%s sensor error: %s" % (getTimeStamp(), exError))
210
-        return False
211
-
212
-    dData['chartUpdateInterval'] = chartUpdateInterval
213
-
214
-    return True
215
-## end def
216
-
217
-def convertData(dData):
218
-    """
219
-    Converts data items and verifies threshold crossings.
220
-    Parameters: dData - a dictionary object that contains the sensor data
221
-    Returns: True if successful, False otherwise
222
-    """
223
-    global bSMSmsgSent
224
-
225
-    if not bSMSmsgSent and dData["voltage"] <= _DEFAULT_CRITICAL_LOW_VOLTAGE:
226
-        # Format a text alert message.
227
-        message = "%s %s low voltage alert: %s volts" % \
228
-                  (getTimeStamp(), _HOSTNAME, dData["voltage"])
229
-        print(message)
230
-        # Send the text alert to recipient phone numbers.
231
-        sms.sendSMS(_SMS_PHONE_NUMBER, message)
232
-        bSMSmsgSent = True
233
-    elif bSMSmsgSent and dData["voltage"] > _DEFAULT_CRITICAL_LOW_VOLTAGE:
234
-        # Format a text alert message.
235
-        message = "%s %s voltage normal: %s volts" % \
236
-                  (getTimeStamp(), _HOSTNAME, dData["voltage"])
237
-        print(message)
238
-        # Send the text alert to recipient phone numbers.
239
-        sms.sendSMS(_SMS_PHONE_NUMBER, message)
240
-        bSMSmsgSent = False
241
-    ## end if
242
-    return True
243
-## end def
244
-
245
-def writeOutputFile(dData):
246
-    """
247
-    Write sensor data items to the output data file, formatted as 
248
-    a Javascript file.  This file may then be requested and used by
249
-    by downstream clients, for instance, an HTML document.
250
-    Parameters:
251
-        dData - a dictionary containing the data to be written
252
-                   to the output data file
253
-        Returns: True if successful, False otherwise
254
-    """
255
-    # Write a JSON formatted file for use by html clients.  The following
256
-    # data items are sent to the client file.
257
-    #    * The last database update date and time
258
-    #    * The data request interval
259
-    #    * The sensor values
260
-
261
-    # Create a JSON formatted string from the sensor data.
262
-    jsData = json.loads("{}")
263
-    try:
264
-        for key in dData:
265
-            jsData.update({key:dData[key]})
266
-        sData = "[%s]" % json.dumps(jsData)
267
-    except Exception as exError:
268
-        print("%s writeOutputFile: %s" % (getTimeStamp(), exError))
269
-        return False
270
-
271
-    if debugMode:
272
-        print(sData)
273
-
274
-    # Write the JSON formatted data to the output data file.
275
-
276
-    try:
277
-        fc = open(_OUTPUT_DATA_FILE, "w")
278
-        fc.write(sData)
279
-        fc.close()
280
-    except Exception as exError:
281
-        print("%s write output file failed: %s" % \
282
-              (getTimeStamp(), exError))
283
-        return False
284
-
285
-    return True
286
-## end def
287
-
288
-def setStatus(updateSuccess):
289
-    """Detect if device is offline or not available on
290
-       the network. After a set number of attempts to get data
291
-       from the device set a flag that the device is offline.
292
-       Parameters:
293
-           updateSuccess - a boolean that is True if data request
294
-                           successful, False otherwise
295
-       Returns: nothing
296
-    """
297
-    global failedUpdateCount, deviceOnline
298
-
299
-    if updateSuccess:
300
-        failedUpdateCount = 0
301
-        # Set status and send a message to the log if the device
302
-        # previously offline and is now online.
303
-        if not deviceOnline:
304
-            print('%s device online' % getTimeStamp())
305
-            deviceOnline = True
306
-        return
307
-    else:
308
-        # The last attempt failed, so update the failed attempts
309
-        # count.
310
-        failedUpdateCount += 1
311
-
312
-    if failedUpdateCount == _MAX_FAILED_DATA_REQUESTS:
313
-        # Max number of failed data requests, so set
314
-        # device status to offline.
315
-        setStatusToOffline()
316
-##end def
317
-
318
-    ### DATABASE FUNCTIONS ###
319
-
320
-def updateDatabase(dData):
321
-    """
322
-    Update the rrdtool database by executing an rrdtool system command.
323
-    Format the command using the data extracted from the sensors.
324
-    Parameters: dData - dictionary object containing data items to be
325
-                        written to the rr database file
326
-    Returns: True if successful, False otherwise
327
-    """
328
- 
329
-    epochTime = getEpochSeconds(dData['time'])
330
-
331
-    # Format the rrdtool update command.
332
-    strFmt = "rrdtool update %s %s:%s:%s:%s:%s:%s"
333
-    strCmd = strFmt % (_RRD_FILE, epochTime, dData['current'], \
334
-             dData['voltage'], dData['power'], dData['battemp'], \
335
-             dData['ambtemp'])
336
-
337
-    if debugMode:
338
-        print("%s" % strCmd) # DEBUG
339
-
340
-    # Run the command as a subprocess.
341
-    try:
342
-        subprocess.check_output(strCmd, shell=True, \
343
-            stderr=subprocess.STDOUT)
344
-    except subprocess.CalledProcessError as exError:
345
-        print("%s: rrdtool update: %s" % \
346
-            (getTimeStamp(), exError.output))
347
-        return False
348
-
349
-    if verboseMode and not debugMode:
350
-        print("database update successful")
351
-
352
-    return True
353
-## end def
354
-
355
-def createGraph(fileName, dataItem, gLabel, gTitle, gStart,
356
-                lower=0, upper=0, trendLine=0, scaleFactor=1,
357
-                autoScale=True, alertLine=""):
358
-    """
359
-    Uses rrdtool to create a graph of specified sensor data item.
360
-    Parameters:
361
-        fileName - name of file containing the graph
362
-        dataItem - data item to be graphed
363
-        gLabel - string containing a graph label for the data item
364
-        gTitle - string containing a title for the graph
365
-        gStart - beginning time of the graphed data
366
-        lower - lower bound for graph ordinate #NOT USED
367
-        upper - upper bound for graph ordinate #NOT USED
368
-        trendLine 
369
-            0, show only graph data
370
-            1, show only a trend line
371
-            2, show a trend line and the graph data
372
-        scaleFactor - amount to pre-scale the data before charting
373
-            the data [default=1]
374
-        autoScale - if True, then use vertical axis auto scaling
375
-            (lower and upper parameters must be zero)
376
-        alertLine - value for which to print a critical
377
-            low voltage alert line on the chart. If not provided
378
-            alert line will not be printed.
379
-    Returns: True if successful, False otherwise
380
-    """
381
-    gPath = _CHARTS_DIRECTORY + fileName + ".png"
382
-    trendWindow = { 'end-1day': 7200,
383
-                    'end-4weeks': 172800,
384
-                    'end-12months': 604800 }
385
- 
386
-    # Format the rrdtool graph command.
387
-
388
-    # Set chart start time, height, and width.
389
-    strCmd = "rrdtool graph %s -a PNG -s %s -e now -w %s -h %s " \
390
-             % (gPath, gStart, _CHART_WIDTH, _CHART_HEIGHT)
391
-   
392
-    # Set the range and scaling of the chart y-axis.
393
-    if lower < upper:
394
-        strCmd  +=  "-l %s -u %s -r " % (lower, upper)
395
-    elif autoScale:
396
-        strCmd += "-A "
397
-    strCmd += "-Y "
398
-
399
-    # Set the chart ordinate label and chart title. 
400
-    strCmd += "-v %s -t %s " % (gLabel, gTitle)
401
- 
402
-    # Show the data, or a moving average trend line over
403
-    # the data, or both.
404
-    strCmd += "DEF:rSeries=%s:%s:LAST " % (_RRD_FILE, dataItem)
405
-    strCmd += "CDEF:dSeries=rSeries,%s,/ " % (scaleFactor)
406
-
407
-    if trendLine == 0:
408
-        strCmd += "LINE1:dSeries#0400ff "
409
-    elif trendLine == 1:
410
-        strCmd += "CDEF:smoothed=dSeries,%s,TREND LINE2:smoothed%s " \
411
-                  % (trendWindow[gStart], _AVERAGE_LINE_COLOR)
412
-    elif trendLine == 2:
413
-        strCmd += "LINE1:dSeries#0400ff "
414
-        strCmd += "CDEF:smoothed=dSeries,%s,TREND LINE2:smoothed%s " \
415
-                  % (trendWindow[gStart], _AVERAGE_LINE_COLOR)
416
-
417
-    if alertLine != "":
418
-        strCmd += "HRULE:%s#FF0000:Critical\ Low\ Voltage " % (alertLine)
419
-     
420
-    if debugMode:
421
-        print("%s\n" % strCmd) # DEBUG
422
-    
423
-    # Run the formatted rrdtool command as a subprocess.
424
-    try:
425
-        result = subprocess.check_output(strCmd, \
426
-                     stderr=subprocess.STDOUT,   \
427
-                     shell=True)
428
-    except subprocess.CalledProcessError as exError:
429
-        print("%s rrdtool graph: %s" % \
430
-              (getTimeStamp(), exError.output))
431
-        return False
432
-
433
-    if verboseMode and not debugMode:
434
-        print("rrdtool graph: %s" % result.decode('utf-8'))
435
-    return True
436
-
437
-## end def
438
-
439
-def generateGraphs():
440
-    """
441
-    Generate graphs for display in html documents.
442
-    Parameters: none
443
-    Returns: nothing
444
-    """
445
-
446
-    # 24 hour stock charts
447
-
448
-    createGraph('24hr_current', 'CUR', 'Amps',
449
-                'Current\ -\ Last\ 24\ Hours', 'end-1day', \
450
-                0, 0, 2, 1000)
451
-    createGraph('24hr_voltage', 'VOLT', 'Volts',
452
-                'Voltage\ -\ Last\ 24\ Hours', 'end-1day', \
453
-                9, 15, 0, 1, True, 11)
454
-    createGraph('24hr_power', 'PWR', 'Watts', 
455
-                'Power\ -\ Last\ 24\ Hours', 'end-1day', \
456
-                0, 0, 2, 1000)
457
-    createGraph('24hr_battemp', 'BTMP', 'deg\ F', 
458
-                'Battery\ Temperature\ -\ Last\ 24\ Hours', 'end-1day', \
459
-                0, 0, 0)
460
-    createGraph('24hr_ambtemp', 'ATMP', 'deg\ F', 
461
-                'Ambient\ Temperature\ -\ Last\ 24\ Hours', 'end-1day', \
462
-                0, 0, 0)
463
-
464
-    # 4 week stock charts
465
-
466
-    createGraph('4wk_current', 'CUR', 'Amps',
467
-                'Current\ -\ Last\ 4\ Weeks', 'end-4weeks', \
468
-                0, 0, 2, 1000)
469
-    createGraph('4wk_voltage', 'VOLT', 'Volts',
470
-                'Voltage\ -\ Last\ 4\ Weeks', 'end-4weeks', \
471
-                9, 15, 0, 1, True, 11)
472
-    createGraph('4wk_power', 'PWR', 'Watts', 
473
-                'Power\ -\ Last\ 4\ Weeks', 'end-4weeks', \
474
-                0, 0, 2, 1000)
475
-    createGraph('4wk_battemp', 'BTMP', 'deg\ F', 
476
-                'Battery\ Temperature\ -\ Last\ 4\ Weeks', 'end-4weeks', \
477
-                0, 0, 2)
478
-    createGraph('4wk_ambtemp', 'ATMP', 'deg\ F', 
479
-                'Ambient\ Temperature\ -\ Last\ 4\ Weeks', 'end-4weeks', \
480
-                0, 0, 2)
481
-
482
-    # 12 month stock charts
483
-
484
-    createGraph('12m_current', 'CUR', 'Amps',
485
-                'Current\ -\ Past\ Year', 'end-12months', \
486
-                0, 0, 2, 1000)
487
-    createGraph('12m_voltage', 'VOLT', 'Volts',
488
-                'Voltage\ -\ Past\ Year', 'end-12months', \
489
-                9, 15, 0, 1, True, 11)
490
-    createGraph('12m_power', 'PWR', 'Watts', 
491
-                'Power\ -\ Past\ Year', 'end-12months', \
492
-                0, 0, 2, 1000)
493
-    createGraph('12m_battemp', 'BTMP', 'deg\ F', 
494
-                'Battery\ Temperature\ -\ Past\ Year', 'end-12months', \
495
-                0, 0, 2)
496
-    createGraph('12m_ambtemp', 'ATMP', 'deg\ F', 
497
-                'Ambient\ Temperature\ -\ Past\ Year', 'end-12months', \
498
-                0, 0, 2)
499
-## end def
500
-
501
-def getCLarguments():
502
-    """
503
-    Get command line arguments.  There are three possible arguments
504
-        -d turns on debug mode
505
-        -v turns on verbose mode
506
-        -p sets the sensor query period
507
-        -c sets the chart update period
508
-    Returns: nothing
509
-    """
510
-    global debugMode, verboseMode, dataRequestInterval, chartUpdateInterval
511
-
512
-    index = 1
513
-    while index < len(sys.argv):
514
-        if sys.argv[index] == '-v':
515
-            verboseMode = True
516
-        elif sys.argv[index] == '-d':
517
-            debugMode = True
518
-            verboseMode = True
519
-        elif sys.argv[index] == '-p':
520
-            try:
521
-                dataRequestInterval = abs(int(sys.argv[index + 1]))
522
-            except:
523
-                print("invalid sensor query period")
524
-                exit(-1)
525
-            index += 1
526
-        elif sys.argv[index] == '-c':
527
-            try:
528
-                chartUpdateInterval = abs(int(sys.argv[index + 1]))
529
-            except:
530
-                print("invalid chart update period")
531
-                exit(-1)
532
-            index += 1
533
-        else:
534
-            cmd_name = sys.argv[0].split('/')
535
-            print("Usage: %s [-d | v] [-p seconds] [-c seconds]" \
536
-                  % cmd_name[-1])
537
-            exit(-1)
538
-        index += 1
539
-##end def
540
-
541
-def main_setup():
542
-    """
543
-    Handles timing of events and acts as executive routine managing
544
-    all other functions.
545
-    Parameters: none
546
-    Returns: nothing
547
-    """
548
-    global power1, battemp, ambtemp, sms
549
-
550
-    signal.signal(signal.SIGTERM, terminateAgentProcess)
551
-    signal.signal(signal.SIGINT, terminateAgentProcess)
552
-
553
-    # Log agent process startup time.
554
-    print '===================\n'\
555
-          '%s starting up node power agent process' % \
556
-                  (getTimeStamp())
557
-
558
-    ## Get command line arguments.
559
-    getCLarguments()
560
-
561
-    ## Exit with error if rrdtool database does not exist.
562
-    if not os.path.exists(_RRD_FILE):
563
-        print('rrdtool database does not exist\n' \
564
-              'use createPowerRrd script to ' \
565
-              'create rrdtool database\n')
566
-        exit(1)
567
-
568
-    # Create sensor objects.  This also initializes each sensor.
569
-    power1 = ina260.ina260(_PWR_SENSOR_ADDR, _BUS_NUMBER,
570
-                            debug=debugMode)
571
-    battemp = tmp102.tmp102(_BAT_TMP_SENSOR_ADDR, _BUS_NUMBER,
572
-                            debug=debugMode)
573
-    ambtemp = tmp102.tmp102(_AMB_TMP_SENSOR_ADDR, _BUS_NUMBER,
574
-                            debug=debugMode)
575
-    # Create instance of SMS alert class
576
-    sms = smsalert.smsalert(_SMS_CALLSIGN, _SMS_PASSCODE, debug=debugMode)
577
-
578
-## end def
579
-
580
-def main_loop():
581
-    # last time output JSON file updated
582
-    lastDataRequestTime = -1
583
-    # last time charts generated
584
-    lastChartUpdateTime = - 1
585
-    # last time the rrdtool database updated
586
-    lastDatabaseUpdateTime = -1
587
-
588
-    ### MAIN LOOP ###
589
-
590
-    while True:
591
-
592
-        currentTime = time.time() # get current time in seconds
593
-
594
-        # Every data request interval read the sensors and process the
595
-        # data from the sensors.
596
-        if currentTime - lastDataRequestTime > dataRequestInterval:
597
-            lastDataRequestTime = currentTime
598
-            dData = {}
599
-
600
-            # Get the data from the sensors.
601
-            result = getSensorData(dData)
602
- 
603
-            # If get data successful, convert the data and verify thresholds.
604
-            if result:
605
-                result = convertData(dData)
606
-
607
-            # If convert data successful, write data to data files.
608
-            if result:
609
-                result = writeOutputFile(dData)
610
-
611
-            # At the rrdtool database update interval, update the database.
612
-            if result and (currentTime - lastDatabaseUpdateTime > \
613
-                           _DATABASE_UPDATE_INTERVAL):   
614
-                lastDatabaseUpdateTime = currentTime
615
-                ## Update the round robin database with the parsed data.
616
-                result = updateDatabase(dData)
617
-
618
-            setStatus(result)
619
-
620
-        # At the chart generation interval, generate charts.
621
-        if currentTime - lastChartUpdateTime > chartUpdateInterval:
622
-            lastChartUpdateTime = currentTime
623
-            p = multiprocessing.Process(target=generateGraphs, args=())
624
-            p.start()
625
-            
626
-        # Relinquish processing back to the operating system until
627
-        # the next update interval.
628
-
629
-        elapsedTime = time.time() - currentTime
630
-        if verboseMode:
631
-            if result:
632
-                print("update successful: %6f sec\n"
633
-                      % elapsedTime)
634
-            else:
635
-                print("update failed: %6f sec\n"
636
-                      % elapsedTime)
637
-        remainingTime = dataRequestInterval - elapsedTime
638
-        if remainingTime > 0.0:
639
-            time.sleep(remainingTime)
640
-    ## end while
641
-## end def
642
-
643
-if __name__ == '__main__':
644
-    main_setup()
645
-    main_loop()
646 0
deleted file mode 100755
... ...
@@ -1,79 +0,0 @@
1
-#!/usr/bin/python
2
-
3
-# courtsey ruler for editing script - 80 characters max line length
4
-#2345678901234567890123456789012345678901234567890123456789012345678901234567890
5
-
6
-import telnetlib
7
-
8
-_DEFAULT_HOST = '{your APRS-IS server hostname}'
9
-_DEFAULT_PORT = '{your APRS-IS message port}'
10
-_DEFAULT_SERVER = '{your APRS-IS server name}'
11
-
12
-class smsalert:
13
-
14
-    def __init__(self, callsign, passcode, host=_DEFAULT_HOST, \
15
-      port=_DEFAULT_PORT, server=_DEFAULT_SERVER, debug=False):
16
-        """
17
-        Initialize an instance of this class.
18
-        Parameters:
19
-          callsign - amateur radio callsign of user (must be verified)
20
-          passcode - passcode for verified callsign
21
-          host - domain name or IP address of APRS-IS server
22
-          port - port on which the APRS-IS server receives messages
23
-          server - APRS service name
24
-          debug - set equal to True for debug output
25
-        Returns: nothing
26
-        """
27
-        # Initialize class instance variables.
28
-        self.callsign = callsign
29
-        self.passcode = passcode
30
-        self.host = host
31
-        self.port = port
32
-        self.server = server
33
-        self.debug = debug
34
-    ## end def
35
-
36
-    def sendSMS(self, phone_number, text_message):
37
-        """
38
-        Sends an SMS text message to the provided phone number.
39
-        Parameters:
40
-          phone_number - phone number to which to send the text message
41
-          text_message - text message to be sent to the provided phone number
42
-        Returns: True if successful, False otherwise
43
-        """
44
-        # Establish network connection to APRS-IS server.
45
-        tn = telnetlib.Telnet(self.host, self.port)
46
-        tn.read_until('# aprsc 2.1.8-gf8824e8')
47
-
48
-        # Login and verify passcode accepted.
49
-        tn.write('user ' + self.callsign + ' pass ' + self.passcode + '\n')
50
-        response = tn.read_until(self.server)
51
-        if self.debug:
52
-            print('response: ' + response[2:])
53
-        if not response.find('verified'):
54
-            print('smsalert error: unverified user')
55
-            del tn
56
-            return False
57
-
58
-        # Format and send SMS message to SMS gateway.
59
-        cmd = '%s>%s::SMSGTE:@%s %s' % \
60
-          (self.callsign, self.server, phone_number, text_message)
61
-        if self.debug:
62
-            print('cmd: ' + cmd)
63
-        tn.write(cmd + '\n')
64
-        del tn
65
-        return True
66
-    ## end def
67
-## end class
68
-
69
-def test_smsalert():
70
-    # Initialize a telnet instance.  Default host, port, and server
71
-    # automatically defined if not included in function call.
72
-    sm = smsalert('{your callsign}', '{your passcode}', debug=True)
73
-
74
-    # Send a text message to a phone number.
75
-    sm.sendSMS('{your phone number}', 'Test message send from smsalert.py')
76
-## end def
77
-
78
-if __name__ == '__main__':
79
-    test_smsalert()
80 0
deleted file mode 100755
... ...
@@ -1,159 +0,0 @@
1
-#!/usr/bin/python2
2
-#
3
-# Module: tmp102.py
4
-#
5
-# Description: This module acts as an interface between the TMP102 sensor
6
-# and downstream applications that use the data.  Class methods get
7
-# temperature data from the TMP102 sensor. It acts as a library module that
8
-# can be imported into and called from other Python programs.
9
-#
10
-# Copyright 2021 Jeff Owrey
11
-#    This program is free software: you can redistribute it and/or modify
12
-#    it under the terms of the GNU General Public License as published by
13
-#    the Free Software Foundation, either version 3 of the License, or
14
-#    (at your option) any later version.
15
-#
16
-#    This program is distributed in the hope that it will be useful,
17
-#    but WITHOUT ANY WARRANTY; without even the implied warranty of
18
-#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
-#    GNU General Public License for more details.
20
-#
21
-#    You should have received a copy of the GNU General Public License
22
-#    along with this program.  If not, see http://www.gnu.org/license.
23
-#
24
-# Revision History
25
-#   * v10 released 01 June 2021 by J L Owrey; first release
26
-#
27
-#2345678901234567890123456789012345678901234567890123456789012345678901234567890
28
-
29
-# Import the I2C interface library
30
-import smbus
31
-import time
32
-
33
-# Define constants
34
-DEGSYM = u'\xB0'
35
-
36
-# Define TMP102 Device Registers
37
-CONFIG_REG = 0x1
38
-TEMP_REG = 0x0
39
-
40
-# Define default sm bus address.
41
-DEFAULT_BUS_ADDRESS = 0x48
42
-DEFAULT_BUS_NUMBER = 1
43
-
44
-# Define the default sensor configuration.  See the TMP102 data sheet
45
-# for meaning of each bit.  The following bytes are written to the
46
-# configuration register
47
-#     byte 1: 01100000
48
-#     byte 2: 10100000
49
-DEFAULT_CONFIG = 0x60A0
50
-
51
-class tmp102:
52
-
53
-    # Initialize the TMP102 sensor at the supplied address (default
54
-    # address is 0x48), and supplied bus (default is 1).  Creates
55
-    # a new SMBus object for each instance of this class.  Writes
56
-    # configuration data (two bytes) to the TMP102 configuration
57
-    # register.
58
-    def __init__(self, sAddr=DEFAULT_BUS_ADDRESS,
59
-                 sbus=DEFAULT_BUS_NUMBER,
60
-                 config=DEFAULT_CONFIG,
61
-                 debug=False): 
62
-        # Instantiate a smbus object
63
-        self.sensorAddr = sAddr
64
-        self.bus = smbus.SMBus(sbus)
65
-        self.debugMode = debug
66
- 
67
-        # Initialize TMP102 sensor.  
68
-        initData = [(config >> 8), (config & 0x00FF)]
69
-        self.bus.write_i2c_block_data(self.sensorAddr, CONFIG_REG, initData)
70
-
71
-        if self.debugMode:
72
-            # Read the TMP102 configuration register.
73
-            data = self.getInfo()
74
-            print(self)
75
-            print("configuration register: %s %s\n" % data)
76
-    ## end def
77
-
78
-    # Reads the configuration register (two bytes).
79
-    def getInfo(self):
80
-        # Read configuration data
81
-        config = self.bus.read_i2c_block_data(self.sensorAddr, CONFIG_REG, 2)
82
-        configB1 = format(config[0], "08b")
83
-        configB2 = format(config[1], "08b")
84
-        return (configB1, configB2)
85
-    ## end def
86
-
87
-    def getTempReg(self):
88
-        # Read temperature register and return raw binary data for test
89
-        # and debug.
90
-        data = self.bus.read_i2c_block_data(self.sensorAddr, TEMP_REG, 2)
91
-        dataB1 = format(data[0], "08b")
92
-        dataB2 = format(data[1], "08b")
93
-        return (dataB1, dataB2)
94
-    ## end def
95
-
96
-    # Gets the temperature in binary format and converts to degrees
97
-    # Celsius.
98
-    def getTempC(self):
99
-        # Get temperature data from the sensor.
100
-        # TMP102 returns the data in two bytes formatted as follows
101
-        #        -------------------------------------------------
102
-        #    bit | b7  | b6  | b5  | b4  | b3  | b2  | b1  | b0  |
103
-        #        -------------------------------------------------
104
-        # byte 1 | d11 | d10 | d9  | d8  | d7  | d6  | d5  | d4  |
105
-        #        -------------------------------------------------
106
-        # byte 2 | d3  | d2  | d1  | d0  | 0   |  0  |  0  |  0  |
107
-        #        -------------------------------------------------
108
-        # The temperature is returned in d11-d0, a two's complement,
109
-        # 12 bit number.  This means that d11 is the sign bit.
110
-        data=self.bus.read_i2c_block_data(self.sensorAddr, TEMP_REG, 2)
111
-
112
-        if self.debugMode:
113
-            dataB1 = format(data[0], "08b")
114
-            dataB2 = format(data[1], "08b")
115
-            print("Temperature Reg: %s %s" % (dataB1, dataB2))
116
-
117
-        # Format into a 12 bit word.
118
-        bData = ( data[0] << 8 | data[1] ) >> 4
119
-        # Convert from two's complement to integer.
120
-        # If d11 is 1, the the number is a negative two's complement
121
-        # number.  The absolute value is 2^12 - 1 minus the value
122
-        # of d11-d0 taken as a positive number.
123
-        if bData > 0x7FF:  # all greater values are negative numbers
124
-            bData = -(0xFFF - bData)  # 0xFFF is 2^12 - 1
125
-        # convert integer data to Celsius
126
-        tempC = bData * 0.0625 # LSB is 0.0625 deg Celsius
127
-        return tempC
128
-    ## end def
129
-
130
-    def getTempF(self):
131
-        # Convert Celsius to Fahrenheit using standard formula.
132
-        tempF = (9./5.) * self.getTempC() + 32.
133
-        return tempF
134
-    ## end def
135
-## end class
136
-
137
-def testclass():
138
-    # Initialize the smbus and TMP102 sensor.
139
-    ts1 = tmp102(0x48, 1, debug=True)
140
-    # Print out sensor values.
141
-    bAl = False
142
-    while True:
143
-        tempC = ts1.getTempC()
144
-        tempF = ts1.getTempF()
145
-        if bAl:
146
-            bAl = False
147
-            print("\033[42;30m%6.2f%sC  %6.2f%sF                 \033[m" % \
148
-                  (tempC, DEGSYM, tempF, DEGSYM))
149
-        else:
150
-            bAl = True
151
-            print("%6.2f%sC  %6.2f%sF" % \
152
-                  (tempC, DEGSYM, tempF, DEGSYM))
153
-        time.sleep(2)
154
-    ## end while
155
-## end def
156
-
157
-if __name__ == '__main__':
158
-    testclass()
159
-
160 0
deleted file mode 100755
... ...
@@ -1,25 +0,0 @@
1
-#!/bin/bash
2
-# Starts up the node power agent as a background process
3
-# and redirects output to a log file.
4
-
5
-APP_PATH="/home/$USER/bin"
6
-LOG_PATH="/home/$USER/log"
7
-
8
-AGENT_NAME="[n]pwAgent.py"
9
-
10
-PROCESS_ID="$(ps x | awk -v a=$AGENT_NAME '$7 ~ a {print $1}')"
11
-
12
-if [ -n "$PROCESS_ID" ]; then
13
-  if [ "$1" != "-q" ]; then
14
-    printf "node power agent running [%s]\n" $PROCESS_ID
15
-  fi
16
-else
17
-  printf "starting up node agent\n"
18
-  cd $APP_PATH
19
-  if [ "$1" != "" ]; then
20
-    ./$AGENT_NAME $1
21
-  else
22
-    ./$AGENT_NAME >> $LOG_PATH/npwAgent.log 2>&1 &
23
-  fi
24
-fi
25
-
26 0
deleted file mode 100755
... ...
@@ -1,13 +0,0 @@
1
-#!/bin/bash
2
-# Stop the node power agent process and clean up environment.
3
-
4
-AGENT_NAME="[n]pwAgent.py"
5
-
6
-PROCESS_ID="$(ps x | awk -v a=$AGENT_NAME '$7 ~ a {print $1}')"
7
-
8
-if [ -n "$PROCESS_ID" ]; then
9
-  printf "killing node power agent [%s]\n" $PROCESS_ID
10
-  kill $PROCESS_ID
11
-else
12
-  echo node power agent not running
13
-fi
14 0
similarity index 100%
15 1
rename from nodepower/bin/python3/createPowerRrd.py
16 2
rename to nodepower/bin/wo_mux/createPowerRrd.py
17 3
similarity index 100%
18 4
rename from nodepower/bin/python3/ina260.py
19 5
rename to nodepower/bin/wo_mux/ina260.py
20 6
similarity index 100%
21 7
rename from nodepower/bin/python3/npwAgent.py
22 8
rename to nodepower/bin/wo_mux/npwAgent.py
23 9
similarity index 100%
24 10
rename from nodepower/bin/python2/npwstart
25 11
rename to nodepower/bin/wo_mux/npwstart
26 12
similarity index 100%
27 13
rename from nodepower/bin/python2/npwstop
28 14
rename to nodepower/bin/wo_mux/npwstop
29 15
similarity index 100%
30 16
rename from nodepower/bin/python3/smsalert.py
31 17
rename to nodepower/bin/wo_mux/smsalert.py
32 18
similarity index 100%
33 19
rename from nodepower/bin/python3/tmp102.py
34 20
rename to nodepower/bin/wo_mux/tmp102.py