From a804cc70f5f64b1ea4c9427bff4da2faa64fc028 Mon Sep 17 00:00:00 2001 From: Chteufleur Date: Mon, 2 Jan 2017 19:18:18 +0100 Subject: [PATCH] Add notification system on temperture. --- controllers/addTemp.go | 9 +++ models/notification/notification.go | 106 ++++++++++++++++++++++++++++ models/sensor/sensor.go | 89 +++++++++++++++++++++-- xmpp/xmpp.go | 15 +++- 4 files changed, 214 insertions(+), 5 deletions(-) create mode 100644 models/notification/notification.go diff --git a/controllers/addTemp.go b/controllers/addTemp.go index 4ecc0bb..f525646 100644 --- a/controllers/addTemp.go +++ b/controllers/addTemp.go @@ -6,6 +6,7 @@ import ( "github.com/astaxie/beego" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/notification" "git.kingpenguin.tk/chteufleur/datahouse.git/models/sensor" "git.kingpenguin.tk/chteufleur/datahouse.git/models/temperature" temperatureTmp "git.kingpenguin.tk/chteufleur/datahouse.git/models/temperature/temp" @@ -38,6 +39,14 @@ func (c *AddTempController) Get() { s = sensor.GetSensorByMac(mac) } + // Notification treatment + for _, notifId := range s.GetNotificationsIds() { + notif := notification.GetNotificationCondition(notifId) + if notif != nil { + notif.Notify(int64(val), s.GetName()+": "+valStr+"°C") + } + } + addToTempBdd(s, val) saveInBDD(s, val) diff --git a/models/notification/notification.go b/models/notification/notification.go new file mode 100644 index 0000000..6a4ec9d --- /dev/null +++ b/models/notification/notification.go @@ -0,0 +1,106 @@ +package notification + +import ( + "strconv" + + "github.com/astaxie/beego/orm" + + "git.kingpenguin.tk/chteufleur/datahouse.git/xmpp" + + "git.kingpenguin.tk/chteufleur/datahouse.git/models/database" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/user" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/utils" +) + +const ( + UPPER = ">" + UPPER_OR_EQUALS = ">=" + LOWER = "<" + LOWER_OR_EQUALS = "<=" + EQUALS = "==" + NOT_EQUALS = "!=" +) + +type NotificationCondition struct { + Id int64 + UserId int64 + Condition string + Value int64 +} + +func init() { + orm.RegisterModel(new(NotificationCondition)) +} + +func AddNotificationCondition(userId int64, condition string, value int64) { + o := orm.NewOrm() + o.Using(database.Alias) + _, _ = o.Insert(&NotificationCondition{UserId: userId, Condition: condition, Value: value}) +} + +func UpdateNotificationCondition(id, userId int64, condition string, value int64) { + o := orm.NewOrm() + o.Using(database.Alias) + + n := GetNotificationCondition(id) + if o.Read(n) == nil { + n.UserId = userId + n.Condition = condition + n.Value = value + o.Update(n) + } +} + +func DeleteNotificationCondition(id int64) { + o := orm.NewOrm() + o.Using(database.Alias) + o.Delete(&NotificationCondition{Id: id}) +} + +func GetNotificationCondition(id int64) *NotificationCondition { + o := orm.NewOrm() + o.Using(database.Alias) + + var ret = new(NotificationCondition) + var maps []orm.Params + _, err := o.QueryTable(new(NotificationCondition)).Filter("Id", id).Values(&maps) + if err == nil { + for _, m := range maps { + ret.Id = utils.GetInt(m, "Id") + ret.UserId = utils.GetInt(m, "UserId") + ret.Condition = utils.GetString(m, "Condition") + ret.Value = utils.GetInt(m, "Value") + } + } + + return ret +} + +func (n *NotificationCondition) IsConditionValidate(val int64) bool { + ret := false + + if n.Condition == UPPER { + ret = (val > n.Value) + } else if n.Condition == UPPER_OR_EQUALS { + ret = (val >= n.Value) + } else if n.Condition == LOWER { + ret = (val < n.Value) + } else if n.Condition == LOWER_OR_EQUALS { + ret = (val <= n.Value) + } else if n.Condition == EQUALS { + ret = (val == n.Value) + } else if n.Condition == NOT_EQUALS { + ret = (val != n.Value) + } + + return ret +} + +func (n *NotificationCondition) Notify(val int64, message string) { + if n.IsConditionValidate(val) { + u := user.GetUser(n.UserId) + if u != nil && u.JID != "" { + xmpp_manager.SendMessage(u.JID, "", "["+n.Condition+" "+strconv.FormatInt(n.Value, 10)+"] "+message) + } + } +} diff --git a/models/sensor/sensor.go b/models/sensor/sensor.go index 0225d58..bd79015 100644 --- a/models/sensor/sensor.go +++ b/models/sensor/sensor.go @@ -1,17 +1,26 @@ package sensor import ( + "strconv" + "strings" + "github.com/astaxie/beego/orm" "git.kingpenguin.tk/chteufleur/datahouse.git/models/database" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/notification" "git.kingpenguin.tk/chteufleur/datahouse.git/models/utils" ) +const ( + NOTIFICATION_DELIMITER = "," +) + type SensorTable struct { - Id int64 - SensorMAC string - Description string - Interval int64 + Id int64 + SensorMAC string + Description string + Interval int64 + Notifications string } func init() { @@ -32,6 +41,7 @@ func GetSensorByMac(sensorMac string) *SensorTable { ret.SensorMAC = utils.GetString(m, "SensorMAC") ret.Description = utils.GetString(m, "Description") ret.Interval = utils.GetInt(m, "Interval") + ret.Notifications = utils.GetString(m, "Notifications") break } } @@ -70,6 +80,7 @@ func GetAllSensor() []SensorTable { r.SensorMAC = utils.GetString(m, "SensorMAC") r.Description = utils.GetString(m, "Description") r.Interval = utils.GetInt(m, "Interval") + r.Notifications = utils.GetString(m, "Notifications") ret = append(ret, *r) } @@ -91,6 +102,7 @@ func GetSensor(id int64) *SensorTable { ret.SensorMAC = utils.GetString(m, "SensorMAC") ret.Description = utils.GetString(m, "Description") ret.Interval = utils.GetInt(m, "Interval") + ret.Notifications = utils.GetString(m, "Notifications") } } return ret @@ -108,6 +120,33 @@ func UpdateSensor(mac, description string, interval int64) { } } +func (ss *SensorTable) update() { + o := orm.NewOrm() + o.Using(database.Alias) + + mac := ss.SensorMAC + s := GetSensorByMac(mac) + if o.Read(s) == nil { + s.Description = ss.Description + s.Interval = ss.Interval + s.Notifications = ss.Notifications + o.Update(s) + } +} + +func UpdateSensorWithNotifications(mac, description string, interval int64, notifications string) { + o := orm.NewOrm() + o.Using(database.Alias) + + s := GetSensorByMac(mac) + if o.Read(s) == nil { + s.Description = description + s.Interval = interval + s.Notifications = notifications + o.Update(s) + } +} + func AddSensor(sensorMac string) { o := orm.NewOrm() o.Using(database.Alias) @@ -125,3 +164,45 @@ func DeleteSensor(sensorId int64) { o.Using(database.Alias) o.Delete(&SensorTable{Id: sensorId}) } + +func (s *SensorTable) GetName() string { + ret := s.Description + if s.Description == "" { + ret = s.SensorMAC + } + return ret +} + +func (s *SensorTable) GetNotificationsIds() []int64 { + var ret []int64 + for _, idStr := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) { + id, err := strconv.Atoi(idStr) + if err == nil { + ret = append(ret, int64(id)) + } + } + return ret +} + +func (s *SensorTable) AddNotification(n notification.NotificationCondition) { + s.Notifications += NOTIFICATION_DELIMITER + strconv.FormatInt(n.Id, 10) + s.update() +} + +func (s *SensorTable) DeleteNotification(n notification.NotificationCondition) { + newNotificationStr := "" + for _, idStr := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) { + id, err := strconv.Atoi(idStr) + if err == nil { + if int64(id) != n.Id { + if newNotificationStr != "" { + newNotificationStr += NOTIFICATION_DELIMITER + } + newNotificationStr += idStr + } + } + } + + s.Notifications = newNotificationStr + s.update() +} diff --git a/xmpp/xmpp.go b/xmpp/xmpp.go index e30df82..3a476a9 100644 --- a/xmpp/xmpp.go +++ b/xmpp/xmpp.go @@ -41,11 +41,12 @@ var ( stream = new(xmpp.Stream) client = new(xmpp.XMPP) - Debug = beego.AppConfig.String("XMPP_DEBUG") == "true" + Debug = false ) func init() { log.SetLogger(variables.LogType, variables.LogParams) + Debug = beego.AppConfig.String("XMPP_DEBUG") == "true" } func must(v interface{}, err error) interface{} { @@ -99,6 +100,18 @@ func SendPresence(status, tpye, message string) { client.Out <- xmpp.Presence{From: jid.Domain, Show: status, Type: tpye, Status: message} } +func SendMessage(to, subject, message string) { + m := xmpp.Message{From: jid.Domain, To: to, Type: "chat"} + mBody := xmpp.MessageBody{Value: message} + m.Body = append(m.Body, mBody) + + if subject != "" { + m.Subject = subject + } + + client.Out <- m +} + func execDiscoCommand(iq *xmpp.Iq) { log.Info("Discovery item iq received") reply := iq.Response(xmpp.IQTypeResult)