initial commit of model script
This commit is contained in:
parent
2c1d7319f1
commit
aad1a71274
|
|
@ -1 +1,3 @@
|
||||||
sftp-config.json
|
sftp-config.json
|
||||||
|
*.pyc
|
||||||
|
models/
|
||||||
|
|
|
||||||
|
|
@ -64,7 +64,7 @@ class MainActivity extends Activity {
|
||||||
protected static int UDPfinishTime = 0;
|
protected static int UDPfinishTime = 0;
|
||||||
protected static double reportedFinishTime = 0.0;
|
protected static double reportedFinishTime = 0.0;
|
||||||
protected static int repeatCounts = 3;
|
protected static int repeatCounts = 3;
|
||||||
protected static int bytes2send = 10 * Utilities.oneMB; // default 10MB
|
protected static int bytes2send = 100 * Utilities.oneMB; // default 100MB
|
||||||
protected static int currentBandwidth = -1; // bps, default is -1, indicating unlimited
|
protected static int currentBandwidth = -1; // bps, default is -1, indicating unlimited
|
||||||
protected static TextView txt_results;
|
protected static TextView txt_results;
|
||||||
protected static Handler myHandler;
|
protected static Handler myHandler;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
'''
|
||||||
|
Created by Yanzi @ 06/16/2016
|
||||||
|
Last updated by Yanzi @ 08/18/2016
|
||||||
|
color module: terminal text add colors
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
class TerminalColors:
|
||||||
|
'''
|
||||||
|
Currently support purple, cyan, darkcyan, blue, green, yellow, red
|
||||||
|
'''
|
||||||
|
BOLD = '\033[1m'
|
||||||
|
UNDERLINE = '\033[4m'
|
||||||
|
END = '\033[0m'
|
||||||
|
PURPLE = '\033[95m'
|
||||||
|
CYAN = '\033[96m'
|
||||||
|
DARKCYAN = '\033[36m'
|
||||||
|
BLUE = '\033[94m'
|
||||||
|
GREEN = '\033[92m'
|
||||||
|
YELLOW = '\033[93m'
|
||||||
|
RED = '\033[91m'
|
||||||
|
|
||||||
|
|
||||||
|
def colorString(myString, bold=True, underline=False, color='red'):
|
||||||
|
'''
|
||||||
|
Set color of the string, including bold and underline
|
||||||
|
@ param myString: the string
|
||||||
|
@ param bold: flag to set if we want to bold the text
|
||||||
|
@ param underline: flag to set if we want to draw underline
|
||||||
|
@ param color: specify a color name, e.g. 'red' or 'green'
|
||||||
|
(may not show depending on terminal setups)
|
||||||
|
@ return new string wrapped with terminal color indicators
|
||||||
|
'''
|
||||||
|
tmp = myString
|
||||||
|
if bold:
|
||||||
|
tmp = '{1}{0}{2}'.format(
|
||||||
|
tmp, TerminalColors.BOLD, TerminalColors.END)
|
||||||
|
if underline:
|
||||||
|
tmp = '{1}{0}{2}'.format(
|
||||||
|
tmp, TerminalColors.UNDERLINE, TerminalColors.END)
|
||||||
|
if hasattr(TerminalColors, color.upper()):
|
||||||
|
tmp = '{1}{0}{2}'.format(
|
||||||
|
tmp, getattr(TerminalColors, color.upper()), TerminalColors.END)
|
||||||
|
return tmp
|
||||||
|
|
@ -0,0 +1,205 @@
|
||||||
|
'''
|
||||||
|
Created by Yanzi @ 06/16/2016
|
||||||
|
Last updated by Yanzi @ 02/02/2017
|
||||||
|
misc module: all sorts of uncategorized functions
|
||||||
|
'''
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import random
|
||||||
|
import time
|
||||||
|
import threading
|
||||||
|
import numpy as np
|
||||||
|
from math import sqrt
|
||||||
|
from TerminalColors import *
|
||||||
|
|
||||||
|
|
||||||
|
class MyTimer(threading.Thread):
|
||||||
|
'''
|
||||||
|
Threaded timer so it is non-blocking and we can do additional stuff
|
||||||
|
'''
|
||||||
|
def __init__(self, timeInSec):
|
||||||
|
threading.Thread.__init__(self)
|
||||||
|
self.time = timeInSec
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
print "Timer thread kicked in.. START.."
|
||||||
|
time.sleep(self.time)
|
||||||
|
print "Timer thread kicked in.. STOP.."
|
||||||
|
|
||||||
|
|
||||||
|
class EmptyLogger:
|
||||||
|
'''
|
||||||
|
logger base
|
||||||
|
'''
|
||||||
|
def __init__(
|
||||||
|
self, loggerTag, level=logging.DEBUG, logPath=None, printout=False
|
||||||
|
):
|
||||||
|
self.myLogger = logging.getLogger(loggerTag)
|
||||||
|
self.myLogger.setLevel(level)
|
||||||
|
self.ch_file = None
|
||||||
|
self.ch_stream = None
|
||||||
|
formatter = logging.Formatter(
|
||||||
|
'%(asctime)s %(name)s %(levelname)s, %(message)s')
|
||||||
|
if logPath is not None:
|
||||||
|
self.ch_file = logging.FileHandler(logPath, 'w')
|
||||||
|
self.ch_file.setLevel(level)
|
||||||
|
self.ch_file.setFormatter(formatter)
|
||||||
|
self.myLogger.addHandler(self.ch_file)
|
||||||
|
if printout:
|
||||||
|
self.ch_stream = logging.StreamHandler()
|
||||||
|
self.ch_stream.setLevel(level)
|
||||||
|
# ch_stream.setLevel(level)
|
||||||
|
self.ch_stream.setFormatter(formatter)
|
||||||
|
self.myLogger.addHandler(self.ch_stream)
|
||||||
|
self.myLogger.info('logging started')
|
||||||
|
|
||||||
|
def info(self, string):
|
||||||
|
self.myLogger.info(string)
|
||||||
|
|
||||||
|
def debug(self, string):
|
||||||
|
self.myLogger.debug(string)
|
||||||
|
|
||||||
|
def error(self, string):
|
||||||
|
self.myLogger.error(colorString(string))
|
||||||
|
|
||||||
|
def note(self, string):
|
||||||
|
self.myLogger.info(colorString(string, color='blue'))
|
||||||
|
|
||||||
|
def enable(self):
|
||||||
|
if self.ch_file is not None:
|
||||||
|
self.myLogger.addHandler(self.ch_file)
|
||||||
|
if self.ch_stream is not None:
|
||||||
|
self.myLogger.addHandler(self.ch_stream)
|
||||||
|
|
||||||
|
def disable(self):
|
||||||
|
if self.ch_file is not None:
|
||||||
|
self.myLogger.removeHandler(self.ch_file)
|
||||||
|
if self.ch_stream is not None:
|
||||||
|
self.myLogger.removeHandler(self.ch_stream)
|
||||||
|
|
||||||
|
|
||||||
|
def convert2Bool(stuff):
|
||||||
|
'''
|
||||||
|
convert string or integer 0/1 to bool
|
||||||
|
supported ['True', 'true', 'yes', 'y', '1', 1] and vice versa
|
||||||
|
'''
|
||||||
|
return stuff in ['True', 'true', 'yes', 'y', '1', 1]
|
||||||
|
|
||||||
|
|
||||||
|
def abs(num):
|
||||||
|
'''
|
||||||
|
compute absolute number
|
||||||
|
'''
|
||||||
|
return np.abs(num)
|
||||||
|
|
||||||
|
|
||||||
|
def nanratio(lst):
|
||||||
|
'''
|
||||||
|
compute the ratio of nan over all elements in list
|
||||||
|
'''
|
||||||
|
if len(lst) is 0:
|
||||||
|
return 0
|
||||||
|
try:
|
||||||
|
nan_count = np.count_nonzero(np.isnan(lst))
|
||||||
|
except:
|
||||||
|
nan_count = np.sum(np.isnan(lst))
|
||||||
|
if np.isnan(nan_count):
|
||||||
|
return float('nan')
|
||||||
|
return 1.0 * nan_count / len(lst)
|
||||||
|
|
||||||
|
|
||||||
|
def max(lst):
|
||||||
|
'''
|
||||||
|
compute max (excluding nan) of a list of numbers
|
||||||
|
'''
|
||||||
|
if len(lst) is 0:
|
||||||
|
return float('nan')
|
||||||
|
return np.nanmax(lst)
|
||||||
|
|
||||||
|
|
||||||
|
def mean(lst):
|
||||||
|
'''
|
||||||
|
compute mean (excluding nan) of a list of numbers
|
||||||
|
'''
|
||||||
|
if len(lst) is 0:
|
||||||
|
return float('nan')
|
||||||
|
try:
|
||||||
|
tmp = np.count_nonzero(~np.isnan(lst))
|
||||||
|
except:
|
||||||
|
tmp = np.sum(~np.isnan(lst))
|
||||||
|
tmp2 = np.nansum(lst)
|
||||||
|
if tmp is 0 or np.isnan(tmp2):
|
||||||
|
return float('nan')
|
||||||
|
return tmp2 / tmp
|
||||||
|
|
||||||
|
|
||||||
|
def median(lst):
|
||||||
|
'''
|
||||||
|
compute median (excluding nan) of a list of numbers
|
||||||
|
'''
|
||||||
|
if len(lst) is 0:
|
||||||
|
return float('nan')
|
||||||
|
lst = np.array(lst)
|
||||||
|
newlst = lst[~np.isnan(lst)]
|
||||||
|
if len(newlst) is 0:
|
||||||
|
return float('nan')
|
||||||
|
return np.median(newlst)
|
||||||
|
|
||||||
|
|
||||||
|
def std(lst):
|
||||||
|
'''
|
||||||
|
compute std (excluding nan) of a list of numbers
|
||||||
|
'''
|
||||||
|
if len(lst) is 0:
|
||||||
|
return float('nan')
|
||||||
|
try:
|
||||||
|
return np.nanstd(lst)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
lst = np.array(lst)
|
||||||
|
tmp = mean(lst)
|
||||||
|
if np.isnan(tmp):
|
||||||
|
return float('nan')
|
||||||
|
return np.sqrt(mean(abs(lst - tmp)**2))
|
||||||
|
|
||||||
|
|
||||||
|
def getRandomIPAddr():
|
||||||
|
'''
|
||||||
|
derive a random ip address
|
||||||
|
'''
|
||||||
|
return '192.168.1.'+str(random.randint(1, 255))
|
||||||
|
|
||||||
|
|
||||||
|
def getRandomMacAddr():
|
||||||
|
'''
|
||||||
|
derive a random MAC address
|
||||||
|
'''
|
||||||
|
mac = [
|
||||||
|
0x02, 0x08, 0x02,
|
||||||
|
random.randint(0x00, 0x7f),
|
||||||
|
random.randint(0x00, 0xff),
|
||||||
|
random.randint(0x00, 0xff)]
|
||||||
|
return ':'.join(map(lambda x: "%02x" % x, mac))
|
||||||
|
|
||||||
|
|
||||||
|
def which(program):
|
||||||
|
def is_exe(fpath):
|
||||||
|
return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
||||||
|
|
||||||
|
fpath, fname = os.path.split(program)
|
||||||
|
if fpath:
|
||||||
|
if is_exe(program):
|
||||||
|
return program
|
||||||
|
else:
|
||||||
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
|
path = path.strip('"')
|
||||||
|
exe_file = os.path.join(path, program)
|
||||||
|
if is_exe(exe_file):
|
||||||
|
return exe_file
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
print 'Usage: from misc import *'
|
||||||
|
|
@ -0,0 +1,238 @@
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import xml.etree.cElementTree as ET
|
||||||
|
from misc import *
|
||||||
|
|
||||||
|
|
||||||
|
def getVoltage(productname):
|
||||||
|
if productname == "shamu":
|
||||||
|
return 4.2
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
class Model():
|
||||||
|
'''
|
||||||
|
The energy model module
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, isDebuging=False, use_uAh=False):
|
||||||
|
self.freqs = []
|
||||||
|
self.cpu_single_core = {}
|
||||||
|
self.cpu_multi_core = {}
|
||||||
|
'''
|
||||||
|
cpu format: { cpu num:
|
||||||
|
{ freq: [active current, idle current], ...}
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
self.net_wifi = {}
|
||||||
|
self.net_LTE = {}
|
||||||
|
self.net_3G = {}
|
||||||
|
'''
|
||||||
|
net format: { 'prom':
|
||||||
|
{ 'index': [rssi, current, length], ...},
|
||||||
|
'active':
|
||||||
|
{ rssi: [rx current, tx current, rx xput, tx xput]}
|
||||||
|
'tail':
|
||||||
|
{ 'index': [rssi, current, length], ...},
|
||||||
|
}
|
||||||
|
'''
|
||||||
|
self.DEBUG = isDebuging
|
||||||
|
self.logger = None
|
||||||
|
if isDebuging:
|
||||||
|
self.logger = EmptyLogger("Model", printout=True)
|
||||||
|
if use_uAh:
|
||||||
|
self._ratio_uAh_over_mAs = 5 / 18.0
|
||||||
|
else:
|
||||||
|
self._ratio_uAh_over_mAs = 1.0
|
||||||
|
|
||||||
|
def load(self, productname, dir="../models/"):
|
||||||
|
self.voltage = getVoltage(productname)
|
||||||
|
filepath = "{0}/{1}.xml".format(dir, productname)
|
||||||
|
if not os.path.isfile(filepath):
|
||||||
|
self.logger.error("File {0} does not exist.".format(filepath))
|
||||||
|
sys.exit(-1)
|
||||||
|
tree = ET.parse(filepath)
|
||||||
|
root = tree.getroot()
|
||||||
|
cpumodel = root.find("cpumodel")
|
||||||
|
self.parseFreqs(cpumodel.find("freqs"))
|
||||||
|
cores = cpumodel.find("cores")
|
||||||
|
self.parseCPUSingleCore(cores)
|
||||||
|
self.parseCPUMultiCore(cores)
|
||||||
|
netmodel = root.find("netmodel")
|
||||||
|
for net in netmodel.findall("net"):
|
||||||
|
if net.attrib['id'] == 'WIFI':
|
||||||
|
self.parseNet(net, self.net_wifi)
|
||||||
|
elif net.attrib['id'] == 'LTE':
|
||||||
|
self.parseNet(net, self.net_LTE)
|
||||||
|
elif net.attrib['id'] == '3G':
|
||||||
|
self.parseNet(net, self.net_3G)
|
||||||
|
|
||||||
|
def parseNet(self, node, net_node):
|
||||||
|
prom = node.find("prom")
|
||||||
|
if prom is None or prom.attrib['numstates'] == '0':
|
||||||
|
net_node['prom'] = None
|
||||||
|
else:
|
||||||
|
net_node['prom'] = {}
|
||||||
|
for pst in prom.findall("promstate"):
|
||||||
|
net_node['prom'][pst.attrib['index']] = \
|
||||||
|
[int(pst.attrib['index']),
|
||||||
|
int(pst.attrib['prompwr']),
|
||||||
|
int(pst.attrib['promlen'])]
|
||||||
|
|
||||||
|
active = node.find("active")
|
||||||
|
if active is None:
|
||||||
|
net_node['active'] = None
|
||||||
|
else:
|
||||||
|
net_node['active'] = {}
|
||||||
|
for ast in active.findall("activestate"):
|
||||||
|
net_node['active'][int(ast.attrib['rssi'])] = \
|
||||||
|
[int(ast.attrib['rxpwr']),
|
||||||
|
int(ast.attrib['txpwr']),
|
||||||
|
float(ast.attrib['rxxput']),
|
||||||
|
float(ast.attrib['txxput'])]
|
||||||
|
|
||||||
|
tail = node.find("tail")
|
||||||
|
if tail is None or tail.attrib['numstates'] == '0':
|
||||||
|
net_node['tail'] = None
|
||||||
|
else:
|
||||||
|
net_node['tail'] = {}
|
||||||
|
for tst in tail.findall("tailstate"):
|
||||||
|
net_node['tail'][tst.attrib['index']] = \
|
||||||
|
[int(tst.attrib['index']),
|
||||||
|
int(tst.attrib['tailpwr']),
|
||||||
|
int(tst.attrib['taillen'])]
|
||||||
|
|
||||||
|
# print net_node
|
||||||
|
|
||||||
|
def parseCPUMultiCore(self, node):
|
||||||
|
for core in node.findall("core"):
|
||||||
|
if core.attrib['mode'] == 'multicore':
|
||||||
|
myid = int(core.attrib['id'])
|
||||||
|
if myid in self.cpu_multi_core:
|
||||||
|
myfreq = int(core.attrib['freq'])
|
||||||
|
self.cpu_multi_core[myid][myfreq] = \
|
||||||
|
[int(core.attrib['active']),
|
||||||
|
int(core.attrib['idle'])]
|
||||||
|
else:
|
||||||
|
self.cpu_multi_core[myid] = \
|
||||||
|
{int(core.attrib['freq']):
|
||||||
|
[int(core.attrib['active']),
|
||||||
|
int(core.attrib['idle'])]}
|
||||||
|
# print self.cpu_multi_core
|
||||||
|
|
||||||
|
def parseCPUSingleCore(self, node):
|
||||||
|
for core in node.findall("core"):
|
||||||
|
if core.attrib['mode'] == 'singlecore':
|
||||||
|
myid = int(core.attrib['id'])
|
||||||
|
if myid in self.cpu_single_core:
|
||||||
|
myfreq = int(core.attrib['freq'])
|
||||||
|
self.cpu_single_core[myid][myfreq] = \
|
||||||
|
[int(core.attrib['active']),
|
||||||
|
int(core.attrib['idle'])]
|
||||||
|
else:
|
||||||
|
self.cpu_single_core[myid] = \
|
||||||
|
{int(core.attrib['freq']):
|
||||||
|
[int(core.attrib['active']),
|
||||||
|
int(core.attrib['idle'])]}
|
||||||
|
# print self.cpu_single_core
|
||||||
|
|
||||||
|
def parseFreqs(self, node):
|
||||||
|
for freq in node.findall("freq"):
|
||||||
|
self.freqs.append(int(freq.attrib['val']))
|
||||||
|
# if self.DEBUG:
|
||||||
|
# self.logger.debug(self.freqs)
|
||||||
|
|
||||||
|
def get_cpu_energy(self, time_diff, freq, util):
|
||||||
|
'''
|
||||||
|
@param freq: list of cpu frequencies
|
||||||
|
@param util: list of cpu utilization
|
||||||
|
'''
|
||||||
|
if len(freq) != len(util) or len(freq) < 1:
|
||||||
|
self.logger.error("freq & util have different length!")
|
||||||
|
sys.exit(-1)
|
||||||
|
current = 0
|
||||||
|
if len(freq) > 1:
|
||||||
|
db = self.cpu_multi_core
|
||||||
|
for i in xrange(len(freq)):
|
||||||
|
if freq[i] <= 0 or freq[i] not in db[i]:
|
||||||
|
self.logger.error("freq outlier: {0}".format(freq[i]))
|
||||||
|
self.logger.debug(db[i])
|
||||||
|
continue
|
||||||
|
active_current = db[i][freq[i]][0]
|
||||||
|
idle_current = db[i][freq[i]][1]
|
||||||
|
current += util[i] * (active_current - idle_current) + \
|
||||||
|
idle_current
|
||||||
|
else:
|
||||||
|
db = self.cpu_single_core
|
||||||
|
if freq[0] <= 0 or freq[0] not in db[0]:
|
||||||
|
self.logger.error("freq outlier: {0}".format(f))
|
||||||
|
self.logger.debug(db[i])
|
||||||
|
else:
|
||||||
|
active_current = db[0][freq[0]][0]
|
||||||
|
idle_current = db[0][freq[0]][1]
|
||||||
|
current = util[0] * (active_current - idle_current) + \
|
||||||
|
idle_current
|
||||||
|
# derive energy
|
||||||
|
energy = current * time_diff * self._ratio_uAh_over_mAs
|
||||||
|
if self.DEBUG:
|
||||||
|
self.logger.debug("cpu_energy: {0:.4f}".format(energy))
|
||||||
|
return energy
|
||||||
|
|
||||||
|
def get_lte_prom_energy(self, time_diff, rssi, isTX=True):
|
||||||
|
self.logger.error('TODO: not implemented yet')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_lte_tail_energy(self, time_diff, rssi, isTX=True):
|
||||||
|
self.logger.error('TODO: not implemented yet')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_lte_active_energy(self, time_diff, rssi, isTX=True):
|
||||||
|
self.logger.error('TODO: not implemented yet')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_wifi_active_energy(self, time_diff, rssi, isTX=True):
|
||||||
|
table_rssi = sorted(self.net_wifi['active'].keys(), reverse=True)
|
||||||
|
if isTX:
|
||||||
|
currentIdx = 1
|
||||||
|
else:
|
||||||
|
currentIdx = 0
|
||||||
|
# fetch current
|
||||||
|
current = None
|
||||||
|
if rssi >= table_rssi[0]:
|
||||||
|
current = self.net_wifi['active'][table_rssi[0]][currentIdx]
|
||||||
|
elif rssi < table_rssi[-1]:
|
||||||
|
current = self.net_wifi['active'][table_rssi[-1]][currentIdx]
|
||||||
|
else:
|
||||||
|
for i in xrange(1, len(table_rssi)):
|
||||||
|
if rssi >= table_rssi[i]:
|
||||||
|
endp = self.net_wifi['active'][table_rssi[i-1]][currentIdx]
|
||||||
|
startp = self.net_wifi['active'][table_rssi[i]][currentIdx]
|
||||||
|
rssi_diff = table_rssi[i-1] - table_rssi[i]
|
||||||
|
current = (endp + 1.0 * (endp - startp) *
|
||||||
|
(rssi - table_rssi[i-1]) / rssi_diff)
|
||||||
|
break
|
||||||
|
if current is None:
|
||||||
|
self.logger.error("Current {0} is nothing!".format(current))
|
||||||
|
sys.exit(-1)
|
||||||
|
# derive energy
|
||||||
|
energy = current * time_diff * self._ratio_uAh_over_mAs
|
||||||
|
if self.DEBUG:
|
||||||
|
self.logger.debug("wifi_active_energy: {0:.4f}".format(energy))
|
||||||
|
return energy
|
||||||
|
|
||||||
|
def get_wifi_tail_energy(self, time_diff):
|
||||||
|
energy = (time_diff * self.net_wifi['tail']['0'][1] *
|
||||||
|
self._ratio_uAh_over_mAs)
|
||||||
|
if self.DEBUG:
|
||||||
|
self.logger.debug("wifi_tail_energy: {0:.4f}".format(energy))
|
||||||
|
return energy
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print "Usage: from model import *"
|
||||||
|
# debugging..
|
||||||
|
myObj = Model(isDebuging=True)
|
||||||
|
# myObj.load(sys.argv[1])
|
||||||
|
myObj.load("shamu")
|
||||||
|
myObj.get_wifi_tail_energy(1)
|
||||||
|
myObj.get_wifi_active_energy(1, -60, isTX=False)
|
||||||
|
myObj.get_cpu_energy(1, [1036800, 422400], [0, 1])
|
||||||
Loading…
Reference in New Issue