Compare commits

...

10 Commits

18 changed files with 855 additions and 155 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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
}

View File

@ -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 : ["

View File

@ -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")

View File

@ -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)
}
}
}

View File

@ -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()
}

View File

@ -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)

View File

@ -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)
}

View File

@ -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 + "\"}"
)

View File

@ -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{})
}

View File

@ -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}}

View File

@ -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;

108
views/notifications.tpl Normal file
View File

@ -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}}

View File

@ -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">

View File

@ -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) {