This commit is contained in:
2019-08-21 23:47:24 +02:00
parent 969ae63d02
commit bd0b562dcd
21 changed files with 495 additions and 487 deletions

20
source/config.go Normal file
View File

@@ -0,0 +1,20 @@
package main
import (
"log"
"github.com/spf13/viper"
)
func readConfig() {
viper.SetConfigName("openpdu.yaml") // name of config file (without extension)
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
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
log.Printf("Fatal error config file: %s \n", err)
}
viper.SetDefault("hostname", "openpdu")
}

View File

@@ -1,196 +0,0 @@
package main
import (
"encoding/json"
"gopkg.in/macaron.v1"
// "github.com/go-macaron/pongo2"
mypongo2 "github.com/flosch/pongo2"
"log"
"net/http"
"os"
"os/exec"
"strings"
)
const CFGFILE = "/config/config.json"
const WEBSITETPLFILE = "/app/website.tpl"
const WEBSITENGINXFILE = "/etc/nginx/conf.d/websites.conf"
const ADMINTPLFILE = "/app/admin.tpl"
const ADMINNGINXFILE = "/etc/nginx/conf.d/admin.conf"
var Config struct {
Admin Website `json:"admin"`
Websites []Website `json:"websites"`
}
type Website struct {
Name string `json:"name"`
Enabled bool `json:"enabled"`
Url string `json:"url"`
Aliases []string `json:"aliases"`
Http Http `json:"http"`
Https Https `json:"https"`
}
type Http struct {
Redirect_to_https bool `json:"redirect_to_https"`
Locations []Location `json:"locations"`
}
type Https struct {
Http2 bool `json:"http2"`
Letsencrypt bool `json:"letsencrypt"`
Locations []Location `json:"locations"`
}
type Location struct {
Location string `json:"location"`
Destination string `json:"destination"`
}
func loadConfig() {
jsonFile, err := os.Open(CFGFILE)
if err != nil {
log.Println(err)
}
defer jsonFile.Close()
jsonParser := json.NewDecoder(jsonFile)
if err = jsonParser.Decode(&Config); err != nil {
log.Println("Error parsing config file: ", err.Error())
}
log.Println("Successfully parsed: " + CFGFILE)
}
func startServer() {
m := macaron.Classic()
// m.Use(macaron.Static("public")) // static files served by nginx
m.Get("/", myHandler)
log.Println("Server is running...")
log.Println(http.ListenAndServe("0.0.0.0:4000", m))
}
func main() {
loadConfig()
writeAdminTemplate()
writeTemplate()
nginxReloadConfig()
startServer()
}
func nginxReloadConfig() {
// TODO: check why this is always in error but it's working...
_, err := exec.Command("/usr/sbin/nginx", "-s", "reload").Output()
if err != nil {
log.Printf("Successfully reloaded nginx config")
} else {
log.Printf("could not reload nginx: %s", err)
}
}
func writeTemplate() {
t, err := mypongo2.FromFile(WEBSITETPLFILE)
if err != nil {
log.Printf("could not render: %s", err)
return
}
f, err := os.Create(WEBSITENGINXFILE)
if err != nil {
log.Printf("cannot open: %s", WEBSITENGINXFILE)
}
defer f.Close()
for _, v := range Config.Websites {
var http_locations []map[string]string
var https_locations []map[string]string
for _, s := range v.Http.Locations {
loc := map[string]string{
"location": s.Location,
"destination": s.Destination,
}
http_locations = append(http_locations, loc)
}
for _, s := range v.Https.Locations {
loc := map[string]string{
"location": s.Location,
"destination": s.Destination,
}
https_locations = append(https_locations, loc)
}
data := mypongo2.Context{
"url": v.Url,
"name": v.Name,
"http2": v.Https.Http2,
"aliases": v.Aliases,
"http_redirect_to_https": v.Http.Redirect_to_https,
"https_locations": https_locations,
"http_locations": http_locations,
}
if err := t.ExecuteWriter(data, f); err != nil {
log.Printf("could not execute: %s", err)
}
}
log.Printf("Successfully created: %s", WEBSITENGINXFILE)
}
func writeAdminTemplate() {
t, err := mypongo2.FromFile(ADMINTPLFILE)
if err != nil {
log.Printf("could not render: %s", err)
return
}
f, err := os.Create(ADMINNGINXFILE)
if err != nil {
log.Printf("cannot open: %s", ADMINNGINXFILE)
}
defer f.Close()
data := mypongo2.Context{
"url": Config.Admin.Url,
"http2": Config.Admin.Https.Http2,
"http_redirect_to_https": Config.Admin.Http.Redirect_to_https,
}
if err := t.ExecuteWriter(data, f); err != nil {
log.Printf("could not execute: %s", err)
}
log.Printf("Successfully created: %s", ADMINNGINXFILE)
}
func myHandler(ctx *macaron.Context) string {
return "The request path is: " + ctx.Req.RequestURI
}
func init() {
mypongo2.RegisterFilter("filterdomaindots", PongoFilterDomainDots)
}
func PongoFilterDomainDots(in *mypongo2.Value, param *mypongo2.Value) (out *mypongo2.Value, err *mypongo2.Error) {
if !in.IsString() {
return nil, &mypongo2.Error{
Sender: "you should use only strings",
}
}
s := in.String()
s = strings.Replace(s, ".", "\\.", -1)
return mypongo2.AsValue(s), nil
}

85
source/i2c.go Normal file
View File

@@ -0,0 +1,85 @@
package main
import (
"errors"
"log"
"periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/i2c/i2creg"
"periph.io/x/periph/host"
)
// I2CBoard bla
type I2CBoard struct {
i2cdev i2c.Dev
channels uint
data []byte
inverted bool
}
// MyBoard bla
var MyBoard = I2CBoard{
channels: 8,
inverted: true,
}
func (b I2CBoard) channelStatus(ch uint) (bool, error) {
if b.channels <= 0 {
return false, errors.New("Board without channels")
}
if ch >= b.channels {
return false, errors.New("Invalid channel")
}
write := []byte{0x0A}
b.data = make([]byte, 2)
err := b.i2cdev.Tx(write, b.data)
if err != nil {
return false, err
}
byteToConsider := ch / b.channels
value := (b.data[byteToConsider] >> ch & 1) == 1
if b.inverted {
value = !value
}
return value, nil
}
func initI2C() {
// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
log.Fatal(err)
}
// Use i2creg I²C bus registry to find the first available I²C bus.
mybus, err := i2creg.Open("/dev/i2c-0")
if err != nil {
log.Fatal(err)
}
// defer mybus.Close()
// bus 0
// Dev is a valid conn.Conn.
mydevice := &i2c.Dev{Addr: 0x27, Bus: mybus}
// Send a command 0x10 and expect a 5 bytes reply.
// write := []byte{0x10}
write := []byte{0x0}
// read := make([]byte, 5)
// if err := d.Tx(write, read); err != nil {
if _, err := mydevice.Write(write); err != nil {
log.Fatal(err)
}
MyBoard.i2cdev = *mydevice
go func() {
var i uint
for i = 0; i < 8; i++ {
v, err := MyBoard.channelStatus(i)
if err != nil {
log.Fatal(err)
}
log.Printf("Channel %d status: %v", i, v)
}
}()
}

View File

@@ -1,127 +1,29 @@
package main
import (
// "encoding/json"
"github.com/go-macaron/pongo2"
"gopkg.in/macaron.v1"
"net/http"
// "encoding/json"
"log"
// "periph.io/x/periph"
"periph.io/x/periph/host"
"periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/i2c/i2creg"
"time"
// "periph.io/x/periph"
"github.com/spf13/viper"
)
// Dictionary aaa
type Dictionary map[string]interface{}
func readConfig() {
viper.SetConfigName("openpdu.yaml") // name of config file (without extension)
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
err := viper.ReadInConfig() // Find and read the config file
if err != nil { // Handle errors reading the config file
log.Printf("Fatal error config file: %s \n", err)
}
viper.SetDefault("hostname","openpdu")
}
func initI2C() {
// Make sure periph is initialized.
if _, err := host.Init(); err != nil {
log.Fatal(err)
}
// Use i2creg I²C bus registry to find the first available I²C bus.
b, err := i2creg.Open("/dev/i2c-0")
if err != nil {
log.Fatal(err)
}
defer b.Close()
// bus 0
// Dev is a valid conn.Conn.
d := &i2c.Dev{Addr: 0x27, Bus: b}
// Send a command 0x10 and expect a 5 bytes reply.
// write := []byte{0x10}
write := []byte{0x0}
// read := make([]byte, 5)
// if err := d.Tx(write, read); err != nil {
if _, err := d.Write(write); err != nil {
log.Fatal(err)
}
for i := 0; i < 2; i++ {
write := []byte{0x0A}
read := make([]byte, 5)
if err := d.Tx(write, read); err != nil {
log.Fatal(err)
}
log.Printf("%v\n", read)
time.Sleep(500 * time.Millisecond)
}
}
// func myHandler(ctx *macaron.Context) string {
// ctx.Data["name"] = "jeremy"
// ctx.HTML(200, "hello") // 200 is the response code.
// return "The request path is: " + ctx.Req.RequestURI
// }
func startServer() {
m := macaron.Classic()
m.Use(pongo2.Pongoer())
m.Use(macaron.Static("static"))
// m.Get("/", myHandler)
m.Get("/", func(ctx *macaron.Context) {
ctx.Data["pluglist"] = []Dictionary{
{"id": 1, "description": "p1"},
{"id": 2, "description": "p2"},
{"id": 3, "description": "p3"},
{"id": 4, "description": "p4"},
{"id": 5, "description": "p5"},
{"id": 6, "description": "p6"},
{"id": 7, "description": "p7"},
{"id": 8, "description": "p8"},
}
ctx.HTML(200, "status") // 200 is the response code.
})
m.Get("/boards", func(ctx *macaron.Context) {
ctx.HTML(200, "boards") // 200 is the response code.
})
log.Println("Server is running...")
log.Println(http.ListenAndServe("0.0.0.0:4000", m))
}
func main() {
readConfig()
nam := viper.Get("name")
log.Printf("name: %v\n", nam)
nam := viper.Get("hostname")
log.Printf("hostname: %v\n", nam)
initI2C()
startServer()
}
// https://github.com/ColorlibHQ/AdminLTE/archive/v2.4.17.tar.gz
/* TODO
@@ -135,4 +37,4 @@ func main() {
- impostazioni mqtt
*/
*/

91
source/webui.go Normal file
View File

@@ -0,0 +1,91 @@
package main
import (
"fmt"
"log"
"net/http"
"github.com/go-macaron/pongo2"
"gopkg.in/macaron.v1"
)
func startServer() {
m := macaron.Classic()
m.Use(pongo2.Pongoer())
m.Use(macaron.Static("static"))
// m.Get("/", myHandler)
m.Get("/", func(ctx *macaron.Context) {
ctx.Data["pluglist"] = []Dictionary{
{"id": 1, "description": "p1"},
{"id": 2, "description": "p2"},
{"id": 3, "description": "p3"},
{"id": 4, "description": "p4"},
{"id": 5, "description": "p5"},
{"id": 6, "description": "p6"},
{"id": 7, "description": "p7"},
{"id": 8, "description": "p8"},
}
ctx.HTML(200, "status") // 200 is the response code.
})
m.Get("/json/status", func(ctx *macaron.Context) {
p0, err := MyBoard.channelStatus(0)
if err != nil {
log.Fatal(err)
}
p1, err := MyBoard.channelStatus(1)
if err != nil {
log.Fatal(err)
}
p2, err := MyBoard.channelStatus(2)
if err != nil {
log.Fatal(err)
}
p3, err := MyBoard.channelStatus(3)
if err != nil {
log.Fatal(err)
}
p4, err := MyBoard.channelStatus(4)
if err != nil {
log.Fatal(err)
}
p5, err := MyBoard.channelStatus(5)
if err != nil {
log.Fatal(err)
}
p6, err := MyBoard.channelStatus(6)
if err != nil {
log.Fatal(err)
}
p7, err := MyBoard.channelStatus(7)
if err != nil {
log.Fatal(err)
}
p1 = p1 && p2 && p3 && p4 && p5 && p6 && p7
ctx.JSON(http.StatusOK, Dictionary{
"data": [][]string{
{"0", "p0", fmt.Sprint(p0)},
{"1", "p1", fmt.Sprint(p1)},
{"2", "p2", fmt.Sprint(p2)},
},
})
})
m.Get("/boards", func(ctx *macaron.Context) {
ctx.HTML(200, "boards") // 200 is the response code.
})
log.Println("Server is running...")
log.Println(http.ListenAndServe("0.0.0.0:4000", m))
}