add download feature

This commit is contained in:
Joerg Lehmann 2021-04-05 10:53:49 +02:00
parent ed62c2f36d
commit 37d1d35afa
6 changed files with 149 additions and 9 deletions

View File

@ -94,6 +94,7 @@ func main() {
http.HandleFunc("/logout", logoutHandler) http.HandleFunc("/logout", logoutHandler)
http.HandleFunc("/confirm", confirmHandler) http.HandleFunc("/confirm", confirmHandler)
http.HandleFunc("/metrics", metricsHandler) http.HandleFunc("/metrics", metricsHandler)
http.HandleFunc("/downloadmetrics", downloadmetricsHandler)
http.HandleFunc("/order", orderHandler) http.HandleFunc("/order", orderHandler)
http.HandleFunc("/save_tracker_settings", save_tracker_settingsHandler) http.HandleFunc("/save_tracker_settings", save_tracker_settingsHandler)
http.HandleFunc("/getstripepaymentintent", getstripepaymentintentHandler) http.HandleFunc("/getstripepaymentintent", getstripepaymentintentHandler)

View File

@ -208,6 +208,126 @@ func metricsHandler(response http.ResponseWriter, request *http.Request) {
} }
} }
func downloadmetricsHandler(response http.ResponseWriter, request *http.Request) {
name := getUserName(request)
if name != "" {
deveui, ok := request.URL.Query()["deveui"]
if !ok || len(deveui[0]) < 1 {
log.Println("Url Param 'deveui' is missing")
fmt.Fprintf(response, "Error: deveui is missing")
return
}
// Query()["deveui"] will return an array of items,
// we only want the single item.
mydeveui := deveui[0]
if !(Contains(getMyDevs(name), mydeveui)) {
log.Println("specified 'deveui' does not belong to this user")
fmt.Fprintf(response, "Error: specified deveui does not belong to this user")
return
}
if AboExpired(mydeveui) {
log.Println("specified 'deveui' has an expired abo")
fmt.Fprintf(response, "Error: specified deveui has an expired abo")
return
}
log.Println("Url Param 'deveui' is: " + string(mydeveui))
// Format of start and stop: YYYY-MM-DDTHH:MI:SSZ
stop, ok := request.URL.Query()["stop"]
var mystop string
if !ok || len(stop[0]) < 1 {
log.Println("Url Param 'stop' is missing, set it to now")
mystop = time.Now().Format("2006-01-02T15:04:05Z")
}
if ok {
mystop = stop[0]
}
layout := "2006-01-02T15:04:05Z"
stopDate, err := time.Parse(layout, mystop)
if err != nil {
fmt.Println(err)
}
start, ok := request.URL.Query()["start"]
var mystart string
if !ok || len(start[0]) < 1 {
log.Println("Url Param 'start' is missing, set it to stop minus one day")
t := stopDate.AddDate(0, 0, -1)
mystart = t.Format("2006-01-02T15:04:05Z")
}
if ok {
mystart = start[0]
}
url := "http://localhost:8086/api/v2/query?org=wobischorg"
data := []byte(fmt.Sprintf(`from(bucket:"wobischbucket")
|> range(start: %s, stop: %s)
|> filter(fn: (r) => r._measurement == "measurement")
|> filter(fn: (r) => r._field == "lon" or r._field == "lat" or r._field == "vbat")
|> filter(fn: (r) => r.deveui == "%s")
|> pivot(rowKey:["_time"], columnKey: ["_field"], valueColumn: "_value")`, mystart, mystop, mydeveui))
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
if err != nil {
log.Fatal("Error reading request. ", err)
}
// Set headers
req.Header.Set("Authorization", "Token "+INFLUX_RO_TOKEN)
req.Header.Set("accept", "application/csv")
req.Header.Set("content-type", "application/vnd.flux")
// Set client timeout
client := &http.Client{Timeout: time.Second * 10}
// Send request
resp, err := client.Do(req)
if err != nil {
log.Fatal("Error reading response. ", err)
}
defer resp.Body.Close()
fmt.Println("response Status:", resp.Status)
fmt.Println("response Headers:", resp.Header)
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal("Error reading body. ", err)
}
fmt.Println("response Body:", string(body))
scanner := bufio.NewScanner(strings.NewReader(string(body)))
for scanner.Scan() {
s := strings.Split(scanner.Text(), ",")
fmt.Printf("Scanned Line: %v\n", s)
if (len(s) >= 11) && !(strings.HasPrefix(s[3], "_")) {
t, err := time.Parse(time.RFC3339, s[3])
if err != nil {
fmt.Printf("error converting time: %s\n", s[3])
continue
}
mytime := t.Format("02.01.2006 15:04")
fmt.Fprintf(response, "\"%s\",%s,%s\n", mytime, s[8], s[9])
}
}
} else {
fmt.Fprintf(response, "Only available for logged in Users")
}
}
func vbat2percent(vbat string) int { func vbat2percent(vbat string) int {
i, err := strconv.Atoi(vbat) i, err := strconv.Atoi(vbat)
res := 0 res := 0

View File

@ -1 +1 @@
cat /home/appuser/wo-bisch-web/static/js/fontawesome-5.11.2/all.js |/home/appuser/wo-bisch-web/minify-fa-js.py home,address-card,balance-scale,sign-out-alt,sign-in-alt,calendar,globe,tint,battery-empty,battery-quarter,battery-half,battery-three-quarters,battery-full,battery-slash,envelope,check,lock,exclamation-triangle,cog,plus,shopping-cart,minus,arrow-right,caret-down,map-marked-alt,exclamation-triangle,envelope,shopping-cart >/home/appuser/wo-bisch-web/static/js/fontawesome-5.11.2/all-minified.js cat /home/appuser/wo-bisch-web/static/js/fontawesome-5.11.2/all.js |/home/appuser/wo-bisch-web/minify-fa-js.py home,address-card,balance-scale,sign-out-alt,sign-in-alt,calendar,globe,tint,battery-empty,battery-quarter,battery-half,battery-three-quarters,battery-full,battery-slash,envelope,check,lock,exclamation-triangle,cog,plus,shopping-cart,minus,arrow-right,caret-down,map-marked-alt,exclamation-triangle,envelope,shopping-cart,download >/home/appuser/wo-bisch-web/static/js/fontawesome-5.11.2/all-minified.js

View File

@ -26,6 +26,11 @@
</div> </div>
</div> </div>
<div class="column is-half py-1"> <div class="column is-half py-1">
<a href="/downloadmetrics" id="btn_download" class="button" download>
<span class="icon">
<i class="fa fa-download"></i>
</span>
</a>
</div> </div>
</div> </div>

View File

@ -768,6 +768,8 @@
"cog": [512, 512, [], "f013", "M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"], "cog": [512, 512, [], "f013", "M487.4 315.7l-42.6-24.6c4.3-23.2 4.3-47 0-70.2l42.6-24.6c4.9-2.8 7.1-8.6 5.5-14-11.1-35.6-30-67.8-54.7-94.6-3.8-4.1-10-5.1-14.8-2.3L380.8 110c-17.9-15.4-38.5-27.3-60.8-35.1V25.8c0-5.6-3.9-10.5-9.4-11.7-36.7-8.2-74.3-7.8-109.2 0-5.5 1.2-9.4 6.1-9.4 11.7V75c-22.2 7.9-42.8 19.8-60.8 35.1L88.7 85.5c-4.9-2.8-11-1.9-14.8 2.3-24.7 26.7-43.6 58.9-54.7 94.6-1.7 5.4.6 11.2 5.5 14L67.3 221c-4.3 23.2-4.3 47 0 70.2l-42.6 24.6c-4.9 2.8-7.1 8.6-5.5 14 11.1 35.6 30 67.8 54.7 94.6 3.8 4.1 10 5.1 14.8 2.3l42.6-24.6c17.9 15.4 38.5 27.3 60.8 35.1v49.2c0 5.6 3.9 10.5 9.4 11.7 36.7 8.2 74.3 7.8 109.2 0 5.5-1.2 9.4-6.1 9.4-11.7v-49.2c22.2-7.9 42.8-19.8 60.8-35.1l42.6 24.6c4.9 2.8 11 1.9 14.8-2.3 24.7-26.7 43.6-58.9 54.7-94.6 1.5-5.5-.7-11.3-5.6-14.1zM256 336c-44.1 0-80-35.9-80-80s35.9-80 80-80 80 35.9 80 80-35.9 80-80 80z"],
"download": [512, 512, [], "f019", "M216 0h80c13.3 0 24 10.7 24 24v168h87.7c17.8 0 26.7 21.5 14.1 34.1L269.7 378.3c-7.5 7.5-19.8 7.5-27.3 0L90.1 226.1c-12.6-12.6-3.7-34.1 14.1-34.1H192V24c0-13.3 10.7-24 24-24zm296 376v112c0 13.3-10.7 24-24 24H24c-13.3 0-24-10.7-24-24V376c0-13.3 10.7-24 24-24h146.7l49 49c20.1 20.1 52.5 20.1 72.6 0l49-49H488c13.3 0 24 10.7 24 24zm-124 88c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20zm64 0c0-11-9-20-20-20s-20 9-20 20 9 20 20 20 20-9 20-20z"],
"envelope": [512, 512, [], "f0e0", "M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"], "envelope": [512, 512, [], "f0e0", "M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"],
"envelope": [512, 512, [], "f0e0", "M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"], "envelope": [512, 512, [], "f0e0", "M502.3 190.8c3.9-3.1 9.7-.2 9.7 4.7V400c0 26.5-21.5 48-48 48H48c-26.5 0-48-21.5-48-48V195.6c0-5 5.7-7.8 9.7-4.7 22.4 17.4 52.1 39.5 154.1 113.6 21.1 15.4 56.7 47.8 92.2 47.6 35.7.3 72-32.8 92.3-47.6 102-74.1 131.6-96.3 154-113.7zM256 320c23.2.4 56.6-29.2 73.4-41.4 132.7-96.3 142.8-104.7 173.4-128.7 5.8-4.5 9.2-11.5 9.2-18.9v-19c0-26.5-21.5-48-48-48H48C21.5 64 0 85.5 0 112v19c0 7.4 3.4 14.3 9.2 18.9 30.6 23.9 40.7 32.4 173.4 128.7 16.8 12.2 50.2 41.8 73.4 41.4z"],

View File

@ -26,9 +26,9 @@ var bounds;
var boundsSwitzerland = new L.LatLngBounds([[47.826186, 10.511814], [45.797054, 5.925007]]); var boundsSwitzerland = new L.LatLngBounds([[47.826186, 10.511814], [45.797054, 5.925007]]);
var dstart = moment({ hour: 0 }); var dstart = moment({ hour: 0 });
var start = dstart.utc().format('YYYY-MM-DDTHH:mm:ss[Z]'); var s_start = dstart.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
var dstop = moment(); var dstop = moment();
var stop = dstop.utc().format('YYYY-MM-DDTHH:mm:ss[Z]'); var s_stop = dstop.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
function vbat2icon(percent) { function vbat2icon(percent) {
if (percent <= 20) { if (percent <= 20) {
@ -51,6 +51,14 @@ function vbat2icon(percent) {
return '<span class="' + icon_color + '"><i class="fas ' + fa_battery_string + '"></i>&nbsp;' + percent + ' &percnt;</span>'; return '<span class="' + icon_color + '"><i class="fas ' + fa_battery_string + '"></i>&nbsp;' + percent + ' &percnt;</span>';
} }
function getDownloadFilename(deveui, start, stop) {
var mdstart = moment(start);
var mdstop = moment(stop);
filename = deveui + "_" + mdstart.format('DD.MM.YYYY') + "_bis_" + mdstop.format('DD.MM.YYYY') + ".csv";
console.log(filename);
return filename;
}
function refreshDatapoints(deveui, start, stop) { function refreshDatapoints(deveui, start, stop) {
range = "" range = ""
range = range + "&start=" + start; range = range + "&start=" + start;
@ -131,6 +139,9 @@ function refreshDatapoints(deveui, start, stop) {
} }
$(document).ready(function () { $(document).ready(function () {
params = "deveui=" + deveui + "&alias=" + alias + "&start=" + s_start + "&stop=" + s_stop;
$("#btn_download").attr("href", "/downloadmetrics?" + params);
$("#btn_download").attr("download", getDownloadFilename(deveui, s_start, s_stop));
map = new L.Map('map', { map = new L.Map('map', {
crs: L.CRS.EPSG3857, crs: L.CRS.EPSG3857,
zoomControl: true, zoomControl: true,
@ -157,22 +168,23 @@ $(document).ready(function () {
map.addLayer(tilelayer); map.addLayer(tilelayer);
map.setView(L.latLng(lat, lon), 10); map.setView(L.latLng(lat, lon), 10);
marker = L.marker([lat, lon], { icon: woBischIcon, zIndexOffset: 1000 }).addTo(map); marker = L.marker([lat, lon], { icon: woBischIcon, zIndexOffset: 1000 }).addTo(map);
$('#reportrange span').html(moment(start).locale('de').format('D. MMM YYYY') + ' - ' + moment(stop).locale('de').format('D. MMM YYYY')); $('#reportrange span').html(moment(s_start).locale('de').format('D. MMM YYYY') + ' - ' + moment(s_stop).locale('de').format('D. MMM YYYY'));
refreshDatapoints(deveui, start, stop); refreshDatapoints(deveui, s_start, s_stop);
}); });
$(function () { $(function () {
var start = moment({ hour: 0 }); var start = moment({ hour: 0 });
var end = moment(); var end = moment();
var s_start = start.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
var s_end = end.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
function cb(start, end) { function cb(start, end) {
$('#reportrange span').html(start.locale('de').format('D. MMM YYYY') + ' - ' + end.locale('de').format('D. MMM YYYY')); $('#reportrange span').html(start.locale('de').format('D. MMM YYYY') + ' - ' + end.locale('de').format('D. MMM YYYY'));
s_start = start.utc().format('YYYY-MM-DDTHH:mm:ss[Z]'); s_start = start.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
s_end = end.utc().format('YYYY-MM-DDTHH:mm:ss[Z]'); s_stop = end.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
refreshDatapoints(deveui, s_start, s_end); params = "deveui=" + deveui + "&alias=" + alias + "&start=" + s_start + "&stop=" + s_stop;
$("#btn_download").attr("href", "/downloadmetrics?" + params);
$("#btn_download").attr("download", getDownloadFilename(deveui, s_start, s_stop));
refreshDatapoints(deveui, s_start, s_stop);
} }
$('#reportrange').daterangepicker({ $('#reportrange').daterangepicker({