Update config.go, display.go, and 7 more files...
This commit is contained in:
parent
1219291a6d
commit
9e2ef61772
@ -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")
|
|
||||||
}
|
}
|
||||||
|
@ -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)}
|
||||||
|
15
src/main.go
15
src/main.go
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
91
src/mqtt.go
91
src/mqtt.go
@ -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
56
src/mqtt_ui.go
Normal 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)
|
||||||
|
}
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
123
templates/mqtt.html
Normal 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>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user