first try of implementing sms alerts

This commit is contained in:
Joerg Lehmann 2019-07-12 19:11:34 +02:00
parent d172f04081
commit 85ea0e2b06
3 changed files with 208 additions and 2 deletions

41
alert.go Normal file
View File

@ -0,0 +1,41 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"time"
"net/http"
"net/url"
)
func sendSMS(phonenumber string, alertMessage string) {
myurl := fmt.Sprintf("https://api.smsapi.com/sms.do?to=%s&message=%s&format=json",phonenumber,url.QueryEscape(alertMessage))
req, err := http.NewRequest("GET", myurl, nil)
if err != nil {
log.Fatal("Error reading request. ", err)
}
req.Header.Set("Authorization", "Bearer IQ4vRG2JvNOmYmrYz6RuSwAanYZgd2hHGwtN62kq")
client := &http.Client{Timeout: time.Second * 10}
resp, err := client.Do(req)
if err != nil {
log.Fatal("Error reading response. ", err)
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal("Error reading body. ", err)
}
fmt.Printf("%s\n", body)
}
func sendAlert(deveui string, alertMessage string) {
fmt.Printf("sendAlert: deveui=%s, message=%s\n", deveui, alertMessage)
sendSMS("41765006123",alertMessage)
}

View File

@ -86,6 +86,7 @@ type payload_1 struct {
// Global variables // Global variables
var file *os.File var file *os.File
var alertMap map[string]string
func DecodePayload(s string, deveui string, devaddr string, lrrlat float32, lrrlon float32, write2file bool) { func DecodePayload(s string, deveui string, devaddr string, lrrlat float32, lrrlon float32, write2file bool) {
var ba []byte var ba []byte
@ -123,7 +124,7 @@ func DecodePayload(s string, deveui string, devaddr string, lrrlat float32, lrrl
// Time of first Packet // Time of first Packet
var tfp = (time.Now().Unix() / 60) - int64(pl_1.O) var tfp = (time.Now().Unix() / 60) - int64(pl_1.O)
var step = int64(pl_1.O / 7) var step = int64(pl_1.O / 7)
t := pl_1.T t := pl_1.T
WriteDatapoint(tfp,deveui,devaddr,pl_1.Vbat,pl_1.H1,pl_1.P1,pl_1.W1,0,0,t,lrrlat,lrrlon) WriteDatapoint(tfp,deveui,devaddr,pl_1.Vbat,pl_1.H1,pl_1.P1,pl_1.W1,0,0,t,lrrlat,lrrlon)
t = t + int16(pl_1.TC1) t = t + int16(pl_1.TC1)
@ -159,7 +160,11 @@ func DecodePayload(s string, deveui string, devaddr string, lrrlat float32, lrrl
WriteDatapoint(tfp,deveui,devaddr,pl_128.Vbat,pl_128.H,pl_128.P,pl_128.W,pl_128.W1,pl_128.W2,pl_128.T,lrrlat,lrrlon) WriteDatapoint(tfp,deveui,devaddr,pl_128.Vbat,pl_128.H,pl_128.P,pl_128.W,pl_128.W1,pl_128.W2,pl_128.T,lrrlat,lrrlon)
} }
} }
// Send alert if necessary
if val, ok := alertMap[deveui]; ok {
sendAlert(deveui,val)
delete(alertMap,deveui)
}
} }
func WriteDatapoint(mytime int64, deveui string, devaddr string, v uint8, h uint8, p uint8, w uint16, w1 int32, w2 int32, t int16, lrrlat float32, lrrlon float32) { func WriteDatapoint(mytime int64, deveui string, devaddr string, v uint8, h uint8, p uint8, w uint16, w1 int32, w2 int32, t int16, lrrlat float32, lrrlon float32) {
@ -182,6 +187,18 @@ func WriteDatapoint(mytime int64, deveui string, devaddr string, v uint8, h uint
} }
WriteStringToFile(s) WriteStringToFile(s)
w_gram := w*5
addValue(deveui,w_gram)
w_loss := getMaxValue(deveui) - w_gram;
if (w_loss > 500) {
// Schwarmalarm!
s = fmt.Sprintf("alert,deveui=%s reason=\"swarmalarm\",w=%di,w_loss=%di %d\n",deveui,w_gram,w_loss,mytime*60*1000*1000*1000)
location, _ := time.LoadLocation("Europe/Zurich")
alertMap[deveui] = fmt.Sprintf("*** Schwarmalarm ***\n%s\n%s\nGewichtsverlust: %d g",getDevAlias(deveui),time.Unix(mytime*60,0).In(location).Format("02.01.2006 15:04"),w_loss)
WriteStringToFile(s)
}
} }
} }
@ -198,6 +215,11 @@ func WriteStringToFile(s string) {
} }
func main() { func main() {
// Init Redis
initDB()
// Init alertMap
alertMap = make(map[string]string)
// Open Output File // Open Output File
f, err := os.OpenFile(outputfile,os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) f, err := os.OpenFile(outputfile,os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)

143
persistence.go Normal file
View File

@ -0,0 +1,143 @@
package main
import (
"fmt"
"time"
"github.com/gomodule/redigo/redis"
)
var globalPool *redis.Pool
const lastvaluesPrefix string = "lastvalues:"
const devPrefix string = "dev:"
func newPool() *redis.Pool {
return &redis.Pool{
// Maximum number of idle connections in the pool.
MaxIdle: 80,
// max number of connections
MaxActive: 12000,
// Dial is an application supplied function for creating and
// configuring a connection.
Dial: func() (redis.Conn, error) {
c, err := redis.Dial("tcp", ":6379")
if err != nil {
panic(err.Error())
}
return c, err
},
}
}
// ping tests connectivity for redis (PONG should be returned)
func ping(c redis.Conn) error {
// Send PING command to Redis
// PING command returns a Redis "Simple String"
// Use redis.String to convert the interface type to string
_, err := redis.String(c.Do("PING"))
if err != nil {
return err
}
return nil
}
func initDB() {
// newPool returns a pointer to a redis.Pool
pool := newPool()
// get a connection from the globalPool (redis.Conn)
conn := pool.Get()
defer conn.Close()
globalPool = pool
// wir machen einen Connection Test
ping(conn)
addValue("0000000000000000",uint16(time.Now().Unix()));
}
func closeDB() {
globalPool.Close()
}
func checkDevAvailable(deveui string) bool {
conn := globalPool.Get()
defer conn.Close()
_, err := redis.String(conn.Do("GET", lastvaluesPrefix + deveui))
if (err == redis.ErrNil) {
return true
} else if err != nil {
return false
}
return false
}
func getMaxValue(deveui string) uint16 {
var res uint16 = 0
var myvalues []uint16
conn := globalPool.Get()
defer conn.Close()
values, _ := redis.Values(conn.Do("LRANGE", lastvaluesPrefix + deveui, 0, -1))
if err := redis.ScanSlice(values, &myvalues); err != nil {
fmt.Println(err)
return 0
}
for _, value := range myvalues {
if (uint16(value) > res) {
res = uint16(value)
}
}
return res
}
func addValue(deveui string, value uint16) {
conn := globalPool.Get()
defer conn.Close()
_, err := conn.Do("LPUSH", lastvaluesPrefix + deveui, value)
if err != nil {
return
}
_, err2 := conn.Do("LTRIM", lastvaluesPrefix + deveui, 0, 4)
if err2 != nil {
return
}
// we set an expiration time of one hour
_, err3 := conn.Do("EXPIRE", lastvaluesPrefix + deveui, 3600)
if err3 != nil {
return
}
}
func getDevAlias(deveui string) string {
res := deveui
if deveui == "" {
return res
}
conn := globalPool.Get()
defer conn.Close()
alias, err := redis.String(conn.Do("HGET", devPrefix+deveui, "alias"))
if err == nil {
res = alias
} else {
res = deveui
}
return res
}