Files
loradar_tool/APIs/APIs.py
2020-06-04 15:43:16 +10:00

436 lines
15 KiB
Python

#!/usr/bin/env python
# coding: utf-8
# In[ ]:
import glob, matplotlib, pprint, requests, math, seaborn
import pandas as pd
import numpy as np
from collections import Counter
from itertools import repeat
import matplotlib.pyplot as plt
get_ipython().run_line_magic('matplotlib', 'inline')
csv_dic = {}
csv_dic[0] = "ALL csv"
docs = glob.glob("*LoRadar_data.csv")
## Calling the session
for num, name in enumerate(docs):
csv_dic[num+1] = name
df = pd.DataFrame(csv_dic.items(), columns = ["Session Number", "Session Name"])
print(df)
dat_idx = int(input("\nPlease select the Session Number to be used: "))
print("\n")
if dat_idx == 0:
all_dat = []
for doc in docs:
all_dat.append(pd.read_csv(doc, encoding = 'unicode_escape', dtype='unicode'))
data = pd.concat(all_dat)
data.reset_index(inplace=True)
data = data.dropna(subset=["UTC timestamp"])
data = data.drop("index", axis=1)
else:
dat_input = docs[dat_idx - 1]
data = pd.read_csv(dat_input, encoding = 'unicode_escape', dtype='unicode')
## Calling the APIs
api_dic = {}
api_dic[0] = "DeviceList"
api_dic[1] = "ChannelOccupancy"
api_dic[2] = "RSSI"
api_dic[3] = "SNR"
api_dic[4] = "NetworkList"
api_dic[5] = "SpectrumPolicing"
df = pd.DataFrame(api_dic.items(), columns = ["API Number", "API Name"])
print(df)
print("\n")
api_idx = int(input("\nPlease select the API Number to be used: "))
print("\n")
## Network filter
netw_l = list(set(data.loc[data.activation == "ABP"].network))
for num, netw in enumerate(netw_l):
print(num+1,netw)
netw_idx = int(input("\nPlease specify the number corresponding to the desired network (To consider all, enter '0'): "))
print("\n")
if num == 0:
network = None
else:
network = netw_l[netw_idx-1]
## Frequency plan filter
frqb_l = list(set(data.Freq_Plan))
for num, frqb in enumerate(frqb_l):
print(num+1,frqb)
frqb_idx = int(input("\nPlease specify the number corresponding to the desired frequency band (To consider all, enter '0'): "))
print("\n")
if num == 0:
frequencyplan = None
else:
frequencyplan = frqb_l[frqb_idx-1]
## Manufacturer filter
manu_l = list(set(data.loc[data.activation=="OTAA"].deveui_manufacturer))
for num, manu in enumerate(manu_l):
print(num+1,manu)
manu_idx = int(input("\nPlease specify the number corresponding to the desired manufacturer (To consider all, enter '0'): "))
print("\n")
if num == 0:
manufacturer = None
else:
manufacturer = manu_l[manu_idx-1]
## List of APIs
def DeviceList(data=data, network=None, frequencyplan=None, manufacturer=None):
# This lists identified devices
# Optional filters are 'network', 'frequencyplan', 'manufacturer'
arg_list = [network, frequencyplan, manufacturer]
# Applying the filters
for i in range(len(arg_list)):
if i == 0:
if network != None:
nwk = network
else:
nwk = data["network"]
elif i == 1:
if frequencyplan != None:
freqplan = frequencyplan
else:
freqplan = data["Freq_Plan"]
elif i == 2:
if manufacturer != None:
manf = manufacturer
else:
manf = data["deveui_manufacturer"]
# Output the result
result = data.loc[(data["Freq_Plan"] == freqplan) &
(data["network"] == nwk) &
(data["deveui_manufacturer"] == manf)]
result = result[["DevEUI or DevAddr", "Freq_Plan",
"network", "deveui_manufacturer"]]
return(result.to_json(orient='records'))
def ChannelOccupancy(data=data, datarate=None, frequencyplan=None):
# This lists channel-wise packet distribution
# Optional filters can be 'datarate' and 'frequencyplan'
arg_list = [datarate, frequencyplan]
for i in range(len(arg_list)):
if i == 0:
if datarate != None:
dr = datarate
else:
dr = data["datarate"]
elif i == 1:
if frequencyplan != None:
freqplan = frequencyplan
else:
freqplan = data["Freq_Plan"]
# Applying the filters
filt = data.loc[(data["datarate"] == dr) & (data["Freq_Plan"] == freqplan)]
# Cleaning the data format
filt = list(zip(filt["datarate"].str.strip(), filt["frequency"].astype(float)/1000000))
# Counting packets
count = Counter(filt)
df = pd.DataFrame(count.values(),
index=pd.MultiIndex.from_tuples(count.keys())).unstack(1)
result = df.fillna(0)[0].sort_index(axis=0)
# Converting to percentage
result = result.div(result.values.sum()/100)
return(result.round(2).to_json(orient='columns'))
def RSSI(data=data, network=None, frequencyplan=None, manufacturer=None):
# This shows the distribution of RSSI in percentage
# Optional filters are 'network', 'frequencyplan', 'manufacturer'
arg_list = [network, frequencyplan, manufacturer]
# Applying the filters
for i in range(len(arg_list)):
if i == 0:
if network != None:
nwk = network
else:
nwk = data["network"]
elif i == 1:
if frequencyplan != None:
freqplan = frequencyplan
else:
freqplan = data["Freq_Plan"]
elif i == 2:
if manufacturer != None:
manf = manufacturer
else:
manf = data["deveui_manufacturer"]
# Output the result
result = data.loc[(data["Freq_Plan"] == freqplan) &
(data["network"] == nwk) &
(data["deveui_manufacturer"] == manf)]
# Create a new dataframe of the RSSI
rssi_data = zip(Counter(result["RSSI"]).keys(), Counter(result["RSSI"]).values())
result = pd.DataFrame(rssi_data, columns = ["RSSI", "Percentage"])
# Converting to percentage
result["Percentage"] = np.round((result["Percentage"]/result["Percentage"].sum())*100, 3)
#return(result)
return(result.to_json(orient='records'))
def SNR(data=data, network=None, frequencyplan=None, manufacturer=None):
# This shows the distribution of RSSI in percentage
# Optional filters are 'network', 'frequencyplan', 'manufacturer'
arg_list = [network, frequencyplan, manufacturer]
# Applying the filters
for i in range(len(arg_list)):
if i == 0:
if network != None:
nwk = network
else:
nwk = data["network"]
elif i == 1:
if frequencyplan != None:
freqplan = frequencyplan
else:
freqplan = data["Freq_Plan"]
elif i == 2:
if manufacturer != None:
manf = manufacturer
else:
manf = data["deveui_manufacturer"]
# Output the result
result = data.loc[(data["Freq_Plan"] == freqplan) &
(data["network"] == nwk) &
(data["deveui_manufacturer"] == manf)]
# Create a new dataframe of the RSSI
snr_data = zip(Counter(result["SNR"]).keys(), Counter(result["SNR"]).values())
result = pd.DataFrame(snr_data, columns = ["SNR", "Percentage"])
# Converting to percentage
result["Percentage"] = np.round((result["Percentage"]/result["Percentage"].sum())*100, 3)
#return(result)
return(result.to_json(orient='records'))
def NetworkList(data=data, frequencyplan=None, manufacturer=None):
# This lists identified devices
# Optional filters are 'frequencyplan', 'manufacturer'
arg_list = [frequencyplan, manufacturer]
# Applying the filters
for i in range(len(arg_list)):
if i == 0:
if frequencyplan != None:
freqplan = frequencyplan
else:
freqplan = data["Freq_Plan"]
elif i == 1:
if manufacturer != None:
manf = manufacturer
else:
manf = data["deveui_manufacturer"]
result = data.loc[(data["Freq_Plan"] == freqplan) &
(data["deveui_manufacturer"] == manf)]
# Split it from the original dataframe by DevAddr or DevEUI
# Output the result
l_freq = []
freq_p = list(set(result["Freq_Plan"]))
if len(freq_p) > 1:
for a, b in result.groupby("Freq_Plan", sort=False):
l_freq.append(b.sort_values(by=["sec_diff"]))
for i in range(len(l_freq)):
print(freq_p[i])
result = l_freq[i].groupby("network").nunique()["DevEUI or DevAddr"]
print(result.to_json(orient='columns'))
else:
print(freq_p[0])
result = l_freq[0].groupby("network").nunique()["DevEUI or DevAddr"]
print(result.to_json(orient='columns'))
def SpectrumPolicing(data=data):
plt.rcParams['axes.facecolor'] = 'white'
plt.rcParams['axes.edgecolor'] = 'black'
plt.rcParams['grid.alpha'] = .9
plt.rcParams['grid.color'] = "black"
matplotlib.rcParams['axes.linewidth'] = 3
plt.rc('grid', linestyle=":")
seaborn.set_context("poster", font_scale=2, rc={"lines.linewidth": 3})
fig, ax = plt.subplots()
fig.set_size_inches(40, 40)
#AS923
size = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]
sf7_250 = [23.17, 30.85, 35.97, 43.65, 51.33, 59.01, 66.69, 74.37, 82.05, 87.17, 94.85]
sf7 = [46.34, 61.7, 71.94, 87.3, 102.66, 118.02, 133.38, 148.74, 164.1, 174.34, 189.7]
sf8 = [82.43, 113.15, 133.63, 164.35, 184.84, 215.55, 236.03, 266.75, 287.23, 317.95, 338.43]
sf9 = [164.86, 205.82, 246.78, 287.74, 328.7, 390.14, 431.1, 472.06, 513.02, 574.46, 615.42]
sf10 = [288.77, 370.69, 452.61, 534.53, 616.45, 698.37, 780.29, 862.21, 944.13, 1026.05, 1107.97]
sf11 = [577.54, 823.3, 987.14, 1150.98, 1314.82, 1478.66, 1724.42, 1888.26, 2052.1, 2215.94, 2461.7]
sf12 = [1155.07, 1482.75, 1810.43, 2138.11, 2465.79, 2793.47, 3121.15, 3448.83, 3776.51, 4104.19, 4431.87]
#AU915 has no 250 and sf11 & 12
all_sf = [sf7_250, sf7, sf8, sf9, sf10, sf11, sf12]
tx_sf = []
times24h = (24*60*60)/(30*1000)
for i in all_sf:
fixed = [times24h*x for x in i]
tx_sf.append(fixed)
all_sf = np.column_stack(tx_sf)
idx = ["SF7 (250kHz)", "SF7 (125kHz)", "SF8 (125kHz)", "SF9 (125kHz)", "SF10 (125kHz)", "SF11 (125kHz)", "SF12 (125kHz)"]
boundary = pd.DataFrame(all_sf.transpose(), columns=size, index=idx)
boundary = boundary.transpose()
cols = ["dimgrey", "red", "saddlebrown", "blue", "orange", "purple", "green", "black"]
# Upper Boundary
upper_b = list(repeat(14000,boundary.shape[0]))
boundary.plot(ax=ax, linewidth=5,
color = cols)
# Creating Fills
ax.fill_between(boundary.index, boundary.iloc[:,0], boundary.iloc[:,1],
where=boundary.iloc[:,1] >= boundary.iloc[:,0], facecolor='dimgrey',
alpha=0.1)
ax.fill_between(boundary.index, boundary.iloc[:,1], boundary.iloc[:,2],
where=boundary.iloc[:,2] >= boundary.iloc[:,1], facecolor='red',
alpha=0.1)
ax.fill_between(boundary.index, boundary.iloc[:,2], boundary.iloc[:,3],
where=boundary.iloc[:,3] >= boundary.iloc[:,2], facecolor='saddlebrown',
alpha=0.1)
ax.fill_between(boundary.index, boundary.iloc[:,3], boundary.iloc[:,4],
where=boundary.iloc[:,4] >= boundary.iloc[:,3], facecolor='blue',
alpha=0.1)
ax.fill_between(boundary.index, boundary.iloc[:,4], boundary.iloc[:,5],
where=boundary.iloc[:,5] >= boundary.iloc[:,4], facecolor='orange',
alpha=0.1)
ax.fill_between(boundary.index, boundary.iloc[:,5], boundary.iloc[:,6],
where=boundary.iloc[:,6] >= boundary.iloc[:,5], facecolor='purple',
alpha=0.1)
ax.fill_between(boundary.index, boundary.iloc[:,6], upper_b,
where=upper_b >= boundary.iloc[:,6], facecolor='green',
alpha=0.1)
#posy, ytextvals = plt.yticks()
#posx, xtextvals = plt.xticks()
#plt.yticks(posy, boundary.index, rotation=0, fontsize=50, va="center")
#plt.xticks(posx, , rotation=0, fontsize=50, va="top")
devs = []
devname = []
for a, b in data.groupby("DevEUI or DevAddr", sort=False):
if b.shape[0] > 1:
for c, d in b.groupby(["bandwidth", "datarate"], sort=False):
if d.shape[0] > 1:
if "-" in list(d.tx_interval[1:]):
error_idx = list(d.tx_interval[1:]).index("-")
new_tx = d.drop(d.index[error_idx+1])
new_dsize = d.drop(d.index[error_idx+1])
avg_tx = np.mean(new_tx.tx_interval[1:].apply(pd.to_numeric))
avg_size = np.mean(new_dsize["size"][1:].apply(pd.to_numeric))
else:
avg_tx = np.mean(d.tx_interval[1:].apply(pd.to_numeric))
avg_size = np.mean(d["size"][1:].apply(pd.to_numeric))
else:
avg_tx = list(d.tx_interval)[0]
avg_size = list(d["size"])[0]
stats = [int(float(c[0])/1000), c[1].strip(), avg_tx, avg_size]
devname.append(a)
devs.append(stats)
devs = np.asarray(devs)
# Assigning Colours
col_l = []
for i in devs:
if (i[0] == "250") & (i[1] == "SF7"):
col_l.append(cols[0])
elif (i[0] == "125") & (i[1] == "SF7"):
col_l.append(cols[1])
elif (i[0] == "125") & (i[1] == "SF8"):
col_l.append(cols[2])
elif (i[0] == "125") & (i[1] == "SF9"):
col_l.append(cols[3])
elif (i[0] == "125") & (i[1] == "SF10"):
col_l.append(cols[4])
elif (i[0] == "125") & (i[1] == "SF11"):
col_l.append(cols[5])
elif (i[0] == "125") & (i[1] == "SF12"):
col_l.append(cols[6])
elif (i[0] == "500"):
col_l.append(cols[7])
# Plotting the Markers (Devices)
plt.scatter(y=devs[:,2].astype(float), x=devs[:,3].astype(float),
c=col_l,
marker='x', s=500, linewidth=5)
plt.ylim(0,14000)
ax.tick_params(axis='both', which='major', pad=15)
plt.ylim(0,14000)
plt.xlabel("Packet Size [Bytes]", labelpad=15)
plt.ylabel("Transmission Interval [s]", labelpad=30)
plt.title("Observed device-wise transmission intervals against respective spectrum policy regions", pad=70, size=60)
if api_idx == 0:
print(DeviceList())
elif api_idx == 1:
print(ChannelOccupancy())
elif api_idx == 2:
print(RSSI())
elif api_idx == 3:
print(SNR())
elif api_idx == 4:
print(NetworkList())
elif api_idx == 5:
print(SpectrumPolicing())