Update openpdu_example.yaml, board.go, and 11 more files...

This commit is contained in:
Paolo Asperti 2021-01-04 18:37:10 +01:00
parent 0687cb2258
commit ef2b809707
13 changed files with 601 additions and 280 deletions

View File

@ -4,7 +4,8 @@ display:
swaptopbottom: false swaptopbottom: false
type: ssd1306 type: ssd1306
w: 128 w: 128
hostname: openpdu-rack1 system:
hostname: openpdu-rack1
mqtt: mqtt:
cliendid: openpdu-main cliendid: openpdu-main
@ -25,23 +26,24 @@ boards:
type: dummy type: dummy
inverted: false inverted: false
channelCount: 4 channelCount: 4
name: The Dummy Board
channels: channels:
4976c508-1f63-4894-a859-cc5bd555b3c1: 4976c508-1f63-4894-a859-cc5bd555b3c1:
num: 0 num: 0
name: autonomo name: autonomo
startValue: false onboot: off
c0a4d271-2b75-41c0-8b05-86c5ca0b3e94: c0a4d271-2b75-41c0-8b05-86c5ca0b3e94:
num: 1 num: 1
name: fenomeno name: fenomeno
startValue: false onboot: off
4d0b384f-6bcb-4eca-a803-ebea90c2a434: 4d0b384f-6bcb-4eca-a803-ebea90c2a434:
num: 2 num: 2
name: ecomeno name: ecomeno
startValue: false onboot: off
acb5e9d5-959c-4427-a850-17c262b96c16: acb5e9d5-959c-4427-a850-17c262b96c16:
num: 3 num: 3
name: ripopolo name: ripopolo
startValue: false onboot: off
outlets: outlets:
0fca047e-0e7f-4cee-83a8-2086ee306faf: 0fca047e-0e7f-4cee-83a8-2086ee306faf:
num: 0 num: 0

View File

@ -9,46 +9,48 @@ import (
) )
type Channel struct { type Channel struct {
id string ID string
num uint Num uint
name string Name string
value bool Value bool
inverted bool // low level only Inverted bool // low level only
startValue bool OnBoot string
parent *Board Parent *Board
} }
type Board struct { type Board struct {
id string ID string
name string Name string
channelCount uint ChannelCount uint
inverted bool // low level only Inverted bool // low level only
channels []Channel Channels []Channel
} }
type Outlet struct { type Outlet struct {
num uint ID string
board *Board Num uint
channel *Channel Description string
Board *Board
Channel *Channel
} }
func (c Channel) Toggle() (bool, error) { func (c Channel) Toggle() (bool, error) {
c.value = !c.value c.Value = !c.Value
return c.value, nil return c.Value, nil
} }
func (c Channel) On() error { func (c Channel) On() error {
c.value = true c.Value = true
return nil return nil
} }
func (c Channel) Off() error { func (c Channel) Off() error {
c.value = true c.Value = true
return nil return nil
} }
func (c Channel) Status() bool { func (c Channel) Status() bool {
return c.value return c.Value
} }
var boards []Board var boards []Board
@ -57,17 +59,26 @@ var outlets []Outlet
func newDummyChannel(v *viper.Viper, channelID string) Channel { func newDummyChannel(v *viper.Viper, channelID string) Channel {
v.SetDefault("name", "unknown") v.SetDefault("name", "unknown")
v.SetDefault("startValue", false) v.SetDefault("lastValue", false)
v.SetDefault("inverted", false) v.SetDefault("inverted", false)
v.SetDefault("onboot", "off")
value := false
switch v.GetString("onboot") {
case "on":
value = true
case "last":
value = v.GetBool("lastValue")
}
// newUUID := UUID.New().String() // newUUID := UUID.New().String()
// v.SetDefault("id", newUUID) // v.SetDefault("id", newUUID)
return Channel{ return Channel{
id: channelID, ID: channelID,
num: v.GetUint("num"), Num: v.GetUint("num"),
name: v.GetString("name"), Name: v.GetString("name"),
value: v.GetBool("startValue"), Value: value,
inverted: v.GetBool("inverted"), Inverted: v.GetBool("inverted"),
startValue: v.GetBool("startValue"), OnBoot: v.GetString("onboot"),
} }
} }
@ -87,10 +98,10 @@ func newDummyBoard(v *viper.Viper, id string) Board {
} }
b = Board{ b = Board{
id: id, ID: id,
name: v.GetString("name"), Name: v.GetString("name"),
channelCount: v.GetUint("channelCount"), ChannelCount: v.GetUint("channelCount"),
inverted: v.GetBool("inverted"), Inverted: v.GetBool("inverted"),
} }
channels := make([]Channel, v.GetInt("channelCount")) channels := make([]Channel, v.GetInt("channelCount"))
@ -101,16 +112,16 @@ func newDummyBoard(v *viper.Viper, id string) Board {
channelid := strings.ToLower(channelid1) channelid := strings.ToLower(channelid1)
channelConfig := channelsConfig.Sub(channelid) channelConfig := channelsConfig.Sub(channelid)
c := newDummyChannel(channelConfig, channelid) c := newDummyChannel(channelConfig, channelid)
c.parent = &b c.Parent = &b
if c.num >= v.GetUint("channelCount") { if c.Num >= v.GetUint("channelCount") {
continue continue
} }
channels[c.num] = c channels[c.Num] = c
allChannels[c.id] = &c allChannels[c.ID] = &c
} }
} }
} }
b.channels = channels b.Channels = channels
return b return b
} }
@ -139,6 +150,8 @@ func parseBoardsConfig() {
} }
outlets = make([]Outlet, len(allChannels))
outletsConfig := viper.Sub("outlets") outletsConfig := viper.Sub("outlets")
if outletsConfig == nil { if outletsConfig == nil {
logWarning("No outlet configured") logWarning("No outlet configured")
@ -148,16 +161,20 @@ func parseBoardsConfig() {
for key := range outletsConfig.AllSettings() { for key := range outletsConfig.AllSettings() {
outletConfig := outletsConfig.Sub(key) outletConfig := outletsConfig.Sub(key)
num := outletConfig.GetUint("num") num := outletConfig.GetUint("num")
outletConfig.SetDefault("description", "no description")
description := outletConfig.GetString("description")
channelID := strings.ToLower(outletConfig.GetString("channelID")) channelID := strings.ToLower(outletConfig.GetString("channelID"))
channel := allChannels[channelID] channel := allChannels[channelID]
// TODO: channel non esistente // TODO: channel non esistente
o := Outlet{ o := Outlet{
num: num, ID: key,
board: channel.parent, Num: num,
channel: channel, Description: description,
Board: channel.Parent,
Channel: channel,
} }
outlets = append(outlets, o) outlets[num] = o
} }
// dumpa tutto // dumpa tutto
@ -173,20 +190,16 @@ func parseBoardsConfig() {
} }
func (c Channel) Dump() { func (c Channel) Dump() {
v := "off" log.Printf(" Channel %d (on boot: %s): %s \n", c.Num, c.OnBoot, c.Name)
if c.startValue {
v = "on"
}
log.Printf(" Channel %d (start: %s): %s \n", c.num, v, c.name)
} }
func (b Board) Dump() { func (b Board) Dump() {
log.Printf("Board '%s' (id: %s): %d channels\n", b.name, b.id, b.channelCount) log.Printf("Board '%s' (id: %s): %d channels\n", b.Name, b.ID, b.ChannelCount)
for c := range b.channels { for c := range b.Channels {
b.channels[c].Dump() b.Channels[c].Dump()
} }
} }
func (o Outlet) Dump() { func (o Outlet) Dump() {
log.Printf("Outlet %v: channel name: %v\n", o.num, o.channel.name) log.Printf("Outlet %v: channel name: %v\n", o.Num, o.Channel.Name)
} }

1
src/board_ui.go Normal file
View File

@ -0,0 +1 @@
package main

View File

@ -8,14 +8,14 @@ import (
type Dictionary map[string]interface{} type Dictionary map[string]interface{}
func init() { func init() {
viper.SetDefault("hostname", "openpdu") viper.SetDefault("system.hostname", "openpdu")
} }
func main() { func main() {
parseBoardsConfig() parseBoardsConfig()
go mqttLoop() go mqttLoop()
go UpsConnect() go UpsConnect()
logInfo("hostname: " + viper.GetString("hostname")) logInfo("hostname: " + viper.GetString("system.hostname"))
startServer() startServer()
} }

82
src/outlets_ui.go Normal file
View File

@ -0,0 +1,82 @@
package main
import (
"fmt"
"net/http"
"strconv"
"strings"
"github.com/spf13/viper"
"gopkg.in/macaron.v1"
)
func outletsPage(ctx *macaron.Context) {
ctx.Data["outlets"] = outlets
ctx.HTML(200, "outlets")
}
type OutletPostForm struct {
Description string `form:"description" binding:"Required"`
OnBoot string `form:"onboot" binding:"Required"`
}
func outletEditPage(ctx *macaron.Context) {
var err error
var num uint64
var o Outlet
num, err = strconv.ParseUint(ctx.Params(":num"), 10, 64)
if err != nil {
ctx.JSON(http.StatusOK, Dictionary{
"result": "error",
"error": err.Error(),
})
return
}
o = outlets[num]
ctx.Data["outlet"] = o
ctx.Data["onboot_values"] = []string{"on", "off", "last"}
ctx.HTML(200, "outlet_edit")
}
func outletEditPost(ctx *macaron.Context, f OutletPostForm) {
var err error
var num uint64
num, err = strconv.ParseUint(ctx.Params(":num"), 10, 64)
if err != nil {
ctx.JSON(http.StatusOK, Dictionary{
"result": "error",
"error": err.Error(),
})
return
}
onboot := "on"
onbootForm := strings.ToLower(strings.TrimSpace(f.OnBoot))
switch onbootForm {
case
"on",
"off",
"last":
onboot = onbootForm
default:
outletsPage(ctx)
return
}
outlets[num].Channel.OnBoot = onboot
s1 := fmt.Sprintf("boards.%s.channels.%s.onboot", outlets[num].Board.ID, outlets[num].Channel.ID)
viper.Set(s1, onboot)
outlets[num].Description = strings.TrimSpace(f.Description)
s2 := fmt.Sprintf("outlets.%s.description", outlets[num].ID)
viper.Set(s2, outlets[num].Description)
viper.WriteConfig()
ctx.Redirect("/outlets")
}

View File

@ -33,7 +33,7 @@ func jsonStatus(ctx *macaron.Context) {
var o Outlet var o Outlet
for i := range outlets { for i := range outlets {
o = outlets[i] o = outlets[i]
d := []string{fmt.Sprintf("%d", o.num), o.channel.name, fmt.Sprintf("%v", o.channel.value)} d := []string{fmt.Sprintf("%d", o.Num), o.Channel.Name, fmt.Sprintf("%v", o.Channel.Value)}
data = append(data, d) data = append(data, d)
} }
@ -59,7 +59,7 @@ func jsonOutletToggle(ctx *macaron.Context) {
} }
func init() { func init() {
viper.SetDefault("listeningport", 4000) viper.SetDefault("system.listeningport", 4000)
} }
func startServer() { func startServer() {
@ -69,6 +69,9 @@ func startServer() {
// m.Get("/", myHandler) // m.Get("/", myHandler)
m.Get("/", statusPage) m.Get("/", statusPage)
m.Get("/outlets", outletsPage)
m.Get("/outlet/:num", outletEditPage)
m.Post("/outlet/:num", binding.Bind(OutletPostForm{}), outletEditPost)
m.Get("/lan", lanPage) m.Get("/lan", lanPage)
m.Get("/mqtt", mqttPage) m.Get("/mqtt", mqttPage)
m.Post("/mqtt", binding.Bind(MQTTPostForm{}), mqttPost) m.Post("/mqtt", binding.Bind(MQTTPostForm{}), mqttPost)
@ -83,8 +86,8 @@ func startServer() {
ctx.HTML(200, "boards") // 200 is the response code. ctx.HTML(200, "boards") // 200 is the response code.
}) })
logInfo("hostname: " + viper.GetString("hostname")) logInfo("hostname: " + viper.GetString("system.hostname"))
logInfo("Web interface ready") logInfo("Web interface ready")
http.ListenAndServe("0.0.0.0:"+viper.GetString("listeningport"), m) http.ListenAndServe("0.0.0.0:"+viper.GetString("system.listeningport"), m)
} }

View File

@ -4,16 +4,16 @@
<!-- Tell the browser to be responsive to screen width --> <!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport"> <meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.7 --> <!-- Bootstrap 3.3.7 -->
<link rel="stylesheet" href="../../bower_components/bootstrap/dist/css/bootstrap.min.css"> <link rel="stylesheet" href="/bower_components/bootstrap/dist/css/bootstrap.min.css">
<!-- Font Awesome --> <!-- Font Awesome -->
<link rel="stylesheet" href="../../bower_components/font-awesome/css/font-awesome.min.css"> <link rel="stylesheet" href="/bower_components/font-awesome/css/font-awesome.min.css">
<!-- Ionicons --> <!-- Ionicons -->
<link rel="stylesheet" href="../../bower_components/Ionicons/css/ionicons.min.css"> <link rel="stylesheet" href="/bower_components/Ionicons/css/ionicons.min.css">
<!-- Theme style --> <!-- Theme style -->
<link rel="stylesheet" href="adminlte/css/AdminLTE.min.css"> <link rel="stylesheet" href="/adminlte/css/AdminLTE.min.css">
<!-- AdminLTE Skins. Choose a skin from the css/skins <!-- AdminLTE Skins. Choose a skin from the css/skins
folder instead of downloading all of them to reduce the load. --> folder instead of downloading all of them to reduce the load. -->
<link rel="stylesheet" href="adminlte/css/skins/_all-skins.min.css"> <link rel="stylesheet" href="/adminlte/css/skins/_all-skins.min.css">
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries --> <!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// --> <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
@ -23,4 +23,4 @@
<![endif]--> <![endif]-->
<!-- Google Font --> <!-- Google Font -->
<link rel="stylesheet" href="../../googlefonts/fonts.css"> <link rel="stylesheet" href="/googlefonts/fonts.css">

View File

@ -1,10 +1,10 @@
<!-- jQuery 3 --> <!-- jQuery 3 -->
<script src="../../bower_components/jquery/dist/jquery.min.js"></script> <script src="/bower_components/jquery/dist/jquery.min.js"></script>
<!-- Bootstrap 3.3.7 --> <!-- Bootstrap 3.3.7 -->
<script src="../../bower_components/bootstrap/dist/js/bootstrap.min.js"></script> <script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<!-- Slimscroll --> <!-- Slimscroll -->
<script src="../../bower_components/jquery-slimscroll/jquery.slimscroll.min.js"></script> <script src="/bower_components/jquery-slimscroll/jquery.slimscroll.min.js"></script>
<!-- FastClick --> <!-- FastClick -->
<script src="../../bower_components/fastclick/lib/fastclick.js"></script> <script src="/bower_components/fastclick/lib/fastclick.js"></script>
<!-- AdminLTE App --> <!-- AdminLTE App -->
<script src="adminlte/js/adminlte.min.js"></script> <script src="/adminlte/js/adminlte.min.js"></script>

View File

@ -19,7 +19,7 @@
</li> </li>
<li class="treeview {% if pageselected in " lan mqtt ups syslog backup " %}active menu-open{% endif %}"> <li class="treeview {% if pageselected in " outlets lan mqtt ups syslog backup " %}active menu-open{% endif %}">
<a href="#"> <a href="#">
<i class="fa fa-gears"></i> <i class="fa fa-gears"></i>
@ -30,6 +30,10 @@
</a> </a>
<ul class="treeview-menu"> <ul class="treeview-menu">
<li {% if pageselected=="outlets" %}class="active" {% endif %}>
<a href="/outlets"><i class="fa fa-circle-o"></i> Outlets</a>
</li>
<li {% if pageselected=="lan" %}class="active" {% endif %}> <li {% if pageselected=="lan" %}class="active" {% endif %}>
<a href="/lan"><i class="fa fa-circle-o"></i> LAN</a> <a href="/lan"><i class="fa fa-circle-o"></i> LAN</a>
</li> </li>

View File

@ -2,121 +2,124 @@
<html> <html>
<head> <head>
{% include "common/common-head.html" %} {% include "common/common-head.html" %}
</head> </head>
<body class="hold-transition skin-blue sidebar-mini"> <body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper"> <div class="wrapper">
{% include "common/page-header.html" %} {% with pageselected="mqtt" %} {% 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">
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-12">
<!-- Main content --> <div class="box box-info">
<section class="content"> <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">
<div class="row"> <label for="schema" class="col-sm-2 control-label">Schema</label>
<div class="col-xs-12"> <div class="col-sm-10">
<select class="form-control" id="schema" name="schema">
{% for i in schemas %}
<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 %} {% if i == schema %}
<option value="{{ i }}" selected>{{ i }}</option> <option value="{{ i }}" selected>{{ i }}</option>
{% else %} {% else %}
<option value="{{ i }}">{{ i }}</option> <option value="{{ i }}">{{ i }}</option>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
</select> </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> </div>
<!-- /.col --> </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> </div>
<!-- /.row -->
</section> <!-- /.box-body -->
<!-- /.content --> <div class="box-footer">
<button type="submit" class="btn btn-info pull-right">Save</button>
</div>
<!-- /.box-footer -->
</form>
</div>
</div>
<!-- /.col -->
</div> </div>
<!-- /.content-wrapper --> <!-- /.row -->
{% include "common/footer.html" %}
</section>
<!-- /.content -->
</div> </div>
<!-- ./wrapper --> <!-- /.content-wrapper -->
{% include "common/common-js.html" %} {% include "common/footer.html" %}
</div>
<!-- ./wrapper -->
{% include "common/common-js.html" %}
</body> </body>
</html> </html>

114
templates/outlet_edit.html Normal file
View File

@ -0,0 +1,114 @@
<!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="outlets" %}
{% 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">Outlet configuration</h3>
</div>
<!-- /.box-header -->
<!-- form start -->
<form class="form-horizontal" method="post">
<div class="box-body">
<div class="form-group">
<label for="num" class="col-sm-2 control-label">Outlet #</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="num" disabled="" value="{{ outlet.Num }}">
</div>
</div>
<div class="form-group">
<label for="description" class="col-sm-2 control-label">Description</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="description" name="description" placeholder="Enter a meaningful description"
value="{{ outlet.Description }}">
</div>
</div>
<div class="form-group">
<label for="onboot" class="col-sm-2 control-label">On Boot</label>
<div class="col-sm-10">
<select class="form-control" id="onboot" name="onboot">
{% for i in onboot_values %}
{% if i == outlet.Channel.OnBoot %}
<option value="{{ i }}" selected>{{ i }}</option>
{% else %}
<option value="{{ i }}">{{ i }}</option>
{% endif %}
{% endfor %}
</select>
</div>
</div>
<div class="form-group">
<label for="board" class="col-sm-2 control-label">Board</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="board" disabled="" value="{{ outlet.Board.Name }}">
</div>
</div>
<div class="form-group">
<label for="channel" class="col-sm-2 control-label">Board port</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="channel" disabled="" value="{{ outlet.Channel.Name }}">
</div>
</div>
<div class="form-group">
<label for="channel" class="col-sm-2 control-label">Board port #</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="channel" disabled="" value="{{ outlet.Channel.Num }}">
</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>

92
templates/outlets.html Normal file
View File

@ -0,0 +1,92 @@
<!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="outlets" %}
{% include "common/sidebar-menu.html" %}
{% endwith %}
<!-- Content Wrapper. Contains page content -->
<div class="content-wrapper">
<!-- Content Header (Page header) -->
<section class="content-header">
<h1>
Outlet configuration
</h1>
</section>
<!-- Main content -->
<section class="content">
<div class="row">
<div class="col-xs-12">
<div class="box">
<div class="box-body">
<table id="outlettable" class="table table-bordered table-hover">
<thead>
<tr>
<th style="width: 15px">#</th>
<th>Description</th>
<th>Internal channel</th>
<th style="width: 150px">On boot</th>
</tr>
</thead>
<tbody>
{%- for outlet in outlets -%}
<tr>
<td>{{ outlet.Num }}</td>
<td><a href="/outlet/{{ outlet.Num }}">{{ outlet.Description }}</a></td>
<td>{{ outlet.Channel.Name }}</td>
<td>{{ outlet.Channel.OnBoot }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- /.box-body -->
</div>
<!-- /.box -->
</div>
<!-- /.col -->
</div>
<!-- /.row -->
</section>
<!-- /.content -->
</div>
<!-- /.content-wrapper -->
{% include "common/footer.html" %}
</div>
<!-- ./wrapper -->
{% include "common/common-js.html" %}
<!-- DataTables -->
<script src="../../bower_components/datatables.net/js/jquery.dataTables.min.js"></script>
<script src="../../bower_components/datatables.net-bs/js/dataTables.bootstrap.min.js"></script>
<script>
$(function () {
var table = $('#outlettable').DataTable({
paging: false,
});
});
</script>
</body>
</html>

View File

@ -2,136 +2,143 @@
<html> <html>
<head> <head>
{% include "common/common-head.html" %} {% include "common/common-head.html" %}
</head> </head>
<body class="hold-transition skin-blue sidebar-mini"> <body class="hold-transition skin-blue sidebar-mini">
<div class="wrapper"> <div class="wrapper">
{% include "common/page-header.html" %} {% with pageselected="ups" %} {% include "common/sidebar-menu.html" %} {% endwith %} {% include "common/page-header.html" %}
{% with pageselected="ups" %}
{% include "common/sidebar-menu.html" %}
{% endwith %}
<!-- Content Wrapper. Contains page content --> <!-- Content Wrapper. Contains page content -->
<div class="content-wrapper"> <div class="content-wrapper">
<!-- Main content --> <!-- Main content -->
<section class="content"> <section class="content">
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-xs-12">
<div class="box box-info"> <div class="box box-info">
<div class="box-header with-border"> <div class="box-header with-border">
<h3 class="box-title">UPS configuration</h3> <h3 class="box-title">UPS configuration</h3>
</div> </div>
<!-- /.box-header --> <!-- /.box-header -->
<!-- form start --> <!-- form start -->
<form class="form-horizontal" method="post"> <form class="form-horizontal" method="post">
<div class="box-body"> <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="upsload" class="col-sm-2 control-label">UPS Load</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsload" disabled="" value="{{ upsload }} %">
</div>
</div>
<div class="form-group">
<label for="upscharge" class="col-sm-2 control-label">UPS Charge</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upscharge" disabled="" value="{{ upscharge }} %">
</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 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>
<!-- /.col --> </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="upsload" class="col-sm-2 control-label">UPS Load</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upsload" disabled="" value="{{ upsload }} %">
</div>
</div>
<div class="form-group">
<label for="upscharge" class="col-sm-2 control-label">UPS Charge</label>
<div class="col-sm-10">
<input type="text" class="form-control" id="upscharge" disabled="" value="{{ upscharge }} %">
</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> </div>
<!-- /.row -->
</section> <!-- /.box-body -->
<!-- /.content --> <div class="box-footer">
<button type="submit" class="btn btn-info pull-right">Save</button>
</div>
<!-- /.box-footer -->
</form>
</div>
</div>
<!-- /.col -->
</div> </div>
<!-- /.content-wrapper --> <!-- /.row -->
{% include "common/footer.html" %}
</section>
<!-- /.content -->
</div> </div>
<!-- ./wrapper --> <!-- /.content-wrapper -->
{% include "common/common-js.html" %} {% include "common/footer.html" %}
</div>
<!-- ./wrapper -->
{% include "common/common-js.html" %}
</body> </body>