initial ups support

This commit is contained in:
Paolo Asperti 2020-12-27 22:29:16 +01:00
parent 2958e13b5e
commit 28dcadbeef
Signed by: paspo
GPG Key ID: 06D46905D19D5182
8 changed files with 410 additions and 147 deletions

13
.editorconfig Normal file
View File

@ -0,0 +1,13 @@
root = true
[*]
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[*]
charset = utf-8
[*.html]
indent_style = space
indent_size = 2

View File

@ -19,6 +19,7 @@ func init() {
func main() { func main() {
readConfig() readConfig()
go mqttLoop() go mqttLoop()
go UpsConnect()
log.Printf("hostname: %v\n", viper.Get("hostname")) log.Printf("hostname: %v\n", viper.Get("hostname"))
startServer() startServer()
} }

72
src/ups.go Normal file
View File

@ -0,0 +1,72 @@
package main
import (
"fmt"
nut "github.com/robbiet480/go.nut"
"github.com/spf13/viper"
)
var upsClient nut.Client
var ups nut.UPS
var upsVars map[string]nut.Variable
func init() {
viper.SetDefault("UpsHost", "localhost")
viper.SetDefault("UpsName", "ups")
viper.SetDefault("UpsUsername", "")
viper.SetDefault("UpsPassword", "")
}
func UpsConnect() {
var username, password string
var connectErr, authenticationError error
var u nut.UPS
upsClient, connectErr = nut.Connect(viper.GetString("UpsHost"))
if connectErr != nil {
fmt.Print(connectErr)
return
}
if username = viper.GetString("UpsUsername"); username == "" {
return
}
if password = viper.GetString("UpsPassword"); password == "" {
return
}
_, authenticationError = upsClient.Authenticate(username, password)
if authenticationError != nil {
fmt.Print(authenticationError)
return
}
upsList, listErr := upsClient.GetUPSList()
if listErr != nil {
fmt.Print(listErr)
return
}
for _, u = range upsList {
if u.Name == viper.GetString("UpsName") {
ups = u
fmt.Print("UPS connected")
UpsReadVars()
}
}
}
func UpsReadVars() {
upsVars = map[string]nut.Variable{}
for _, v := range ups.Variables {
upsVars[v.Name] = v
}
}
func UpsReconfigure() {
ups = nut.UPS{}
upsClient = nut.Client{}
fmt.Print("UPS disconnected")
go UpsConnect()
}

47
src/ups_ui.go Normal file
View File

@ -0,0 +1,47 @@
package main
import (
"strings"
"github.com/spf13/viper"
"gopkg.in/macaron.v1"
)
func upsPage(ctx *macaron.Context) {
ctx.Data["host"] = viper.GetString("UpsHost")
ctx.Data["upsname"] = viper.GetString("UpsName")
ctx.Data["username"] = viper.GetString("UpsUsername")
ctx.Data["password"] = viper.GetString("UpsPassword")
// if ups == nil {
// ctx.Data["serverstatus"] = "Disconnected"
// ctx.Data["upsstatus"] = "unknown"
// } else {
ctx.Data["serverstatus"] = "Connected"
ctx.Data["upsstatus"] = upsVars["ups.status"].Value
ctx.Data["upsmfr"] = upsVars["device.mfr"].Value
ctx.Data["upsmodel"] = upsVars["device.model"].Value
ctx.Data["upsserial"] = upsVars["device.serial"].Value
// }
ctx.HTML(200, "ups")
}
type UPSPostForm struct {
Host string `form:"host" binding:"Required"`
UpsName string `form:"upsname" binding:"Required"`
Username string `form:"username" binding:"Required"`
Password string `form:"password" binding:"Required"`
}
func upsPost(ctx *macaron.Context, f UPSPostForm) {
viper.Set("UpsHost", strings.ToLower(strings.TrimSpace(f.Host)))
viper.Set("UpsName", strings.TrimSpace(f.UpsName))
viper.Set("UpsUsername", strings.TrimSpace(f.Username))
viper.Set("UpsPassword", f.Password)
viper.WriteConfig()
UpsReconfigure()
upsPage(ctx)
}

View File

@ -107,6 +107,8 @@ func startServer() {
m.Get("/", statusPage) m.Get("/", statusPage)
m.Get("/mqtt", mqttPage) m.Get("/mqtt", mqttPage)
m.Post("/mqtt", binding.Bind(MQTTPostForm{}), mqttPost) m.Post("/mqtt", binding.Bind(MQTTPostForm{}), mqttPost)
m.Get("/ups", upsPage)
m.Post("/ups", binding.Bind(UPSPostForm{}), upsPost)
m.Get("/json/status", jsonStatus) m.Get("/json/status", jsonStatus)
m.Post("/json/outlet/:id/toggle", jsonOutletToggle) m.Post("/json/outlet/:id/toggle", jsonOutletToggle)

View File

@ -1,5 +1,5 @@
<!-- Left side column. contains the logo and sidebar --> <!-- Left side column. contains the logo and sidebar -->
<aside class="main-sidebar"> <aside class="main-sidebar">
<!-- sidebar: style can be found in sidebar.less --> <!-- sidebar: style can be found in sidebar.less -->
<section class="sidebar"> <section class="sidebar">
@ -49,7 +49,12 @@
{% endif %} {% endif %}
<a href="/mqtt"><i class="fa fa-circle-o"></i> MQTT</a></li> <a href="/mqtt"><i class="fa fa-circle-o"></i> MQTT</a></li>
<li><a href="/ups"><i class="fa fa-circle-o"></i> UPS</a></li> {% if pageselected == "ups" %}
<li class="active">
{% else %}
<li>
{% endif %}
<a href="/ups"><i class="fa fa-circle-o"></i> UPS</a></li>
<li><a href="/syslog"><i class="fa fa-circle-o"></i> syslog</a></li> <li><a href="/syslog"><i class="fa fa-circle-o"></i> syslog</a></li>
<li><a href="/backup"><i class="fa fa-circle-o"></i> backup</a></li> <li><a href="/backup"><i class="fa fa-circle-o"></i> backup</a></li>
<li><a href="/restore"><i class="fa fa-circle-o"></i> restore</a></li> <li><a href="/restore"><i class="fa fa-circle-o"></i> restore</a></li>
@ -58,4 +63,4 @@
</ul> </ul>
</section> </section>
<!-- /.sidebar --> <!-- /.sidebar -->
</aside> </aside>

View File

@ -1,15 +1,14 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
{% include "common/common-head.html" %} {% include "common/common-head.html" %}
</head> </head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
{% include "common/page-header.html" %} <body class="hold-transition skin-blue sidebar-mini">
{% with pageselected="mqtt" %} <div class="wrapper">
{% include "common/sidebar-menu.html" %}
{% endwith %} {% include "common/page-header.html" %} {% with pageselected="mqtt" %} {% include "common/sidebar-menu.html" %} {% endwith %}
<!-- Content Wrapper. Contains page content --> <!-- Content Wrapper. Contains page content -->
<div class="content-wrapper"> <div class="content-wrapper">
@ -118,6 +117,6 @@
{% include "common/common-js.html" %} {% include "common/common-js.html" %}
</body> </body>
</html>
</html>

124
templates/ups.html Normal file
View File

@ -0,0 +1,124 @@
<!DOCTYPE html>
<html>
<head>
{% include "common/common-head.html" %}
</head>
<body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper">
{% include "common/page-header.html" %} {% with pageselected="ups" %} {% include "common/sidebar-menu.html" %} {% endwith %}
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-12">
<div class="box box-info">
<div class="box-header with-border">
<h3 class="box-title">UPS configuration</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form class="form-horizontal" method="post">
<div class="box-body">
<div class="form-group">
<label for="serverstatus" class="col-sm-2 control-label">Server Status</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="serverstatus" disabled="" value="{{ serverstatus }}">
</div>
</div>
<div class="form-group">
<label for="upsstatus" class="col-sm-2 control-label">UPS Status</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsstatus" disabled="" value="{{ upsstatus }}">
</div>
</div>
<div class="form-group">
<label for="upsmfr" class="col-sm-2 control-label">UPS Brand</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsmfr" disabled="" value="{{ upsmfr }}">
</div>
</div>
<div class="form-group">
<label for="upsmodel" class="col-sm-2 control-label">UPS Model</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsmodel" disabled="" value="{{ upsmodel }}">
</div>
</div>
<div class="form-group">
<label for="upsserial" class="col-sm-2 control-label">UPS Serial</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsserial" disabled="" value="{{ upsserial }}">
</div>
</div>
<div class="form-group">
<label for="host" class="col-sm-2 control-label">Host</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="host" name="host" placeholder="Hostname or IP address" value="{{ host }}">
</div>
</div>
<div class="form-group">
<label for="upsname" class="col-sm-2 control-label">UPS Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsname" name="upsname" placeholder="UPS name" value="{{ upsname }}">
</div>
</div>
<div class="form-group">
<label for="username" class="col-sm-2 control-label">Username</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="username" name="username" placeholder="username (if required)" value="{{ username }}">
</div>
</div>
<div class="form-group">
<label for="password" class="col-sm-2 control-label">Password</label>
<div class="col-sm-10">
<input type="password" class="form-control" id="password" name="password" placeholder="password (if required)" value="{{ password }}">
</div>
</div>
</div>
<!-- /.box-body -->
<div class="box-footer">
<button type="submit" class="btn btn-info pull-right">Save</button>
</div>
<!-- /.box-footer -->
</form>
</div>
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
{% include "common/footer.html" %}
</div>
<!-- ./wrapper -->
{% include "common/common-js.html" %}
</body>
</html>