diff --git a/controllers/sensors.go b/controllers/sensors.go index bbf3cab..026b010 100644 --- a/controllers/sensors.go +++ b/controllers/sensors.go @@ -6,6 +6,7 @@ import ( "git.kingpenguin.tk/chteufleur/datahouse.git/models/relay" "git.kingpenguin.tk/chteufleur/datahouse.git/models/sensor" "git.kingpenguin.tk/chteufleur/datahouse.git/models/temperature" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/teleinfo" "git.kingpenguin.tk/chteufleur/datahouse.git/models/variables" "strconv" @@ -30,9 +31,11 @@ func (c *SensorsController) Prepare() { func (c *SensorsController) Get() { sensors := sensor.GetAllSensor() relays := relay.GetAllRelay() + compteurs := teleinfo.GetAllCompteur() c.Data["sensors"] = sensors c.Data["relays"] = relays + c.Data["compteurs"] = compteurs c.TplNames = "sensors.tpl" } @@ -42,6 +45,8 @@ func (c *SensorsController) Post() { c.PostTempSensors() } else if tpye == "relay" { c.PostRelay() + } else if tpye == "compteur" { + c.PostCompteur() } else { c.Redirect("/404", 404) } @@ -85,3 +90,21 @@ func (c *SensorsController) PostRelay() { c.Redirect("/404", 404) } } + +func (c *SensorsController) PostCompteur() { + description := c.Input().Get("description") + adresse := c.Input().Get("adresse") + + isDelete := c.Input().Get("delete") + isSave := c.Input().Get("save") + if isSave != "" { + teleinfo.UpdateCompteur(adresse, description) + c.Redirect("/sensors", 302) + } else if isDelete != "" { + cpt := teleinfo.GetCompteurByAdresse(adresse) + teleinfo.DeleteCompteur(cpt.Id) + c.Redirect("/sensors", 302) + } else { + c.Redirect("/404", 404) + } +} diff --git a/controllers/teleinfo.go b/controllers/teleinfo.go new file mode 100644 index 0000000..8045c56 --- /dev/null +++ b/controllers/teleinfo.go @@ -0,0 +1,68 @@ +package controllers + +import ( + "github.com/astaxie/beego" + + "git.kingpenguin.tk/chteufleur/datahouse.git/models/variables" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/teleinfo" +) + +//—————————————————————————————————————————————————————————————————————————————— +// AddTeleinfoController +//—————————————————————————————————————————————————————————————————————————————— +type AddTeleinfoController struct { + beego.Controller +} + +func (c *AddTeleinfoController) Prepare() { + c.Data["version"] = variables.Version +} + +func (c *AddTeleinfoController) Get() { + adresse := c.GetString(teleinfo.AdresseCompteur) + tarif := c.GetString(teleinfo.OptionTarifaire) + option := c.GetString(teleinfo.OptionBase) + hp, _ := c.GetInt(teleinfo.HeurePleinne) + hc, _ := c.GetInt(teleinfo.HeureCreuse) + + teleinfo.AddData(adresse, tarif, option, int64(hp), int64(hc)) + + cpt := teleinfo.GetCompteurByAdresse(adresse) + if cpt == nil || cpt.Id == 0 { + teleinfo.AddCompteur(adresse) + } + c.Ctx.Output.Body([]byte("")) +} + + + +//—————————————————————————————————————————————————————————————————————————————— +// ViewTeleinfoController +//—————————————————————————————————————————————————————————————————————————————— +type ViewTeleinfoController struct { + beego.Controller +} + +func (c *ViewTeleinfoController) Prepare() { + c.Data["IsViewTeleinfo"] = true + c.Data["version"] = variables.Version +} + +func (c *ViewTeleinfoController) Get() { + c.Data["compteurs"] = teleinfo.GetAllCompteur() + + adresse := c.Ctx.Input.Param(":compteur") + cpt := teleinfo.GetCompteurByAdresse(adresse) + if cpt.Id != 0 { + c.Data["isCompteurSelected"] = true + c.Data["dataCompteur"] = teleinfo.GetLastDataForCompteur(cpt.AdresseCompteur) + c.Data["compteurAdresse"] = cpt.AdresseCompteur + if cpt.Description != "" { + c.Data["compteurDescription"] = cpt.Description + } else { + c.Data["compteurDescription"] = cpt.AdresseCompteur + } + } + + c.TplNames = "teleinfo.tpl" +} diff --git a/models/teleinfo/teleinfo.go b/models/teleinfo/teleinfo.go new file mode 100644 index 0000000..8dea874 --- /dev/null +++ b/models/teleinfo/teleinfo.go @@ -0,0 +1,229 @@ +package teleinfo + +import ( + "github.com/astaxie/beego/logs" + "github.com/astaxie/beego/orm" + + "git.kingpenguin.tk/chteufleur/datahouse.git/models/database" + "git.kingpenguin.tk/chteufleur/datahouse.git/models/utils" + + "time" +) + +const ( + AdresseCompteur = "ADCO" + OptionTarifaire = "OPTARIF" + OptionBase = "BASE" // Wh + HeurePleinne = "HCHP" // Wh + HeureCreuse = "HCHC" // Wh +) + +var ( + _, timezoneOffset = time.Now().Zone() + log = logs.NewLogger(10000) + + optionTarifaireTranslate = make(map[string]string) +) + +func init() { + log.SetLogger("console", "") + orm.RegisterModel(new(TeleinfoTable), new(CompteurTeleinfoTable)) + orm.DefaultRowsLimit = 4500 + + optionTarifaireTranslate["BASE"] = "Base" + optionTarifaireTranslate["HC.."] = "Heures Creuses" + optionTarifaireTranslate["EJP."] = "EJP" +} + + + +//—————————————————————————————————————————————————————————————————————————————— +// TeleinfoTable +//—————————————————————————————————————————————————————————————————————————————— +type TeleinfoTable struct { + Id int64 + HorodateGMT time.Time `orm:"auto_now;type(datetime)"` + AdresseCompteur string + OptionTarifaire string + OptionBase string + HeurePleinne int64 + HeureCreuse int64 +} + + +func AddData(adresse, tarif, option string, hp, hc int64) { + log.Info("Add teleinfo {adresse: %s, tarif: %s, option: %s, hp: %d, hc: %d}", adresse, tarif, option, hp, hc) + o := orm.NewOrm() + o.Using(database.Alias) + + ti := new(TeleinfoTable) + ti.AdresseCompteur = adresse + ti.OptionTarifaire = tarif + ti.OptionBase = option + ti.HeurePleinne = hp + ti.HeureCreuse = hc + o.Insert(ti) +} + +func GetAllDataForCompteur(adresseCompteur string) []TeleinfoTable { + o := orm.NewOrm() + o.Using(database.Alias) + + var dataArray []TeleinfoTable + var maps []orm.Params + _, err := o.QueryTable(new(TeleinfoTable)).Filter("AdresseCompteur", adresseCompteur).Values(&maps) + if err == nil { + for _, m := range maps { + d := new(TeleinfoTable) + d.Id = utils.GetInt(m, "Id") + d.HorodateGMT = utils.GetTime(m, "HorodateGMT") + + d.AdresseCompteur = utils.GetString(m, "AdresseCompteur") + d.OptionTarifaire = optionTarifaireTranslate[utils.GetString(m, "OptionTarifaire")] + d.OptionBase = utils.GetString(m, "OptionBase") + + d.HeurePleinne = utils.GetInt(m, "HeurePleinne") + d.HeureCreuse = utils.GetInt(m, "HeureCreuse") + + dataArray = append(dataArray, *d) + } + } + return dataArray +} + +func GetLastDataForCompteur(adresseCompteur string) *TeleinfoTable { + o := orm.NewOrm() + o.Using(database.Alias) + + data := new(TeleinfoTable) + var maps []orm.Params + _, err := o.QueryTable(new(TeleinfoTable)).Filter("AdresseCompteur", adresseCompteur).OrderBy("HorodateGMT").Values(&maps) + if err == nil { + for _, m := range maps { + data.Id = utils.GetInt(m, "Id") + data.HorodateGMT = utils.GetTime(m, "HorodateGMT") + + data.AdresseCompteur = utils.GetString(m, "AdresseCompteur") + data.OptionTarifaire = optionTarifaireTranslate[utils.GetString(m, "OptionTarifaire")] + data.OptionBase = utils.GetString(m, "OptionBase") + + data.HeurePleinne = utils.GetInt(m, "HeurePleinne") + data.HeureCreuse = utils.GetInt(m, "HeureCreuse") + } + } + return data +} + + + + +//—————————————————————————————————————————————————————————————————————————————— +// CompteurTeleinfoTable +//—————————————————————————————————————————————————————————————————————————————— +type CompteurTeleinfoTable struct { + Id int64 + AdresseCompteur string + Description string +} + +func GetCompteurByAdresse(adresse string) *CompteurTeleinfoTable { + o := orm.NewOrm() + o.Using(database.Alias) + + ret := new(CompteurTeleinfoTable) + var maps []orm.Params + _, err := o.QueryTable(new(CompteurTeleinfoTable)).Filter("AdresseCompteur", adresse).Values(&maps) + if err == nil { + for _, m := range maps { + ret.Id = utils.GetInt(m, "Id") + ret.AdresseCompteur = utils.GetString(m, "AdresseCompteur") + ret.Description = utils.GetString(m, "Description") + break + } + } + + return ret +} + +func GetAllCompteurIds() []int64 { + o := orm.NewOrm() + o.Using(database.Alias) + + var ret []int64 + var maps []orm.Params + _, err := o.QueryTable(new(CompteurTeleinfoTable)).Values(&maps) + if err == nil { + for _, m := range maps { + ret = append(ret, utils.GetInt(m, "Id")) + } + } + return ret +} + +func GetAllCompteur() []CompteurTeleinfoTable { + o := orm.NewOrm() + o.Using(database.Alias) + + var ret []CompteurTeleinfoTable + var maps []orm.Params + _, err := o.QueryTable(new(CompteurTeleinfoTable)).Values(&maps) + if err == nil { + for _, m := range maps { + r := new(CompteurTeleinfoTable) + r.Id = utils.GetInt(m, "Id") + r.AdresseCompteur = utils.GetString(m, "AdresseCompteur") + r.Description = utils.GetString(m, "Description") + + ret = append(ret, *r) + } + } + return ret +} + +func GetSensor(id int64) *CompteurTeleinfoTable { + o := orm.NewOrm() + o.Using(database.Alias) + + + var ret = new(CompteurTeleinfoTable) + var maps []orm.Params + _, err := o.QueryTable(new(CompteurTeleinfoTable)).Filter("Id", id).Values(&maps) + if err == nil { + for _, m := range maps { + ret.Id = utils.GetInt(m, "Id") + ret.AdresseCompteur = utils.GetString(m, "AdresseCompteur") + ret.Description = utils.GetString(m, "Description") + } + } + return ret +} + +func UpdateCompteur(adresse, description string) { + o := orm.NewOrm() + o.Using(database.Alias) + + s := GetCompteurByAdresse(adresse) + if o.Read(s) == nil { + s.AdresseCompteur = adresse + s.Description = description + o.Update(s) + } +} + +func AddCompteur(adresse string) { + o := orm.NewOrm() + o.Using(database.Alias) + _, _ = o.Insert(&CompteurTeleinfoTable{AdresseCompteur: adresse}) +} + +func DeleteCompteurByAdresse(adresse string) { + o := orm.NewOrm() + o.Using(database.Alias) + o.Delete(&CompteurTeleinfoTable{AdresseCompteur: adresse}) +} + +func DeleteCompteur(compteurId int64) { + o := orm.NewOrm() + o.Using(database.Alias) + o.Delete(&CompteurTeleinfoTable{Id: compteurId}) +} diff --git a/models/temperature/temperature.go b/models/temperature/temperature.go index a556457..2f9599b 100644 --- a/models/temperature/temperature.go +++ b/models/temperature/temperature.go @@ -25,6 +25,7 @@ var ( func init() { log.SetLogger("console", "") orm.RegisterModel(new(TempTable)) + orm.DefaultRowsLimit = 4500 } /** diff --git a/models/variables/variables.go b/models/variables/variables.go index 5edd2b0..778f2e2 100644 --- a/models/variables/variables.go +++ b/models/variables/variables.go @@ -1,7 +1,7 @@ package variables const ( - Version = "0.0.4.3" + Version = "0.0.5.0" SessionName = "Session_Data_House" @@ -11,12 +11,15 @@ const ( var ( RootRoute = "/" - AddTempRoute = "/add/temp/" + sensorMacRegex + "/:val([0-9]+)" - AddRelayRoute = "/add/relay/" + sensorMacRegex + AddTempRoute = "/add/temp/" + sensorMacRegex + "/:val([0-9]+)" + AddRelayRoute = "/add/relay/" + sensorMacRegex + TeleinfoAddRoute = "/teleinfo/add" - ViewTempRoute = "/view/temp" - ViewRelaysRoute = "/view/relay" - ViewRelayRoute = "/view/relay/" + sensorMacRegex + ViewTempRoute = "/view/temp" + ViewRelaysRoute = "/view/relay" + ViewRelayRoute = "/view/relay/" + sensorMacRegex + ViewTeleinfosRoute = "/view/teleinfo" + ViewTeleinfoRoute = "/view/teleinfo/:compteur([0-9A-Fa-f:]+)" CommandRelayRoute = "/command/relay/" + sensorMacRegex @@ -24,4 +27,5 @@ var ( LoginRoute = "/login/:route(.*)" LoginRouteNoRegex = "/login" UserRoute = "/user" + ) diff --git a/routers/router.go b/routers/router.go index da59e28..d873f39 100644 --- a/routers/router.go +++ b/routers/router.go @@ -11,6 +11,7 @@ func init() { beego.Router(variables.AddTempRoute, &controllers.AddTempController{}) beego.Router(variables.AddRelayRoute, &controllers.AddRelayController{}) + beego.Router(variables.TeleinfoAddRoute, &controllers.AddTeleinfoController{}) beego.Router(variables.ViewTempRoute, &controllers.ViewTempController{}) beego.Router(variables.ViewRelaysRoute, &controllers.ViewRelayController{}) @@ -18,6 +19,9 @@ func init() { beego.Router(variables.CommandRelayRoute, &controllers.CommandRelayController{}) + beego.Router(variables.ViewTeleinfosRoute, &controllers.ViewTeleinfoController{}) + beego.Router(variables.ViewTeleinfoRoute, &controllers.ViewTeleinfoController{}) + beego.Router(variables.SensorsRoute, &controllers.SensorsController{}) beego.Router(variables.LoginRoute, &controllers.LoginController{}) beego.Router(variables.UserRoute, &controllers.UserController{}) diff --git a/sensors/TeleInfo/TeleInfo.ino b/sensors/TeleInfo/TeleInfo.ino new file mode 100644 index 0000000..1966cbb --- /dev/null +++ b/sensors/TeleInfo/TeleInfo.ino @@ -0,0 +1,160 @@ +/* + * Send TeleInfo via HTTP GET request to $host service. + * Read ERDF TeleInfo when received, then send it to the server. + * Version 1.0 + */ + + +/* + * TODO : Gestion du temps pour n'envoyer que toute les minutes (ou un truc du genre) + */ +#include + +//---------------------------------------------------- + +const char* ssid = "TNCAP3F2E03"; +const char* password = "73ABCCAA87"; + +//const char* host = "datahouse.kingpenguin.tk"; +const char* host = "192.168.1.143"; +const int httpPort = 8080; +const int DEFAULT_INTERVAL = 60000; // 60 sec + +//---------------------------------------------------- +String ADCO = ""; +String OPTARIF = ""; +String BASE = ""; +String HCHP = ""; +String HCHC = ""; +//---------------------------------------------------- + +// Wait for x second. +void sleepSec(int sec) { + for (int i=0; i<1000; i++) { + delay(sec); + } +} + + + +long nextInterval; + +void sendDataToServer() { + // Use WiFiClient class to create TCP connections + WiFiClient client; + if (!client.connect(host, httpPort)) { + Serial.print("connection failed on host "); + Serial.print(host); + Serial.print(":"); + Serial.println(host); + return; + } + + // We now create a URI for the request + // TODO a finir + String url = "/teleinfo/add?ADCO="+ADCO+"&OPTARIF="+OPTARIF+"&BASE="+BASE+"&HCHC="+HCHC+"&HCHP="+HCHP; + ADCO = ""; + OPTARIF = ""; + BASE = ""; + HCHC = ""; + HCHP = ""; + + Serial.print("Requesting URL: "); + Serial.println(url); + + // This will send the request to the server + client.println("GET "+url+" HTTP/1.1"); + client.println("Host: "+String(host)); + client.println("Connection: keep-alive"); +// client.println("Connection: close"); + client.println(); + delay(10); + + Serial.println(); + String line = ""; + while (client.available()) { + char c = client.read(); + line += c; + } + Serial.println(line); + + nextInterval = line.toInt(); + if (nextInterval == 0) { + nextInterval = DEFAULT_INTERVAL; + } + nextInterval = millis() + nextInterval; +} + + +void setup() { + Serial.begin(1200); + delay(10); + + // We start by connecting to a WiFi network + + Serial.println(); + Serial.println(); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); +} + + +void loop() { + if (Serial.available() > 0) { + String str = Serial.readStringUntil('\n'); + if (millis() >= nextInterval) { + bool sendable = false; + + int i = str.indexOf("ADCO"); + if (i != -1) { + i = i + 4 +1; + ADCO = str.substring(i, i+12); + } + + i = str.indexOf("OPTARIF"); + if (i != -1) { + i = i + 7 +1; + OPTARIF = str.substring(i, i+4); + } + + i = str.indexOf("BASE"); + if (i != -1) { + i = i + 4 +1; + BASE = str.substring(i, i+9); + } + + i = str.indexOf("HCHC"); + if (i != -1) { + i = i + 4 +1; + HCHC = str.substring(i, i+9); + } + + i = str.indexOf("HCHP"); + if (i != -1) { + i = i + 4 +1; + HCHP = str.substring(i, i+9); + sendable = true; + } + + + if (sendable && ADCO != "") { + sendDataToServer(); + } + } + } +} + + + diff --git a/views/base/navbar.html b/views/base/navbar.html index 8471ba3..1cf0bed 100644 --- a/views/base/navbar.html +++ b/views/base/navbar.html @@ -24,11 +24,12 @@ {{end}} >Relais - + >Télé-Info +