allow min/max alerting for weight

This commit is contained in:
Joerg Lehmann 2021-08-21 17:06:42 +02:00
parent f8a59825e6
commit 9e494e077f
7 changed files with 131 additions and 18 deletions

View File

@ -19,6 +19,7 @@ type OneMetric struct {
Readonly bool Readonly bool
Alarmactive string Alarmactive string
Smsnumber string Smsnumber string
Minmax string
Timestamp string Timestamp string
Temperature string Temperature string
Humidity string Humidity string
@ -370,6 +371,7 @@ func getLastMetrics(deveui string) OneMetric {
res.Readonly = false res.Readonly = false
res.Alarmactive = getDevAlarmactive(deveui) res.Alarmactive = getDevAlarmactive(deveui)
res.Smsnumber = getDevSmsnumber(deveui) res.Smsnumber = getDevSmsnumber(deveui)
res.Minmax = getDevMinmax(deveui)
res.ActiveUntil = getActiveUntil(deveui) res.ActiveUntil = getActiveUntil(deveui)
res.DaysUntilDeactivated = CalcDaysUntil(res.ActiveUntil) res.DaysUntilDeactivated = CalcDaysUntil(res.ActiveUntil)
return res return res

View File

@ -55,6 +55,7 @@ type Dev struct {
Alias string Alias string
Alarmactive string Alarmactive string
Smsnumber string Smsnumber string
Minmax string
ActiveUntil string // Abo bezahlt bis TT.MM.YYYY ActiveUntil string // Abo bezahlt bis TT.MM.YYYY
} }
@ -105,7 +106,7 @@ func updateScaleSettings(scaleSettings Dev) error {
defer conn.Close() defer conn.Close()
// SET object // SET object
_, err := conn.Do("HMSET", devPrefix+scaleSettings.Deveui, "alias", scaleSettings.Alias, "alarmactive", scaleSettings.Alarmactive, "smsnumber", scaleSettings.Smsnumber) _, err := conn.Do("HMSET", devPrefix+scaleSettings.Deveui, "alias", scaleSettings.Alias, "alarmactive", scaleSettings.Alarmactive, "smsnumber", scaleSettings.Smsnumber, "minmax", scaleSettings.Minmax)
if err != nil { if err != nil {
return err return err
} }
@ -217,6 +218,28 @@ func getDevSmsnumber(deveui string) string {
return res return res
} }
func getDevMinmax(deveui string) string {
res := "0,0"
if deveui == "" {
return res
}
conn := globalPool.Get()
defer conn.Close()
logit("getDevMinMax: Deveui: " + deveui)
minmax, err := redis.String(conn.Do("HGET", devPrefix+deveui, "minmax"))
if err == nil {
logit("getDevAlarmactive: minmax: " + minmax)
res = minmax
} else {
log.Print(err)
}
return res
}
func getActiveUntil(deveui string) string { func getActiveUntil(deveui string) string {
res := "" res := ""

View File

@ -86,24 +86,41 @@ func save_scale_settingsHandler(response http.ResponseWriter, request *http.Requ
return return
} }
minmax, ok5 := request.URL.Query()["minmax"]
if !ok5 || len(minmax[0]) < 1 {
log.Println("Url Param 'minmax' is missing")
fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"minmax must be specified in URL\" }")
return
}
myminmax := minmax[0]
match2, _ := regexp.MatchString(`^[0-9]{1,6},[0-9]{1,6}$`, myminmax)
if !(match2) {
log.Println("Url Param 'minmax' is not valid")
fmt.Fprintf(response, "{ \"rc\": 12, \"msg\": \"minmax is not valid, must be in in format 50000,80000\" }")
return
}
var mydev Dev var mydev Dev
mydev.Deveui = mydeveui mydev.Deveui = mydeveui
mydev.Alias = myalias mydev.Alias = myalias
mydev.Alarmactive = myalarmactive mydev.Alarmactive = myalarmactive
mydev.Smsnumber = mysmsnumber mydev.Smsnumber = mysmsnumber
mydev.Minmax = myminmax
// now we try to save the settings // now we try to save the settings
err := updateScaleSettings(mydev) err := updateScaleSettings(mydev)
if err != nil { if err != nil {
log.Println("Error to Update Device Settings") log.Println("Error to Update Device Settings")
fmt.Fprintf(response, "{ \"rc\": 6, \"msg\": \"error with saving device settings\" }") fmt.Fprintf(response, "{ \"rc\": 7, \"msg\": \"error with saving device settings\" }")
return return
} else { } else {
fmt.Fprintf(response, "{ \"rc\": 0, \"msg\": \"SUCCESS\" }") fmt.Fprintf(response, "{ \"rc\": 0, \"msg\": \"SUCCESS\" }")
} }
} else { } else {
fmt.Fprintf(response, "{ \"rc\": 7, \"msg\": \"Only available for logged in users\" }") fmt.Fprintf(response, "{ \"rc\": 8, \"msg\": \"Only available for logged in users\" }")
} }
} }

View File

@ -34,6 +34,16 @@
<p id="smsnumber_errormsg" class="help is-danger"></p> <p id="smsnumber_errormsg" class="help is-danger"></p>
</div> </div>
<div class="field">
<label class="label">Minimum, Maximum (in Gramm)</label>
<div class="control has-icons-right">
<input id="minmax" class="input" type="text" maxlength="16"> <span id="minmax_exclamation" class="icon is-small is-right">
<i class="fas fa-exclamation-triangle"></i>
</span>
</div>
<p id="minmax_errormsg" class="help is-danger"></p>
</div>
<div class="is-size-7"> <div class="is-size-7">
Device ID: <span id="deveui"></span> Device ID: <span id="deveui"></span>
</div> </div>
@ -103,12 +113,13 @@ Sie erhalten eine E-Mail, sobald die Zahlung erfolgreich abgeschlossen ist.
<p class="is-size-2 is-size-5-mobile has-text-centered has-text-weight-bold" ><span class="alias" id="alias_{{.Deveui}}">{{.Alias}}</span>{{ if not .Readonly }}<a class="show-modal" class="block-link"><span style="float:right;" class="icon is-size-4 is-size-5-mobile"><i class="fa fa-cog"></i></span></a>{{ end }}</p> <p class="is-size-2 is-size-5-mobile has-text-centered has-text-weight-bold" ><span class="alias" id="alias_{{.Deveui}}">{{.Alias}}</span>{{ if not .Readonly }}<a class="show-modal" class="block-link"><span style="float:right;" class="icon is-size-4 is-size-5-mobile"><i class="fa fa-cog"></i></span></a>{{ end }}</p>
<p id="alarmactive_{{.Deveui}}" hidden>{{.Alarmactive}}</p> <p id="alarmactive_{{.Deveui}}" hidden>{{.Alarmactive}}</p>
<p id="smsnumber_{{.Deveui}}" hidden>{{.Smsnumber}}</p> <p id="smsnumber_{{.Deveui}}" hidden>{{.Smsnumber}}</p>
<p id="minmax_{{.Deveui}}" hidden>{{.Minmax}}</p>
<p id="lastmeasurement_{{.Deveui}}" class="has-text-centered">letzte &uuml;bermittelte Messung: {{.Timestamp}}</p> <p id="lastmeasurement_{{.Deveui}}" class="has-text-centered">letzte &uuml;bermittelte Messung: {{.Timestamp}}</p>
<div id="{{.Deveui}}"> <div id="{{.Deveui}}">
<div class="column is-full notification is-warning"> <div class="column is-full notification is-warning">
<nav class="level"> <nav class="level">
<div class="level-item has-text-centered"> <div class="level-item has-text-centered">
<a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=t"> <a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=t&minmax={{.Minmax}}">
<div> <div>
<p class="icon"><i class="fa fa-thermometer-half"></i></p> <p class="icon"><i class="fa fa-thermometer-half"></i></p>
<p id="temp_{{.Deveui}}" class="title">{{.Temperature}} &deg;C</p> <p id="temp_{{.Deveui}}" class="title">{{.Temperature}} &deg;C</p>
@ -116,7 +127,7 @@ Sie erhalten eine E-Mail, sobald die Zahlung erfolgreich abgeschlossen ist.
</a> </a>
</div> </div>
<div class="level-item has-text-centered"> <div class="level-item has-text-centered">
<a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=h"> <a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=h&minmax={{.Minmax}}">
<div> <div>
<p class="icon"><i class="fa fa-tint"></i></p> <p class="icon"><i class="fa fa-tint"></i></p>
<p id="humidity_{{.Deveui}}" class="title">{{.Humidity}} %</p> <p id="humidity_{{.Deveui}}" class="title">{{.Humidity}} %</p>
@ -132,7 +143,7 @@ Sie erhalten eine E-Mail, sobald die Zahlung erfolgreich abgeschlossen ist.
</div> </div>
{{ else }} {{ else }}
<div class="level-item has-text-centered"> <div class="level-item has-text-centered">
<a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=w"> <a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=w&minmax={{.Minmax}}">
<div> <div>
<p class="icon"><i class="fa fa-balance-scale"></i></p> <p class="icon"><i class="fa fa-balance-scale"></i></p>
<p id="weight_{{.Deveui}}" class="title is-size-2 has-text-weight-bold">{{.Weight_kg}} kg</p> <p id="weight_{{.Deveui}}" class="title is-size-2 has-text-weight-bold">{{.Weight_kg}} kg</p>
@ -141,7 +152,7 @@ Sie erhalten eine E-Mail, sobald die Zahlung erfolgreich abgeschlossen ist.
</div> </div>
{{ end }} {{ end }}
<div class="level-item has-text-centered"> <div class="level-item has-text-centered">
<a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=p"> <a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=p&minmax={{.Minmax}}">
<div> <div>
<p class="icon"><i class="fa fa-cloud"></i></p> <p class="icon"><i class="fa fa-cloud"></i></p>
<p id="pressure_{{.Deveui}}" class="title">{{.Pressure}} hP</p> <p id="pressure_{{.Deveui}}" class="title">{{.Pressure}} hP</p>
@ -149,7 +160,7 @@ Sie erhalten eine E-Mail, sobald die Zahlung erfolgreich abgeschlossen ist.
</a> </a>
</div> </div>
<div class="level-item has-text-centered"> <div class="level-item has-text-centered">
<a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=vp"> <a class="block-link" href="/graph.html?deveui={{.Deveui}}&alias={{.Alias}}&property=vp&minmax={{.Minmax}}">
<div> <div>
<p class="icon"><i class="fa fa-battery-three-quarters"></i></p> <p class="icon"><i class="fa fa-battery-three-quarters"></i></p>
<p id="acculevel_{{.Deveui}}" class="title">{{.BatteryPercent}} %</p> <p id="acculevel_{{.Deveui}}" class="title">{{.BatteryPercent}} %</p>

View File

@ -1,12 +1,13 @@
var chart; var chart;
function drawGraph(deveui, alias, property, start, stop, create_graph) { function drawGraph(deveui, alias, property, start, stop, minmax, create_graph) {
range = "" range = ""
range = range + "&start=" + start; range = range + "&start=" + start;
range = range + "&stop=" + stop; range = range + "&stop=" + stop;
var label; var label;
var labels = {}; var labels = {};
var annotations = {};
var forceNiceScale = true; var forceNiceScale = true;
$(".button").removeClass("is-success"); $(".button").removeClass("is-success");
if (property=="t") { if (property=="t") {
@ -15,12 +16,22 @@ function drawGraph(deveui, alias, property, start, stop, create_graph) {
mysubtitle = 'Temperatur in °C'; mysubtitle = 'Temperatur in °C';
minfunc = function(min) { if (min > 0) { return 0 } else { return min } } minfunc = function(min) { if (min > 0) { return 0 } else { return min } }
maxfunc = function(max) { return max + 5 } maxfunc = function(max) { return max + 5 }
labels = {
offsetX: 40,
offsetY: -5,
align: 'right'
};
} else if (property=="vp") { } else if (property=="vp") {
$("#btn_vp").addClass("is-success"); $("#btn_vp").addClass("is-success");
label = 'Akkuladung'; label = 'Akkuladung';
mysubtitle = 'Akkuladung in Prozent'; mysubtitle = 'Akkuladung in Prozent';
minfunc = function(min) { return 0 } minfunc = function(min) { return 0 }
maxfunc = function(max) { return 100 } maxfunc = function(max) { return 100 }
labels = {
offsetX: 40,
offsetY: -5,
align: 'right'
};
forceNiceScale = false; forceNiceScale = false;
} else if (property=="w") { } else if (property=="w") {
$("#btn_w").addClass("is-success"); $("#btn_w").addClass("is-success");
@ -28,9 +39,19 @@ function drawGraph(deveui, alias, property, start, stop, create_graph) {
mysubtitle = 'Gewicht in Kilogramm'; mysubtitle = 'Gewicht in Kilogramm';
minfunc = function(min) { if (min > 5000) { return min - 2000 } else { return 0 } } minfunc = function(min) { if (min > 5000) { return min - 2000 } else { return 0 } }
maxfunc = function(max) { return max + 2000 } maxfunc = function(max) { return max + 2000 }
annotations = { yaxis: [
{
y: minmax.split(",")[0],
y2: minmax.split(",")[1],
borderColor: '#000',
fillColor: '#00FF00'
}
]
};
labels = { labels = {
offsetX: 50, offsetX: 45,
offsetY: -4, offsetY: -5,
align: 'right',
formatter: function(val, index) { formatter: function(val, index) {
return (val / 1000.0).toFixed(3); return (val / 1000.0).toFixed(3);
} }
@ -41,6 +62,11 @@ function drawGraph(deveui, alias, property, start, stop, create_graph) {
mysubtitle = 'Luftfeuchtigkeit in Prozent'; mysubtitle = 'Luftfeuchtigkeit in Prozent';
minfunc = function(min) { return 0 } minfunc = function(min) { return 0 }
maxfunc = function(max) { return 100 } maxfunc = function(max) { return 100 }
labels = {
offsetX: 40,
offsetY: -5,
align: 'right'
};
forceNiceScale = false; forceNiceScale = false;
} else if (property=="p") { } else if (property=="p") {
$("#btn_p").addClass("is-success"); $("#btn_p").addClass("is-success");
@ -48,6 +74,11 @@ function drawGraph(deveui, alias, property, start, stop, create_graph) {
mysubtitle = 'Luftdruck in Hektopascal'; mysubtitle = 'Luftdruck in Hektopascal';
minfunc = function(min) { return 900 } minfunc = function(min) { return 900 }
maxfunc = function(max) { return 1060 } maxfunc = function(max) { return 1060 }
labels = {
offsetX: 40,
offsetY: -5,
align: 'right'
};
} else { } else {
label = 'Unknown'; label = 'Unknown';
mysubtitle = 'Unknown'; mysubtitle = 'Unknown';
@ -113,6 +144,7 @@ function drawGraph(deveui, alias, property, start, stop, create_graph) {
max: maxfunc, max: maxfunc,
forceNiceScale: forceNiceScale, forceNiceScale: forceNiceScale,
labels: labels, labels: labels,
opposite: true,
floating: true floating: true
}, },
tooltip: { tooltip: {
@ -120,6 +152,7 @@ function drawGraph(deveui, alias, property, start, stop, create_graph) {
format: 'dd.MM.yyyy HH:mm' format: 'dd.MM.yyyy HH:mm'
} }
}, },
annotations: annotations,
series: [{ series: [{
name: label, name: label,
data: mydata data: mydata
@ -145,6 +178,7 @@ var alias = urlParams.get('alias');
var property = urlParams.get('property'); var property = urlParams.get('property');
var start = urlParams.get('start'); var start = urlParams.get('start');
var stop = urlParams.get('stop'); var stop = urlParams.get('stop');
var minmax = urlParams.get('minmax') || "0,0";
range=""; range="";
if (start == null) { if (start == null) {
@ -161,4 +195,4 @@ if (stop == null) {
$('#reportrange span').html(moment(start).locale('de').format('D. MMM YYYY') + ' - ' + moment(stop).locale('de').format('D. MMM YYYY')); $('#reportrange span').html(moment(start).locale('de').format('D. MMM YYYY') + ' - ' + moment(stop).locale('de').format('D. MMM YYYY'));
drawGraph(deveui, alias, property, start, stop, true); drawGraph(deveui, alias, property, start, stop, minmax, true);

View File

@ -24,32 +24,32 @@ $(function() {
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_end = end.utc().format('YYYY-MM-DDTHH:mm:ss[Z]');
//console.log("Start: " + s_start + ' End: ' + s_end + ' Property: '+ property); //console.log("Start: " + s_start + ' End: ' + s_end + ' Property: '+ property);
drawGraph(deveui, alias, property, s_start,s_end, false); drawGraph(deveui, alias, property, s_start,s_end, minmax, false);
} }
$('#btn_w').on("click", function() { $('#btn_w').on("click", function() {
change_property('w'); change_property('w');
drawGraph(deveui, alias, property, s_start, s_end, false); drawGraph(deveui, alias, property, s_start, s_end, minmax, false);
}); });
$('#btn_t').on("click", function() { $('#btn_t').on("click", function() {
change_property('t'); change_property('t');
drawGraph(deveui, alias, property, s_start, s_end, false); drawGraph(deveui, alias, property, s_start, s_end, minmax, false);
}); });
$('#btn_h').on("click", function() { $('#btn_h').on("click", function() {
change_property('h'); change_property('h');
drawGraph(deveui, alias, property, s_start, s_end, false); drawGraph(deveui, alias, property, s_start, s_end, minmax, false);
}); });
$('#btn_p').on("click", function() { $('#btn_p').on("click", function() {
change_property('p'); change_property('p');
drawGraph(deveui, alias, property, s_start, s_end, false); drawGraph(deveui, alias, property, s_start, s_end, minmax, false);
}); });
$('#btn_vp').on("click", function() { $('#btn_vp').on("click", function() {
change_property('vp'); change_property('vp');
drawGraph(deveui, alias, property, s_start, s_end, false); drawGraph(deveui, alias, property, s_start, s_end, minmax, false);
}); });
$('#reportrange').daterangepicker({ $('#reportrange').daterangepicker({

View File

@ -7,6 +7,8 @@ function validate(what, text) {
var re = /^[a-zA-Z0-9 ]{1,25}$/; var re = /^[a-zA-Z0-9 ]{1,25}$/;
} else if (what == 'smsnumber') { } else if (what == 'smsnumber') {
var re = /^\+[0-9]{11,11}$/; var re = /^\+[0-9]{11,11}$/;
} else if (what == 'minmax') {
var re = /^[0-9]{1,6},[0-9]{1,6}$/;
} }
return re.test(text); return re.test(text);
} }
@ -50,11 +52,13 @@ $( document ).ready(function() {
$(".show-modal").click(function() { $(".show-modal").click(function() {
$("#alias_exclamation").hide(); $("#alias_exclamation").hide();
$("#smsnumber_exclamation").hide(); $("#smsnumber_exclamation").hide();
$("#minmax_exclamation").hide();
var alias = $(this).prev().html(); var alias = $(this).prev().html();
var deveui = $(this).prev().attr('id').replace("alias_",""); var deveui = $(this).prev().attr('id').replace("alias_","");
$('#deveui').html(deveui); $('#deveui').html(deveui);
var alarmactive = $('#alarmactive_'+deveui).html(); var alarmactive = $('#alarmactive_'+deveui).html();
var smsnumber = $('#smsnumber_'+deveui).html(); var smsnumber = $('#smsnumber_'+deveui).html();
var minmax = $('#minmax_'+deveui).html();
$("#alias").val(alias); $("#alias").val(alias);
console.log(alarmactive); console.log(alarmactive);
@ -64,6 +68,7 @@ $( document ).ready(function() {
$('#checkbox').prop('checked', false); $('#checkbox').prop('checked', false);
} }
$("#smsnumber").val(smsnumber); $("#smsnumber").val(smsnumber);
$("#minmax").val(minmax);
$("#modal").addClass("is-active"); $("#modal").addClass("is-active");
}); });
@ -183,6 +188,25 @@ $( document ).ready(function() {
$("#smsnumber_exclamation").hide(); $("#smsnumber_exclamation").hide();
} }
if (!validate('minmax',$('#minmax').val())) {
$('#minmax_errormsg').html('Minium,Maximum, Beispiel: 20000,10000');
$("#minmax").addClass("is-danger");
$("#minmax_exclamation").show();
is_valid = false;
} else {
const minmaxArr = $('#minmax').val().split(",");
if ((Number(minmaxArr[1]) > Number(minmaxArr[0])) || (minmaxArr[1] == '0')) {
$('#minmax_errormsg').html('');
$("#minmax").removeClass("is-danger");
$("#minmax_exclamation").hide();
} else {
$('#minmax_errormsg').html('Maximum muss gr&ouml;sser als Minimum sein (oder 0)');
$("#minmax").addClass("is-danger");
$("#minmax_exclamation").show();
is_valid = false;
}
}
if (!(is_valid)) { if (!(is_valid)) {
return; return;
} }
@ -195,6 +219,7 @@ $( document ).ready(function() {
deveui: $('#deveui').html(), deveui: $('#deveui').html(),
alias: $('#alias').val(), alias: $('#alias').val(),
smsnumber: $("#smsnumber").val(), smsnumber: $("#smsnumber").val(),
minmax: $("#minmax").val(),
alarmactive: alarmactive alarmactive: alarmactive
}, },
success: function(response) { success: function(response) {
@ -207,6 +232,7 @@ $( document ).ready(function() {
} }
$('#alarmactive_'+$('#deveui').html()).html(alarmactive); $('#alarmactive_'+$('#deveui').html()).html(alarmactive);
$('#smsnumber_'+$('#deveui').html()).html($('#smsnumber').val()); $('#smsnumber_'+$('#deveui').html()).html($('#smsnumber').val());
$('#minmax_'+$('#deveui').html()).html($('#minmax').val());
} }
}, },
error: function(xhr) { error: function(xhr) {