Compare commits
10 Commits
7113e69a91
...
b387657f5a
| Author | SHA1 | Date |
|---|---|---|
|
|
b387657f5a | |
|
|
213e1305d9 | |
|
|
8378253574 | |
|
|
aa1259b3dc | |
|
|
c8ebf02e30 | |
|
|
87891cfd0d | |
|
|
f4ed7afc59 | |
|
|
2e630d4fe1 | |
|
|
a804cc70f5 | |
|
|
84d7c000ae |
|
|
@ -2,10 +2,12 @@ appname = DataHouse
|
|||
httpport = 8080
|
||||
runmode = dev
|
||||
|
||||
mysqluser = "root"
|
||||
mysqlpass = "toto"
|
||||
database = mysql
|
||||
mysqluser = "datahouse_user"
|
||||
mysqlpass = "datahouse_user_password"
|
||||
mysqlurls = "127.0.0.1"
|
||||
mysqldb = "orm_test"
|
||||
mysqldb = "datahouse"
|
||||
row_limit = 100000
|
||||
|
||||
sessionon = true
|
||||
SessionProvider = memory
|
||||
|
|
@ -16,4 +18,7 @@ SessionCookieLifeTime = 3600
|
|||
|
||||
JID = test@kingpenguin.tk
|
||||
PWD = test
|
||||
SERVER = 51.254.205.203
|
||||
PORT = 5222
|
||||
TIMER_PING = 60
|
||||
XMPP_DEBUG = true
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -51,8 +51,9 @@ func (c *LoginController) Post() {
|
|||
|
||||
login := c.GetString("login")
|
||||
passwd := c.GetString("password")
|
||||
token := c.GetString("token")
|
||||
|
||||
if !isLoginOK(login, passwd) {
|
||||
if !isLoginOK(login, passwd, token) {
|
||||
c.Abort("403")
|
||||
}
|
||||
|
||||
|
|
@ -64,7 +65,7 @@ func (c *LoginController) Post() {
|
|||
}
|
||||
}
|
||||
|
||||
func isLoginOK(lgn, pwd string) bool {
|
||||
func isLoginOK(lgn, pwd, token string) bool {
|
||||
ret := false
|
||||
usr := user.GetUserByLogin(lgn)
|
||||
if usr.Id == 0 {
|
||||
|
|
@ -74,9 +75,9 @@ func isLoginOK(lgn, pwd string) bool {
|
|||
log.Info("Standard auth")
|
||||
ret = pwd != "" && pwd == usr.Password
|
||||
|
||||
if !ret && usr.JID != "" {
|
||||
if !ret && usr.JID != "" && token != "" {
|
||||
log.Info("Auth by JID")
|
||||
resp, _ := http.Get(UrlXmppAuth + "?domain=datahouse.kingpenguin.tk&method=POST&jid=" + usr.JID + "&transaction_id=datahouse")
|
||||
resp, _ := http.Get(UrlXmppAuth + "?domain=datahouse.kingpenguin.tk&method=POST&jid=" + usr.JID + "&transaction_id=" + token)
|
||||
httpStatusCode := resp.StatusCode
|
||||
if resp != nil && httpStatusCode == 200 {
|
||||
ret = true
|
||||
|
|
|
|||
|
|
@ -0,0 +1,124 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"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/user"
|
||||
"git.kingpenguin.tk/chteufleur/datahouse.git/models/variables"
|
||||
)
|
||||
|
||||
type NotificationsController struct {
|
||||
beego.Controller
|
||||
}
|
||||
|
||||
type NotificationView struct {
|
||||
Id int64
|
||||
Condition string
|
||||
Value int64
|
||||
Sensor string
|
||||
}
|
||||
|
||||
type SensorView struct {
|
||||
MAC string
|
||||
Name string
|
||||
}
|
||||
|
||||
func (c *NotificationsController) Prepare() {
|
||||
sess := c.GetSession(variables.SessionName)
|
||||
if sess == nil {
|
||||
c.Redirect(variables.LoginRouteNoRegex+variables.UserRoute, 302)
|
||||
} else {
|
||||
c.Data["IsAuthentificated"] = true
|
||||
}
|
||||
|
||||
c.Data["IsNotifications"] = true
|
||||
c.Data["version"] = variables.Version
|
||||
}
|
||||
|
||||
func (c *NotificationsController) Get() {
|
||||
var notifications []NotificationView
|
||||
var notifIds []int64
|
||||
u := c.getUserLogin()
|
||||
if u != nil {
|
||||
notif := notification.GetNotificationConditionByUser(u.Id)
|
||||
for _, nv := range notif {
|
||||
n := new(NotificationView)
|
||||
n.Id = nv.Id
|
||||
n.Condition = nv.Condition
|
||||
n.Value = nv.Value
|
||||
|
||||
sensr := sensor.GetSensorByNotificationId(n.Id)
|
||||
if sensr != nil {
|
||||
n.Sensor = sensr.GetName()
|
||||
notifications = append(notifications, *n)
|
||||
notifIds = append(notifIds, n.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
c.Data["notifications"] = notifications
|
||||
|
||||
var snsrs []SensorView
|
||||
sensors := sensor.GetAllSensor()
|
||||
for _, s := range sensors {
|
||||
snsrs = append(snsrs, SensorView{MAC: s.SensorMAC, Name: s.GetName()})
|
||||
}
|
||||
c.Data["sensors"] = snsrs
|
||||
|
||||
c.TplName = "notifications.tpl"
|
||||
}
|
||||
|
||||
func (c *NotificationsController) Post() {
|
||||
u := c.getUserLogin()
|
||||
|
||||
action := c.Input().Get("action")
|
||||
notifIdStr := c.Input().Get("id")
|
||||
condition := c.Input().Get("condition")
|
||||
valueStr := c.Input().Get("value")
|
||||
sensMAC := c.Input().Get("sensor-mac")
|
||||
|
||||
notifId, errNotifId := strconv.ParseInt(notifIdStr, 10, 64)
|
||||
value, errValue := strconv.ParseInt(valueStr, 10, 64)
|
||||
|
||||
if action == "modif" && errNotifId == nil && errValue == nil {
|
||||
if notification.UpdateNotificationCondition(notifId, u.Id, condition, value) == nil {
|
||||
oldSensor := sensor.GetSensorByNotificationId(notifId)
|
||||
newSensor := sensor.GetSensorByMac(sensMAC)
|
||||
if oldSensor.Id != 0 && newSensor.Id != 0 && oldSensor.Id != newSensor.Id {
|
||||
oldSensor.DeleteNotification(notifId)
|
||||
newSensor.AddNotification(notifId)
|
||||
}
|
||||
}
|
||||
} else if action == "delete" && errNotifId == nil && errValue == nil {
|
||||
notification.DeleteNotificationCondition(notifId)
|
||||
sens := sensor.GetSensorByNotificationId(notifId)
|
||||
if sens.Id != 0 {
|
||||
sens.DeleteNotification(notifId)
|
||||
}
|
||||
} else if action == "add" && errValue == nil {
|
||||
sens := sensor.GetSensorByMac(sensMAC)
|
||||
if sens.Id != 0 {
|
||||
notifId, err := notification.AddNotificationCondition(u.Id, condition, value)
|
||||
if err == nil {
|
||||
sens.AddNotification(notifId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
c.Redirect(variables.NotificationsRoute, 302)
|
||||
}
|
||||
|
||||
func (c *NotificationsController) getUserLogin() *user.User {
|
||||
ret := new(user.User)
|
||||
|
||||
login := c.GetSession(variables.SessionName)
|
||||
switch lo := login.(type) {
|
||||
case string:
|
||||
ret = user.GetUserByLogin(lo)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
|
@ -8,6 +8,7 @@ import (
|
|||
|
||||
"html/template"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
//——————————————————————————————————————————————————————————————————————————————
|
||||
|
|
@ -62,7 +63,8 @@ func (c *ViewTeleinfoController) Prepare() {
|
|||
}
|
||||
|
||||
func (c *ViewTeleinfoController) Get() {
|
||||
c.Data["compteurs"] = teleinfo.GetAllCompteur()
|
||||
compteurs := teleinfo.GetAllCompteur()
|
||||
c.Data["compteurs"] = compteurs
|
||||
|
||||
adresse := c.Ctx.Input.Param(":compteur")
|
||||
cpt := teleinfo.GetCompteurByAdresse(adresse)
|
||||
|
|
@ -75,13 +77,47 @@ func (c *ViewTeleinfoController) Get() {
|
|||
desc = cpt.AdresseCompteur
|
||||
}
|
||||
c.Data["compteurDescription"] = desc
|
||||
dataPower := formatDataSensorTeleInfo(teleinfo.GetAllDataForCompteur(cpt.AdresseCompteur))
|
||||
compteurs := teleinfo.GetAllDataForCompteur(cpt.AdresseCompteur)
|
||||
c.Data["lastHorodate"] = getHorodateHighchart(compteurs[len(compteurs)-1].HorodateGMT)
|
||||
dataPower := formatDataSensorTeleInfo(compteurs)
|
||||
c.Data["dataPower"] = template.JS(dataPower)
|
||||
}
|
||||
|
||||
c.TplName = "teleinfo.tpl"
|
||||
}
|
||||
|
||||
func (c *ViewTeleinfoController) Post() {
|
||||
currentTimeStr := c.GetString("currentTime")
|
||||
adresse := c.Ctx.Input.Param(":compteur")
|
||||
currentTime, err := strconv.ParseInt(currentTimeStr, 10, 64)
|
||||
if err == nil {
|
||||
dateGMT := time.Unix(currentTime/1000-int64(timezoneOffset), 0)
|
||||
data := teleinfo.GetNextData(adresse, dateGMT)
|
||||
dataStr := formatDataToJsonTeleInfo(data)
|
||||
c.Ctx.Output.Body([]byte(dataStr))
|
||||
}
|
||||
}
|
||||
|
||||
func getHorodateHighchart(date time.Time) string {
|
||||
return strconv.FormatInt((date.Unix()+int64(timezoneOffset))*1000, 10)
|
||||
|
||||
}
|
||||
|
||||
func formatDataToJsonTeleInfo(values []teleinfo.TeleinfoTable) string {
|
||||
ret := ""
|
||||
ret += "{\"values\": ["
|
||||
for i := 0; i < len(values); i++ {
|
||||
if i > 0 {
|
||||
ret += ","
|
||||
}
|
||||
horodate := getHorodateHighchart(values[i].HorodateGMT)
|
||||
value := strconv.FormatInt(values[i].PuissanceApparente, 10)
|
||||
ret += "[" + horodate + "," + value + "]"
|
||||
}
|
||||
ret += "]}"
|
||||
return ret
|
||||
}
|
||||
|
||||
func formatDataSensorTeleInfo(values []teleinfo.TeleinfoTable) string {
|
||||
ret := ""
|
||||
ret += "{name : \"Puissance apparente (VA)\",marker : {enabled : true, radius : 3}, data : ["
|
||||
|
|
|
|||
6
main.go
6
main.go
|
|
@ -62,7 +62,7 @@ func main() {
|
|||
time.Sleep(1 * time.Second)
|
||||
models.ChanRuns <- watchlog.EndRun
|
||||
time.Sleep(1 * time.Second)
|
||||
// models.ChanRuns <- xmpp_manager.EndRun
|
||||
go xmpp_manager.Run()
|
||||
|
||||
beego.Run()
|
||||
}
|
||||
|
|
@ -72,10 +72,6 @@ func reborn() {
|
|||
action := <-models.ChanRuns
|
||||
|
||||
switch action {
|
||||
case xmpp_manager.EndRun:
|
||||
go xmpp_manager.Run()
|
||||
log.Info("XMPP Started")
|
||||
|
||||
case watchlog.EndRun:
|
||||
go watchlog.Run()
|
||||
log.Info("Watchlog Started")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,167 @@
|
|||
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) (int64, error) {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
return o.Insert(&NotificationCondition{UserId: userId, Condition: condition, Value: value})
|
||||
}
|
||||
|
||||
func UpdateNotificationCondition(id, userId int64, condition string, value int64) error {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
|
||||
n := GetNotificationCondition(id)
|
||||
if o.Read(n) == nil {
|
||||
n.UserId = userId
|
||||
n.Condition = condition
|
||||
n.Value = value
|
||||
_, err := o.Update(n)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func DeleteNotificationCondition(id int64) {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
o.Delete(&NotificationCondition{Id: id})
|
||||
}
|
||||
|
||||
func GetAllNotificationConditionIds() []int64 {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
|
||||
notif := new(NotificationCondition)
|
||||
var ret []int64
|
||||
var maps []orm.Params
|
||||
_, err := o.QueryTable(notif).Values(&maps)
|
||||
if err == nil {
|
||||
for _, m := range maps {
|
||||
ret = append(ret, utils.GetInt(m, "Id"))
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetAllNotificationCondition() []NotificationCondition {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
|
||||
notif := new(NotificationCondition)
|
||||
var maps []orm.Params
|
||||
var ret []NotificationCondition
|
||||
_, err := o.QueryTable(notif).Values(&maps)
|
||||
if err == nil {
|
||||
for _, m := range maps {
|
||||
n := new(NotificationCondition)
|
||||
n.Id = utils.GetInt(m, "Id")
|
||||
n.UserId = utils.GetInt(m, "UserId")
|
||||
n.Condition = utils.GetString(m, "Condition")
|
||||
n.Value = utils.GetInt(m, "Value")
|
||||
ret = append(ret, *n)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func GetNotificationConditionByUser(idUser int64) []NotificationCondition {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
|
||||
var ret []NotificationCondition
|
||||
var maps []orm.Params
|
||||
_, err := o.QueryTable(new(NotificationCondition)).Filter("UserId", idUser).Values(&maps)
|
||||
if err == nil {
|
||||
for _, m := range maps {
|
||||
n := new(NotificationCondition)
|
||||
n.Id = utils.GetInt(m, "Id")
|
||||
n.UserId = utils.GetInt(m, "UserId")
|
||||
n.Condition = utils.GetString(m, "Condition")
|
||||
n.Value = utils.GetInt(m, "Value")
|
||||
ret = append(ret, *n)
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,25 @@
|
|||
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/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
NOTIFICATION_DELIMITER = ","
|
||||
)
|
||||
|
||||
type SensorTable struct {
|
||||
Id int64
|
||||
SensorMAC string
|
||||
Description string
|
||||
Interval int64
|
||||
Notifications string
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
@ -32,6 +40,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 +79,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 +101,19 @@ 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
|
||||
}
|
||||
|
||||
func GetSensorByNotificationId(notifId int64) *SensorTable {
|
||||
var ret *SensorTable = nil
|
||||
allSensors := GetAllSensor()
|
||||
for _, s := range allSensors {
|
||||
if s.IsContainNotificationId(notifId) {
|
||||
ret = &s
|
||||
break
|
||||
}
|
||||
}
|
||||
return ret
|
||||
|
|
@ -108,6 +131,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 +175,58 @@ 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) IsContainNotificationId(idNotif int64) bool {
|
||||
for _, b := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) {
|
||||
bb, err := strconv.Atoi(b)
|
||||
if err == nil && int64(bb) == idNotif {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *SensorTable) AddNotification(notifId int64) {
|
||||
if s.Notifications != "" {
|
||||
s.Notifications += NOTIFICATION_DELIMITER
|
||||
}
|
||||
s.Notifications += strconv.FormatInt(notifId, 10)
|
||||
s.update()
|
||||
}
|
||||
|
||||
func (s *SensorTable) DeleteNotification(notifId int64) {
|
||||
newNotificationStr := ""
|
||||
for _, idStr := range strings.Split(s.Notifications, NOTIFICATION_DELIMITER) {
|
||||
id, err := strconv.Atoi(idStr)
|
||||
if err == nil {
|
||||
if int64(id) != notifId {
|
||||
if newNotificationStr != "" {
|
||||
newNotificationStr += NOTIFICATION_DELIMITER
|
||||
}
|
||||
newNotificationStr += idStr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s.Notifications = newNotificationStr
|
||||
s.update()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -124,6 +124,38 @@ func GetLastDataForCompteur(adresseCompteur string) *TeleinfoTable {
|
|||
return data
|
||||
}
|
||||
|
||||
func GetNextData(addressCompteur string, from time.Time) []TeleinfoTable {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
|
||||
var dataArray []TeleinfoTable
|
||||
var maps []orm.Params
|
||||
_, err := o.QueryTable(new(TeleinfoTable)).Filter("AdresseCompteur", addressCompteur).Filter("HorodateGMT__gt", from).OrderBy("HorodateGMT").Values(&maps)
|
||||
if err == nil {
|
||||
for _, m := range maps {
|
||||
dataTime := utils.GetTime(m, "HorodateGMT")
|
||||
if dataTime.After(from) {
|
||||
d := new(TeleinfoTable)
|
||||
d.Id = utils.GetInt(m, "Id")
|
||||
d.HorodateGMT = dataTime
|
||||
|
||||
d.AdresseCompteur = utils.GetString(m, "AdresseCompteur")
|
||||
d.OptionTarifaire = optionTarifaireTranslate[utils.GetString(m, "OptionTarifaire")]
|
||||
d.OptionBase = utils.GetInt(m, "OptionBase")
|
||||
|
||||
d.IntensiteSouscrite = utils.GetInt(m, "IntensiteSouscrite")
|
||||
d.IntensiteInstantanne = utils.GetInt(m, "IntensiteInstantanne")
|
||||
d.IntensiteMax = utils.GetInt(m, "IntensiteMax")
|
||||
|
||||
d.PuissanceApparente = utils.GetInt(m, "PuissanceApparente")
|
||||
|
||||
dataArray = append(dataArray, *d)
|
||||
}
|
||||
}
|
||||
}
|
||||
return dataArray
|
||||
}
|
||||
|
||||
func DeleteDataCompteur(adresseCompteur string) {
|
||||
o := orm.NewOrm()
|
||||
o.Using(database.Alias)
|
||||
|
|
|
|||
|
|
@ -3,9 +3,14 @@ package utils
|
|||
import (
|
||||
"github.com/astaxie/beego/orm"
|
||||
|
||||
"crypto/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
dictionary = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
)
|
||||
|
||||
func GetString(m orm.Params, param string) string {
|
||||
ret := ""
|
||||
switch i := m[param].(type) {
|
||||
|
|
@ -38,3 +43,14 @@ func GetTime(m orm.Params, param string) time.Time {
|
|||
|
||||
return ret
|
||||
}
|
||||
|
||||
func TokenGenerator(length int) string {
|
||||
var bytes = make([]byte, length)
|
||||
if _, err := rand.Read(bytes); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for k, v := range bytes {
|
||||
bytes[k] = dictionary[v%byte(len(dictionary))]
|
||||
}
|
||||
return string(bytes)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,14 +14,14 @@ const (
|
|||
)
|
||||
|
||||
var (
|
||||
/*
|
||||
————————————————————————————————————————————————————————————————————————————————
|
||||
/*
|
||||
————————————————————————————————————————————————————————————————————————————————
|
||||
Routes
|
||||
————————————————————————————————————————————————————————————————————————————————
|
||||
*/
|
||||
————————————————————————————————————————————————————————————————————————————————
|
||||
*/
|
||||
RootRoute = "/"
|
||||
|
||||
AddTempRoute = "/add/temp/" + sensorMacRegex + "/:val([0-9]+)"
|
||||
AddTempRoute = "/add/temp/" + sensorMacRegex + "/:val([-]{0,1}[0-9]+)"
|
||||
AddRelayRoute = "/add/relay/" + sensorMacRegex
|
||||
TeleinfoAddRoute = "/teleinfo/add"
|
||||
AddSoilMoistRoute = "/add/soil" /* Route for soil moisture sensors*/
|
||||
|
|
@ -40,7 +40,7 @@ var (
|
|||
LoginRoute = "/login/:route(.*)"
|
||||
LoginRouteNoRegex = "/login"
|
||||
UserRoute = "/user"
|
||||
|
||||
NotificationsRoute = "/notifications"
|
||||
|
||||
/*
|
||||
————————————————————————————————————————————————————————————————————————————————
|
||||
|
|
@ -48,5 +48,5 @@ var (
|
|||
————————————————————————————————————————————————————————————————————————————————
|
||||
*/
|
||||
LogType = logFile
|
||||
LogParams = "{\""+LogFileName+"\":\""+LogFilePath+"\"}"
|
||||
LogParams = "{\"" + LogFileName + "\":\"" + LogFilePath + "\"}"
|
||||
)
|
||||
|
|
|
|||
|
|
@ -28,5 +28,6 @@ func init() {
|
|||
beego.Router(variables.SensorsRoute, &controllers.SensorsController{})
|
||||
beego.Router(variables.LoginRoute, &controllers.LoginController{})
|
||||
beego.Router(variables.UserRoute, &controllers.UserController{})
|
||||
beego.Router(variables.NotificationsRoute, &controllers.NotificationsController{})
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@
|
|||
class="active"
|
||||
{{end}}
|
||||
><a href="/user">Utilisateur</a></li>
|
||||
<li
|
||||
{{if .IsNotifications}}
|
||||
class="active"
|
||||
{{end}}
|
||||
><a href="/notifications">Notifications</a></li>
|
||||
{{end}}
|
||||
<li
|
||||
{{if .IsSensor}}
|
||||
|
|
|
|||
|
|
@ -31,14 +31,16 @@
|
|||
<form id="loginForm" class="form-signin" action="/login" method="POST">
|
||||
<h2 class="form-signin-heading">Login</h2>
|
||||
<label for="inputEmail" class="sr-only">Email address</label>
|
||||
<input id="inputLogin" name="login" class="form-control" placeholder="Login" required autofocus>
|
||||
<input name="token" type="hidden" id="token-value" value="" />
|
||||
<input id="inputLogin" name="login" class="form-control" placeholder="Login" required autofocus />
|
||||
<label for="inputPassword" class="sr-only">Password</label>
|
||||
<input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" required>
|
||||
<input type="password" id="inputPassword" name="password" class="form-control" placeholder="Password" />
|
||||
<!-- <div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" value="remember-me"> Remember me
|
||||
</label>
|
||||
</div> -->
|
||||
<center><p id="token-value-txt"></p></center>
|
||||
<button class="btn btn-lg btn-primary btn-block" type="submit">Laisse moi entrer</button>
|
||||
</form>
|
||||
|
||||
|
|
@ -51,8 +53,14 @@
|
|||
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
|
||||
<script src="/static/js/jquery.sha256.min.js"></script>
|
||||
<script type="application/javascript">
|
||||
var rand = function() {
|
||||
return Math.random().toString(36).substr(2);
|
||||
}
|
||||
$("form").attr('action', window.location.pathname);
|
||||
$("#loginForm").submit(function() {
|
||||
var token = Math.random().toString(36).substr(2);
|
||||
$('#token-value').val(token);
|
||||
$('#token-value-txt').text("Token: "+token);
|
||||
$('#inputPassword').val($.sha256($('#inputPassword').val()));
|
||||
console.log("Password: "+$('#inputPassword').val());
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,108 @@
|
|||
{{template "base/base.html" .}}
|
||||
{{define "meta"}}
|
||||
{{end}}
|
||||
{{define "extrajs"}}
|
||||
{{end}}
|
||||
{{define "body"}}
|
||||
|
||||
{{ $senss := .sensors }}
|
||||
{{ $notifs := .notifications }}
|
||||
<br/>
|
||||
|
||||
<table class="table table-striped">
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>Condition</th>
|
||||
<th>Value</th>
|
||||
<th>Sensor</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
{{range $key, $val := $notifs}}
|
||||
<form method="POST" >
|
||||
<tr>
|
||||
<td>
|
||||
{{$val.Id}}
|
||||
<input type="hidden" name="id" value="{{$val.Id}}" />
|
||||
</td>
|
||||
<td>
|
||||
<select class="form-control" name="condition">
|
||||
<option value="<"
|
||||
{{if eq $val.Condition "<" }}
|
||||
selected
|
||||
{{end}}
|
||||
>lower</option>
|
||||
<option value="<="
|
||||
{{if eq $val.Condition "<=" }}
|
||||
selected
|
||||
{{end}}
|
||||
>lower or equals</option>
|
||||
<option value=">"
|
||||
{{if eq $val.Condition ">" }}
|
||||
selected
|
||||
{{end}}
|
||||
>greater</option>
|
||||
<option value=">="
|
||||
{{if eq $val.Condition ">=" }}
|
||||
selected
|
||||
{{end}}
|
||||
>greater or equals</option>
|
||||
<option value="!="
|
||||
{{if eq $val.Condition "!=" }}
|
||||
selected
|
||||
{{end}}
|
||||
>different</option>
|
||||
<option value="=="
|
||||
{{if eq $val.Condition "==" }}
|
||||
selected
|
||||
{{end}}
|
||||
>equals</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><input type="number" class="form-control" placeholder="Value" name="value" value="{{$val.Value}}" /></td>
|
||||
<td>
|
||||
<select class="form-control" name="sensor-mac">
|
||||
{{range $kk, $sens := $senss}}
|
||||
<option value="{{$sens.MAC}}"
|
||||
{{ if eq $sens.Name $val.Sensor }}
|
||||
selected
|
||||
{{end}}
|
||||
>{{$sens.Name}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</td>
|
||||
<td>
|
||||
<button type="submit" name="action" value="modif" class="btn btn-info btn-xs btn-block">Udpate</button>
|
||||
<button type="submit" name="action" value="delete" class="btn btn-danger btn-xs btn-block">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
</form>
|
||||
{{end}}
|
||||
<form method="POST" >
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>
|
||||
<select class="form-control" name="condition">
|
||||
<option value="<">lower</option>
|
||||
<option value="<=">lower or equals</option>
|
||||
<option value=">">greater</option>
|
||||
<option value=">=">greater or equals</option>
|
||||
<option value="!=">different</option>
|
||||
<option value="==">equals</option>
|
||||
</select>
|
||||
</td>
|
||||
<td><input type="number" class="form-control" placeholder="Value" name="value" /></td>
|
||||
<td>
|
||||
<select class="form-control" name="sensor-mac">
|
||||
{{range $kk, $sens := $senss}}
|
||||
<option value="{{$sens.MAC}}">{{$sens.Name}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</td>
|
||||
<td><button type="submit" name="action" value="add" class="btn btn-success btn-xs btn-block">Add</button></td>
|
||||
</tr>
|
||||
</form>
|
||||
</table>
|
||||
|
||||
<br/>
|
||||
|
||||
{{end}}
|
||||
|
|
@ -4,20 +4,58 @@
|
|||
<script type="text/javascript" src="/static/highstock/js/highstock.js"></script>
|
||||
<script type="text/javascript" src="/static/highstock/js/themes/grid.js"></script>
|
||||
<script type="text/javascript" src="/static/highstock/js/modules/exporting.js"></script>
|
||||
<script src="http://code.highcharts.com/highcharts.js"></script>
|
||||
{{end}}
|
||||
{{define "extrajs"}}
|
||||
<script type="text/javascript">
|
||||
$(function () {
|
||||
chart1 = new Highcharts.StockChart({
|
||||
var lastTimeStamps = {{.lastHorodate}};
|
||||
|
||||
var initData = function(series) {
|
||||
//loadNewData(series);
|
||||
setInterval(function() {
|
||||
loadNewData(series);
|
||||
}, 30000);
|
||||
};
|
||||
|
||||
var loadNewData = function(series) {
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
data: {
|
||||
currentTime: lastTimeStamps
|
||||
},
|
||||
success: function(json) {
|
||||
console.log(json);
|
||||
var obj = JSON.parse(json);
|
||||
for (var i=0; i<obj.values.length; i++) {
|
||||
var arrayVal = [obj.values[i][0], obj.values[i][1]];
|
||||
console.log(arrayVal);
|
||||
series.addPoint(arrayVal, true, false);
|
||||
|
||||
if (i == obj.values.length-1) {
|
||||
lastTimeStamps = obj.values[i][0] + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
$(function () {
|
||||
|
||||
Highcharts.setOptions({
|
||||
global: {
|
||||
useUTC: false
|
||||
}
|
||||
});
|
||||
|
||||
// Create the chart
|
||||
Highcharts.StockChart({
|
||||
chart: {
|
||||
renderTo : 'graphe',
|
||||
load : function () {
|
||||
renderTo: "graphe",
|
||||
events: {
|
||||
load: function () {
|
||||
// set up the updating of the chart each second
|
||||
var series = this.series[0];
|
||||
setInterval(function () {
|
||||
var x = (new Date()).getTime(), // current time
|
||||
y = Math.round(Math.random() * 100);
|
||||
series.addPoint([x, y], true, true);
|
||||
}, 1000);
|
||||
initData(series);
|
||||
}
|
||||
}
|
||||
},
|
||||
rangeSelector: {
|
||||
|
|
@ -65,7 +103,7 @@
|
|||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Puissance (W)'
|
||||
text: 'Puissance (VA)'
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
|
|
@ -80,18 +118,12 @@
|
|||
verticalAlign : 'middle',
|
||||
align : 'right'
|
||||
},
|
||||
|
||||
series : [ {{.dataPower}} ]
|
||||
});
|
||||
});
|
||||
Highcharts.setOptions({
|
||||
global: {
|
||||
useUTC: false
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{{end}}
|
||||
{{define "extrajs"}}
|
||||
{{end}}
|
||||
{{define "body"}}
|
||||
<div class="row">
|
||||
<div class="col-sm-3">
|
||||
|
|
|
|||
77
xmpp/xmpp.go
77
xmpp/xmpp.go
|
|
@ -1,10 +1,12 @@
|
|||
package xmpp_manager
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/astaxie/beego"
|
||||
"github.com/astaxie/beego/logs"
|
||||
|
||||
"git.kingpenguin.tk/chteufleur/datahouse.git/models"
|
||||
"git.kingpenguin.tk/chteufleur/datahouse.git/models/relay"
|
||||
"git.kingpenguin.tk/chteufleur/datahouse.git/models/variables"
|
||||
"git.kingpenguin.tk/chteufleur/go-xmpp.git/src/xmpp"
|
||||
|
|
@ -26,8 +28,6 @@ const (
|
|||
Type_unsubscribed = "unsubscribed"
|
||||
Type_probe = "probe"
|
||||
Type_error = "error"
|
||||
|
||||
EndRun = "EndRunXMPP"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -35,17 +35,27 @@ var (
|
|||
|
||||
JidStr = beego.AppConfig.String("JID")
|
||||
passwdStr = beego.AppConfig.String("PWD")
|
||||
server = beego.AppConfig.String("SERVER")
|
||||
serverPort = beego.AppConfig.String("PORT")
|
||||
|
||||
jid xmpp.JID
|
||||
stream = new(xmpp.Stream)
|
||||
client = new(xmpp.XMPP)
|
||||
|
||||
Debug = true
|
||||
ping = false
|
||||
pingId int64 = 0
|
||||
timerDoPing, _ = beego.AppConfig.Int("TIMER_PING")
|
||||
|
||||
Debug = false
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetLogger(variables.LogType, variables.LogParams)
|
||||
Debug = beego.AppConfig.String("XMPP_DEBUG") == "true"
|
||||
if timerDoPing < 30 {
|
||||
timerDoPing = 30
|
||||
}
|
||||
go doPing()
|
||||
}
|
||||
|
||||
func must(v interface{}, err error) interface{} {
|
||||
|
|
@ -58,17 +68,42 @@ func must(v interface{}, err error) interface{} {
|
|||
func Run() {
|
||||
// Create stream and configure it as a component connection.
|
||||
log.Info("XMPP Run()")
|
||||
|
||||
streamConfig := &xmpp.StreamConfig{LogStanzas: Debug}
|
||||
jid = must(xmpp.ParseJID(JidStr)).(xmpp.JID)
|
||||
stream = must(xmpp.NewStream(jid.Domain+":"+serverPort, &xmpp.StreamConfig{LogStanzas: Debug})).(*xmpp.Stream)
|
||||
var addrs []string
|
||||
var err error = nil
|
||||
if server != "" {
|
||||
log.Info("Host in config")
|
||||
addr := server
|
||||
if serverPort != "" {
|
||||
addr += ":" + serverPort
|
||||
} else {
|
||||
addr += ":5222"
|
||||
}
|
||||
addrs = append(addrs, addr)
|
||||
} else {
|
||||
log.Info("SRV lookup")
|
||||
addrs, err = xmpp.HomeServerAddrs(jid)
|
||||
}
|
||||
if err == nil && len(addrs) > 0 {
|
||||
stream = must(xmpp.NewStream(addrs[0], streamConfig)).(*xmpp.Stream)
|
||||
client = must(xmpp.NewClientXMPP(stream, jid, passwdStr, &xmpp.ClientConfig{InsecureSkipVerify: true})).(*xmpp.XMPP)
|
||||
|
||||
mainXMPP()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
log.Debug("xmpp.Run Ended")
|
||||
models.ChanRuns <- EndRun
|
||||
go Run()
|
||||
}
|
||||
|
||||
func mainXMPP() {
|
||||
SendPresence(Status_online, Type_available, "")
|
||||
defer func() {
|
||||
ping = false
|
||||
log.Debug("mainXMPP Ended")
|
||||
}()
|
||||
SendPresence(Status_online, Type_available, "DataHouse")
|
||||
ping = true
|
||||
|
||||
for x := range client.In {
|
||||
switch v := x.(type) {
|
||||
|
|
@ -86,14 +121,34 @@ func mainXMPP() {
|
|||
log.Info("recv: %v", x)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Send deconnexion
|
||||
SendPresence(Status_offline, Type_unavailable, "")
|
||||
log.Debug("mainXMPP Ended")
|
||||
func doPing() {
|
||||
for {
|
||||
if ping {
|
||||
iq := &xmpp.Iq{Id: strconv.FormatInt(pingId, 10), Type: xmpp.IQTypeGet, To: jid.Domain, From: jid.Full()}
|
||||
iq.PayloadEncode(&xmpp.Ping{})
|
||||
client.Out <- iq
|
||||
pingId++
|
||||
}
|
||||
time.Sleep(time.Duration(timerDoPing) * time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func SendPresence(status, tpye, message string) {
|
||||
client.Out <- xmpp.Presence{From: jid.Domain, Show: status, Type: tpye, Status: message}
|
||||
client.Out <- xmpp.Presence{From: jid.Full(), 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) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue