Update config.go, display.go, and 7 more files...

This commit is contained in:
Paolo Asperti 2020-12-23 15:32:05 +01:00
parent 1219291a6d
commit 9e2ef61772
9 changed files with 299 additions and 40 deletions

View File

@ -7,14 +7,12 @@ import (
) )
func readConfig() { func readConfig() {
viper.SetConfigName("openpdu.yaml") // name of config file (without extension) viper.SetConfigName("openpdu") // name of config file (without extension)
viper.SetConfigType("yaml") viper.SetConfigType("yaml")
viper.AddConfigPath("/etc/openpdu/") // path to look for the config file in
viper.AddConfigPath(".") // optionally look for config in the working directory viper.AddConfigPath(".") // optionally look for config in the working directory
viper.AddConfigPath("/etc/openpdu/") // path to look for the config file in
err := viper.ReadInConfig() // Find and read the config file err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file if err != nil { // Handle errors reading the config file
log.Printf("Fatal error config file: %s \n", err) log.Printf("Can't read config file: %s \n", err)
} }
viper.SetDefault("hostname", "openpdu")
} }

View File

@ -6,6 +6,7 @@ import (
"log" "log"
"net" "net"
"github.com/spf13/viper"
"golang.org/x/image/font" "golang.org/x/image/font"
"golang.org/x/image/font/basicfont" "golang.org/x/image/font/basicfont"
"golang.org/x/image/math/fixed" "golang.org/x/image/math/fixed"
@ -14,6 +15,18 @@ import (
"periph.io/x/periph/devices/ssd1306" "periph.io/x/periph/devices/ssd1306"
) )
func init() {
viper.SetDefault("DisplayType", "none")
displayLoop()
}
func displayLoop() {
if viper.GetString("DisplayType") == "ssd1306" {
initI2C()
go disp()
}
}
func addLabel(img *image.RGBA, x, y int, label string) { func addLabel(img *image.RGBA, x, y int, label string) {
col := color.RGBA{200, 100, 0, 255} col := color.RGBA{200, 100, 0, 255}
point := fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)} point := fixed.Point26_6{fixed.Int26_6(x * 64), fixed.Int26_6(y * 64)}

View File

@ -12,17 +12,14 @@ import (
// Dictionary aaa // Dictionary aaa
type Dictionary map[string]interface{} type Dictionary map[string]interface{}
func init() {
viper.SetDefault("hostname", "openpdu")
}
func main() { func main() {
readConfig() readConfig()
go mqttLoop()
nam := viper.Get("hostname") log.Printf("hostname: %v\n", viper.Get("hostname"))
log.Printf("hostname: %v\n", nam)
initI2C()
go disp()
startServer() startServer()
} }

View File

@ -2,32 +2,85 @@ package main
import ( import (
"fmt" "fmt"
"os" "time"
MQTT "github.com/eclipse/paho.mqtt.golang" MQTT "github.com/eclipse/paho.mqtt.golang"
"github.com/spf13/viper"
) )
var MQTTclient MQTT.Client
func init() { func init() {
// set the protocol, ip and port of the broker. viper.SetDefault("MqttCliendID", "OpenPDU") // max 23 chars
opts := MQTT.NewClientOptions().AddBroker("tcp://localhost:1883") viper.SetDefault("MqttPrefix", "openpdu") // max 23 chars
viper.SetDefault("MqttSchema", "tcp")
viper.SetDefault("MqttHost", "localhost")
viper.SetDefault("MqttPort", "1883")
viper.SetDefault("MqttUsername", "")
viper.SetDefault("MqttPassword", "")
// set the id to the client. // MQTT.ERROR = log.New(os.Stdout, "[ERROR] ", 0)
opts.SetClientID("Device-pub") // MQTT.CRITICAL = log.New(os.Stdout, "[CRIT] ", 0)
// MQTT.WARN = log.New(os.Stdout, "[WARN] ", 0)
// MQTT.DEBUG = log.New(os.Stdout, "[DEBUG] ", 0)
// create a new client. //MQTTclient.Subscribe("some_topic", 0, nil);
c := MQTT.NewClient(opts) //MQTTclient.Disconnect(250)
token := c.Connect()
token.Wait()
if token.Error() != nil {
fmt.Println(token.Error())
os.Exit(1)
}
message := "hello this is the trial message"
c.Publish("some_topic", 0, false, message)
//c.Subscribe("some_topic", 0, nil);
c.Disconnect(250)
} }
// https://girishjoshi.io/post/golang-paho-mqtt/ // https://girishjoshi.io/post/golang-paho-mqtt/
func mqttLoop() {
uri := viper.GetString("MqttSchema") + "://" + viper.GetString("MqttHost") + ":" + viper.GetString("MqttPort")
opts := MQTT.NewClientOptions().AddBroker(uri)
opts.SetClientID(viper.GetString("MqttCliendID"))
if username := viper.GetString("MqttUsername"); username != "" {
opts.SetUsername(username)
}
if password := viper.GetString("MqttPassword"); password != "" {
opts.SetPassword(password)
}
opts.SetAutoReconnect(true)
opts.SetConnectRetryInterval(5 * time.Second)
opts.SetConnectTimeout(5 * time.Second)
opts.SetConnectionLostHandler(func(c MQTT.Client, err error) {
fmt.Printf("!!!!!! mqtt connection lost error: %s\n" + err.Error())
})
opts.SetReconnectingHandler(func(c MQTT.Client, options *MQTT.ClientOptions) {
fmt.Println("...... mqtt reconnecting ......")
})
opts.SetOnConnectHandler(func(c MQTT.Client) {
fmt.Println("...... mqtt connected ......")
// MQTTclient.Publish("openpdu/status", 0, false, "connected")
})
MQTTclient = MQTT.NewClient(opts)
for {
token := MQTTclient.Connect()
token.Wait()
if MQTTclient.IsConnected() {
break
}
time.Sleep(5 * time.Second)
}
}
func MQTTreconfigure() {
if MQTTclient.IsConnected() {
MQTTclient.Disconnect(250)
}
go mqttLoop()
}
func MQTTpublish(topic string, value string) {
if MQTTclient.IsConnected() {
MQTTclient.Publish(viper.GetString("MqttPrefix")+"/"+topic, 0, false, value)
}
}

56
src/mqtt_ui.go Normal file
View File

@ -0,0 +1,56 @@
package main
import (
"strings"
"github.com/spf13/viper"
"gopkg.in/macaron.v1"
)
func mqttPage(ctx *macaron.Context) {
ctx.Data["schema"] = viper.GetString("MqttSchema")
ctx.Data["host"] = viper.GetString("MqttHost")
ctx.Data["port"] = viper.GetString("MqttPort")
ctx.Data["clientid"] = viper.GetString("MqttCliendID")
ctx.Data["prefix"] = viper.GetString("MqttPrefix")
ctx.Data["username"] = viper.GetString("MqttUsername")
ctx.Data["password"] = viper.GetString("MqttPassword")
ctx.Data["schemas"] = []string{"tcp", "ssl", "ws"}
ctx.HTML(200, "mqtt")
}
type MQTTPostForm struct {
Schema string `form:"schema" binding:"Required"`
Host string `form:"host" binding:"Required"`
Port string `form:"port" binding:"Required"`
Prefix string `form:"prefix" binding:"Required"`
ClientID string `form:"clientid" binding:"Required"`
Username string `form:"username"`
Password string `form:"password"`
}
func mqttPost(ctx *macaron.Context, f MQTTPostForm) {
schema := strings.ToLower(strings.TrimSpace(f.Schema))
switch schema {
case
"tcp",
"ssl",
"ws":
viper.Set("MqttSchema", schema)
default:
mqttPage(ctx)
return
}
viper.Set("MqttHost", strings.ToLower(strings.TrimSpace(f.Host)))
viper.Set("MqttPort", strings.ToLower(strings.TrimSpace(f.Port)))
viper.Set("MqttCliendID", strings.TrimSpace(f.ClientID))
viper.Set("MqttPrefix", strings.TrimSpace(f.Prefix))
viper.Set("MqttUsername", strings.TrimSpace(f.Username))
viper.Set("MqttPassword", f.Password)
viper.WriteConfig()
mqttPage(ctx)
}

View File

@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"github.com/go-macaron/binding"
"github.com/go-macaron/pongo2" "github.com/go-macaron/pongo2"
"gopkg.in/macaron.v1" "gopkg.in/macaron.v1"
) )
@ -25,6 +26,7 @@ func statusPage(ctx *macaron.Context) {
} }
func jsonStatus(ctx *macaron.Context) { func jsonStatus(ctx *macaron.Context) {
MQTTpublish("openpdu/status", "asdss")
p0, err := MyBoard.channelStatus(0) p0, err := MyBoard.channelStatus(0)
if err != nil { if err != nil {
@ -85,10 +87,12 @@ func jsonOutletToggle(ctx *macaron.Context) {
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
MQTTpublish("openpdu/toggolo1", string(id))
err = MyBoard.channelToggle(uint(id)) err = MyBoard.channelToggle(uint(id))
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
MQTTpublish("openpdu/toggolo2", string(id))
ctx.JSON(http.StatusOK, Dictionary{ ctx.JSON(http.StatusOK, Dictionary{
"data": "ok", "data": "ok",
}) })
@ -101,6 +105,8 @@ func startServer() {
// m.Get("/", myHandler) // m.Get("/", myHandler)
m.Get("/", statusPage) m.Get("/", statusPage)
m.Get("/mqtt", mqttPage)
m.Post("/mqtt", binding.Bind(MQTTPostForm{}), mqttPost)
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

@ -26,20 +26,33 @@
</a> </a>
</li> </li>
{% if pageselected in "lan mqtt ups syslog backup restore" %}
<li class="treeview active menu-open">
{% else %}
<li class="treeview"> <li class="treeview">
{% endif %}
<a href="#"> <a href="#">
<i class="fa fa-gears"></i> <span>Settings</span> <i class="fa fa-gears"></i> <span>Settings</span>
<span class="pull-right-container"> <span class="pull-right-container">
<i class="fa fa-angle-left pull-right"></i> <i class="fa fa-angle-left pull-right"></i>
</span> </span>
</a> </a>
<ul class="treeview-menu"> <ul class="treeview-menu">
<li><a href="/settings/lan"><i class="fa fa-circle-o"></i> LAN</a></li> <li><a href="/lan"><i class="fa fa-circle-o"></i> LAN</a></li>
<li><a href="/settings/mqtt"><i class="fa fa-circle-o"></i> MQTT</a></li>
<li><a href="/settings/ups"><i class="fa fa-circle-o"></i> UPS</a></li> {% if pageselected == "mqtt" %}
<li><a href="/settings/syslog"><i class="fa fa-circle-o"></i> syslog</a></li> <li class="active">
<li><a href="/settings/backup"><i class="fa fa-circle-o"></i> backup</a></li> {% else %}
<li><a href="/settings/restore"><i class="fa fa-circle-o"></i> restore</a></li> <li>
{% endif %}
<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>
<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="/restore"><i class="fa fa-circle-o"></i> restore</a></li>
</ul> </ul>
</li> </li>
</ul> </ul>

123
templates/mqtt.html Normal file
View File

@ -0,0 +1,123 @@
<!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="mqtt" %}
{% 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">MQTT configuration</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form class="form-horizontal" method="post">
<div class="box-body">
<div class="form-group">
<label for="schema" class="col-sm-2 control-label">Schema</label>
<div class="col-sm-10">
<select class="form-control" id="schema" name="schema">
{% for i in schemas %}
{% if i == schema %}
<option value="{{ i }}" selected>{{ i }}</option>
{% else %}
<option value="{{ i }}">{{ i }}</option>
{% endif %}
{% endfor %}
</select>
</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="port" class="col-sm-2 control-label">Port</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="port" name="port" placeholder="1883" value="{{ port }}">
</div>
</div>
<div class="form-group">
<label for="clientid" class="col-sm-2 control-label">Client ID</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="clientid" name="clientid" placeholder="client id" value="{{ clientid }}">
</div>
</div>
<div class="form-group">
<label for="prefix" class="col-sm-2 control-label">Prefix</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="prefix" name="prefix" placeholder="topic prefix" value="{{ prefix }}">
</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>