mqttGeo / mqttGeo.py /
3a5b1d8 3 years ago
1 contributor
194 lines | 7.581kb
#!/usr/bin/python3
import time
import csv2geojs
import json
import paho.mqtt.client as mqtt

MAXLRR=4
filename="mqttGeo.csv"
#filenameStatus="mqttGeo.html"
filenameBase="mqttGeo"


def htmlLatest(deveui,subID,FCnt,timeLatest,lat,lon,err,rssi):
    htmlOutput="<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
    htmlOutput+="<html>\n"
    htmlOutput+="<head>\n"
    htmlOutput+="  <title>mqttGeo Latest</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+=csv2geojs.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.4em; }\n"
    htmlOutput+="#fcnt { font-size: 1.8em; }\n"
    htmlOutput+="#time { font-size: 1.4em; }\n"
    htmlOutput+="#position { display: inline-block; font-size: 1.5em; }\n"
    htmlOutput+="#rssi { font-size: 1.2em; }\n"
    htmlOutput+="button {\n"
    htmlOutput+="  position: relative;\n"
    htmlOutput+="  width: 300px;\n"
    htmlOutput+="  height: 40px;\n"
    htmlOutput+="  margin: 10px auto;\n"
    htmlOutput+="  padding: 0;\n"
    htmlOutput+="  font-size: 22px;\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+="<script type=\"text/javascript\">\n"
    htmlOutput+="setTimeout(function(){\n"
    htmlOutput+="      location = ''\n"
    htmlOutput+="},1200000);\n"
    htmlOutput+="</script>\n"
    htmlOutput+="<body>\n"
    htmlOutput+="<h2>mqttGeo Latest</h2>\n"
    htmlOutput+="  <div id=\"mapid\" style=\"width: 95%; max-width: 400px; height: 200px; margin: auto\"></div>\n"

    if 0 != lat and 0 != lon:
        xmin=0.999999*lon
        xmax=1.000001*lon
        ymin=0.999999*lat
        ymax=1.000001*lat
        htmlOutput+="<script>\n"
        zoomValue=19
        circleOpacity=0.2
        color=csv2geojs.networkSurveyColor(rssi)
        if err < 3:
            err=3
        htmlOutput+="  var mymap = L.map('mapid').setView(["+str(lat)+", "+str(lon)+"], "+str(zoomValue)+");\n"
        htmlOutput+="\n"
        htmlOutput+="  L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token="+csv2geojs.networkSurveySetMapboxApiToken()+"', {\n"
        htmlOutput+="    maxZoom: 20,\n"
        htmlOutput+="    attribution: 'Map data &copy; <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+="  L.circle(["+str(lat)+","+str(lon)+"],{color: '"+color+"', fillcolor: '"+color+"', fillOpacity: "+str(circleOpacity)+", radius:"+str(err)+"}).addTo(mymap);\n"
        htmlOutput+="</script>\n"

    htmlOutput+="<p>\n"
    htmlOutput+="<div id=\"deveui\">"+deveui+"</div>\n"
    htmlOutput+="<div id=\"fcnt\">"+str(FCnt)+"</div>\n"
    htmlOutput+="<div id=\"time\">"+timeLatest+"</div>\n"
    htmlOutput+="<div id=\"position\">"+str(lat)+" "+str(lon)+" "+str(err)+"</div>\n"
    htmlOutput+="<div id=\"rssi\">"+str(rssi)+"</div>\n"
    htmlOutput+="</p>\n"
    htmlOutput+="<p>\n"
    htmlOutput+="<div id=\"reload\"><button class=\"btn-green\" onClick=\"window.location.reload();\">Reload</div>\n"
    htmlOutput+="</p>\n"

    htmlOutput+="</body>\n"
    htmlOutput+="</html>\n"
    filenameStatus=filenameBase+"-"+subID+".html"
    with open(filenameStatus,"w") as f2:
        f2.write(htmlOutput+"\n")
        f2.close

# The callback for when the client receives a CONNACK response from the server.
def on_connect(client, userdata, flags, rc):
    print("Connected with result code "+str(rc))
    client.subscribe("geoloc/#")

# The callback for when a PUBLISH message is received from the server.
def on_message(client, userdata, msg):
    json_data=str(msg.payload.decode('ASCII'))
    parseTopic=msg.topic.split('/')
    if "uplink" in msg.topic:
        csvLine=""
        #print("Uplink received for SubID: "+parseTopic[1]+" and DevEUI: "+parseTopic[3])
        try:
            parsed=json.loads(json_data)
            pattern = '%Y-%m-%dT%H:%M:%S.%f%z'
            epoch = int(time.mktime(time.strptime(parsed['DevEUI_uplink']['Time'], pattern)))
            FCnt=parsed['DevEUI_uplink']['FCntUp']
            csvLine+=parseTopic[1]+","+parseTopic[3]+","+parsed['DevEUI_uplink']['Time']+","+str(epoch)+","+str(FCnt)
            print("Uplink received for SubID: "+parseTopic[1]+" and DevEUI: "+parseTopic[3]+" Fcnt: "+str(FCnt))
        except:
            print("Uh ho")

        lat=0
        lon=0
        err=0
        if parsed['DevEUI_uplink']['payload'] is not None:
            if parsed['DevEUI_uplink']['payload']['messageType'] == "POSITION_MESSAGE":
                try:
                    lat=parsed['DevEUI_uplink']['payload']['gpsLatitude']
                    lon=parsed['DevEUI_uplink']['payload']['gpsLongitude']
                    err=parsed['DevEUI_uplink']['payload']['horizontalAccuracy']
                except:
                    print("[WARN] GPS Timeout")

                
            else:
                print("[WARN] Not a position message:"+parsed['DevEUI_uplink']['payload']['messageType'])
        else:
            print("[WARN] No decoded payload")
        csvLine+=","+str(lat)+","+str(lon)+","+str(err)
        #print(csvLine)

        # Append GW details
        #parsed['DevEUI_uplink']['Lrrs']['Lrr']
        #Lrrid
        #LrrRSSI
        #LrrSNR
        count=0
        rssi=100
        for lrr in parsed['DevEUI_uplink']['Lrrs']['Lrr']:
            count+=1
            #print(lrr['Lrrid'])
            if rssi == 100:
                rssi=lrr['LrrRSSI']
            csvLine+=","+lrr['Lrrid']+","+str(lrr['LrrRSSI'])+","+str(lrr['LrrSNR'])
        i = 0
        for i in range(count,MAXLRR):
            csvLine+=",,,"

        # Appending only if position is different from 0,0
        if 0 != lat and 0 != lon:
            with open(filename,'a+') as f:
                f.write(csvLine+"\n")
                f.close()
        htmlLatest(parseTopic[3],parseTopic[1],FCnt,parsed['DevEUI_uplink']['Time'],lat,lon,err,rssi)

        csv2geojs.networkSurvey(filename,parseTopic[1])




client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message

broker_address="192.168.1.33"
user="esp8266"
password="NjWxXrEMnOeaNtv8b40u"
port=1883
try:
    client.username_pw_set(user, password=password)
except:
    print("[FAILED]MQTT Set")
try:
    client.connect(broker_address, port, 60)
except:
    print("[FAILED]MQTT connect")
client.loop_forever()