1 contributor
#!/usr/bin/python3
import time
import configuration
circleOpacity=0.2
useLeafletLocal=1
MAPBOXTOKEN="pk.eyJ1IjoieWFuaWtjYXdpZHJvbmUiLCJhIjoiY2p4dmlheGtzMDN0dTNoa2R2b2sxZndkNSJ9.Tfd-xcohTT4x7nEe5_6Rxg"
server = configuration.get_server()
# Leaflet
# https://unpkg.com/leaflet@1.7.1/dist/leaflet.js
# https://unpkg.com/leaflet@1.7.1/dist/leaflet.css
def networkSurveyColor(rssi):
color="#888"
if float(rssi) < -105:
color="#f00"
elif float(rssi) < -95:
color="#ff6600"
elif float(rssi) < -85:
color="#ffa500"
elif float(rssi) < -80:
color="#ffab40"
else:
color="#15ab00"
return color
def networkSurveySetLeaflet(useLocal):
global useLeafletLocal
if True is useLocal:
useLeafletLocal=1
else:
useLeafletLocal=0
def networkSurveyAddLeaflet():
global useLeafletLocal
leaflet=""
leafletCssPath="leaflet.css"
leafletJsPath="leaflet.js"
if useLeafletLocal is 0:
leafletCssPath="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css"
leafletJsPath="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js"
leaflet+=" <link rel=\"stylesheet\" href=\""+leafletCssPath+"\"\n"
leaflet+=" integrity=\"sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==\"\n"
leaflet+=" crossorigin=\"\"/>\n"
leaflet+=" <script src=\""+leafletJsPath+"\"\n"
leaflet+=" integrity=\"sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==\"\ncrossorigin=\"\"/>\n"
leaflet+=" </script>\n"
return leaflet
def networkSurveySetMapboxApiToken():
global MAPBOXTOKEN
return MAPBOXTOKEN
def networkSurvey(filename, subId, devEUI = None, fileOutput= True):
global server
global circleOpacity
start_time = time.time()
htmlOutput="<!DOCTYPE html>\n"
htmlOutput+="<html>\n"
htmlOutput+="<head>\n"
htmlOutput+=" <title>"+server['name']+"</title>\n"
htmlOutput+=" <meta charset=\"utf-8\" />\n"
htmlOutput+=" <meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"
htmlOutput+=" <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n"
htmlOutput+=networkSurveyAddLeaflet()
htmlOutput+="<style>\n"
htmlOutput+="html {\n"
htmlOutput+=" font-family: \"Lucida Sans\", sans-serif; text-align: center;\n"
htmlOutput+="}\n"
htmlOutput+="#deveui { font-size: 1.1em; }\n"
htmlOutput+="#fcnt { font-size: 1.4em; }\n"
htmlOutput+="#time { font-size: 1.1em; }\n"
htmlOutput+="#position { display: inline-block; font-size: 1.1em; }\n"
htmlOutput+="button {\n"
htmlOutput+=" position: relative;\n"
htmlOutput+=" width: 200px;\n"
htmlOutput+=" height: 24px;\n"
htmlOutput+=" margin: 8px auto;\n"
htmlOutput+=" padding: 0;\n"
htmlOutput+=" font-size: 16px;\n"
htmlOutput+=" text-align: center;\n"
htmlOutput+=" color: white;\n"
htmlOutput+=" border: none;\n"
htmlOutput+=" outline: none;\n"
htmlOutput+=" cursor: pointer;\n"
htmlOutput+=" overflow: hidden;\n"
htmlOutput+=" text-shadow: 0 1px 2px rgba(0, 0, 0, 0.25);\n"
htmlOutput+=" transition: transform 0.4s ease-in-out;\n"
htmlOutput+="}\n"
htmlOutput+=".btn-green {\n"
htmlOutput+=" background: #1abc9c;\n"
htmlOutput+=" border-bottom: 2px solid #12ab8d;\n"
htmlOutput+=" box-shadow: inset 0 -2px #12ab8d;\n"
htmlOutput+="}\n"
htmlOutput+="</style>\n"
htmlOutput+="</head>\n"
htmlOutput+="<body>\n"
if fileOutput is True:
htmlOutput += "<h2>"+filename+" - "+subId+"</h2>"
htmlOutput+=" <div id=\"mapid\" style=\"width: 95%; max-width: 400px; height: 400px; margin: auto\"></div>\n"
htmlOutput+="\n"
htmlOutput+="<script>\n"
latMin=90
lonMin=180
latMax=-90
lonMax=-180
pointList=""
count = 0
countRaw = 0
lastLine=""
with open(filename, "rt") as fin:
lines=fin.readlines()
for line in lines:
part=line.split(',')
countRaw += 1
if subId == part[0]:
if devEUI is None:
lastLine=line
if part[5] is not "0" and part[6] is not "0":
count += 1
color=networkSurveyColor(part[9])
jsLine=" L.circle(["+part[5]+","+part[6]+"],{color: '"+color+"', fillcolor: '"+color+"', fillOpacity: "+str(circleOpacity)+", radius:XXXX}).addTo(mymap);\n"
if float(part[5]) > latMax:
latMax=float(part[5])
if float(part[5]) < latMin:
latMin=float(part[5])
if float(part[6]) > lonMax:
lonMax=float(part[6])
if float(part[6]) < lonMin:
lonMin=float(part[6])
pointList+=jsLine
elif part[1] == devEUI:
lastLine=line
if part[5] is not "0" and part[6] is not "0":
count += 1
color=networkSurveyColor(part[9])
jsLine=" L.circle(["+part[5]+","+part[6]+"],{color: '"+color+"', fillcolor: '"+color+"', fillOpacity: "+str(circleOpacity)+", radius:XXXX}).addTo(mymap);\n"
if float(part[5]) > latMax:
latMax=float(part[5])
if float(part[5]) < latMin:
latMin=float(part[5])
if float(part[6]) > lonMax:
lonMax=float(part[6])
if float(part[6]) < lonMin:
lonMin=float(part[6])
pointList+=jsLine
fin.close()
# Adapt Zoom to Max(DeltaLat, DeltaLon)
latDelta=latMax-latMin
lonDelta=lonMax-lonMin
posDelta=latDelta
zoomValue=13
if lonDelta > latDelta:
posDelta = lonDelta
if posDelta < 0.00075:
zoomValue=19
elif posDelta < 0.0015:
zoomValue=18
elif posDelta < 0.003:
zoomValue=17
elif posDelta < 0.006:
zoomValue=16
elif posDelta < 0.012:
zoomValue=15
#print(str(posDelta)+" : "+str(zoomValue))
# Adapt Radius to number of circles
radiusValue=5
if count < 50:
radiusValue=1
elif count < 100:
radiusValue=10
elif count < 500:
radiusValue=5
elif count < 1000:
radiusValue=2
elif count < 2000:
radiusValue=1
pointList=pointList.replace("XXXX",str(radiusValue))
#print(str(posDelta))
latMid=(latMin+latMax)/2
lonMid=(lonMin+lonMax)/2
htmlOutput+=" var mymap = L.map('mapid').setView(["+str(latMid)+", "+str(lonMid)+"], "+str(zoomValue)+");\n"
htmlOutput+="\n"
htmlOutput+=" L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token="+networkSurveySetMapboxApiToken()+"', {\n"
htmlOutput+=" maxZoom: 20,\n"
htmlOutput+=" attribution: 'Map data © <a href=\"https://www.openstreetmap.org/copyright\">OpenStreetMap</a> contributors, ' +\n"
htmlOutput+=" 'Imagery © <a href=\"https://www.mapbox.com/\">Mapbox</a>',\n"
htmlOutput+=" id: 'mapbox/streets-v11',\n"
htmlOutput+=" tileSize: 512,\n"
htmlOutput+=" zoomOffset: -1\n"
htmlOutput+=" }).addTo(mymap);\n"
htmlOutput+="\n"
htmlOutput+= pointList
htmlOutput+="</script>\n"
deltaTime = float(int(100*(time.time() - start_time)))/100
htmlOutput+="<p>Took: "+str(deltaTime)+" seconds</p>\n"
if countRaw != 0:
#print(lastLine)
part=lastLine.split(',')
lastOutput="<p>\n"
lastOutput+="<div id=\"deveui\">"+part[1]+"</div>\n"
lastOutput+="<div id=\"fcnt\">"+part[4]+"</div>\n"
lastOutput+="<div id=\"time\">"+part[2]+"</div>\n"
lastOutput+="<div id=\"position\">"+part[5]+" "+part[6]+" "+part[7]+"</div>\n"
lastOutput+="<div id=\"reload\"><button class=\"btn-green\" onClick=\"window.location.reload();\">Reload</div>\n"
lastOutput+="</p>\n"
htmlOutput+=lastOutput
htmlOutput+="</body>\n"
htmlOutput+="</html>\n"
if fileOutput is True:
filenameSurvey="networkSurvey-"+str(subId)+".html"
with open(filenameSurvey,"w") as f:
f.write(htmlOutput+"\n")
f.close()
return htmlOutput