th7/api/config.go

293 lines
5.8 KiB
Go
Raw Normal View History

2023-12-12 21:07:04 +00:00
package api
2023-12-05 17:22:12 +00:00
import (
"errors"
"net/http"
"strconv"
"strings"
2023-12-06 19:21:54 +00:00
cfg "th7/config"
2023-12-05 17:22:12 +00:00
"th7/data/config"
"github.com/gin-gonic/gin"
)
var (
ErrConfigChannelNotFound = errors.New("a configured channel with this ID was not found")
ErrConfigRestrictedDB = errors.New("access to the DB map is restricted")
)
func (g *GinAdapter) getConfigByID(id int) (config.Channel, error) {
for channel := range g.cfg.Channels {
if g.cfg.Channels[channel].Id == id {
return g.cfg.Channels[channel], nil
}
}
return config.Channel{}, ErrConfigChannelNotFound
}
// check if a supplied key string is in the device struct (TH7)
func configDeviceIsValidKey(key string) bool {
key = strings.ToLower(key)
for k := range deviceKeys {
if key == deviceKeys[k] {
return true
}
}
return false
}
func configDeviceIsValidValue(key string, value string) bool {
// all the values are bools for now
value = strings.ToLower(value)
return (value == "true" || value == "false")
}
// this doesn't actually do anything to program state... yet
func (g *GinAdapter) updateConfigDevice(key string, value string) error {
bValue, err := strconv.ParseBool(value)
if err != nil {
return err
}
key = strings.ToLower(key)
// might have to sync these writes ?
// go doesn't have switch case fall-thru
switch key {
case "led":
g.cfg.Board.Led = bValue
case "nolog":
g.cfg.Board.NoLog = bValue
case "noweb":
g.cfg.Board.NoWeb = bValue
case "debug":
g.cfg.Board.Debug = bValue
}
return nil
}
func (g *GinAdapter) validConfigChannel(id int) bool {
for c := range g.cfg.Channels {
if g.cfg.Channels[c].Id == id {
return true
}
}
return false
}
func configChannelIsValidKey(key string) bool {
key = strings.ToLower(key)
for k := range channelKeys {
if key == channelKeys[k] {
return true
}
}
return false
}
func (g *GinAdapter) configChannelUpdateValue(id int, key string, value string) error {
2023-12-06 19:21:54 +00:00
var cfgChannelPtr *config.Channel
2023-12-05 17:22:12 +00:00
key = strings.ToLower(key)
value = strings.ToLower(value)
2023-12-06 19:21:54 +00:00
2023-12-05 17:22:12 +00:00
foundChannel := false
// find the channel, given and checked by id
for k := range g.cfg.Channels {
if g.cfg.Channels[k].Id == id {
cfgChannelPtr = &(g.cfg.Channels[k])
foundChannel = true
}
}
if !foundChannel {
return ErrConfigChannelNotFound
}
switch key {
case "thermocouple":
2023-12-06 19:21:54 +00:00
tc, err := cfg.GetThermocoupleType(value)
2023-12-05 17:22:12 +00:00
if err != nil {
return err
}
cfgChannelPtr.Thermo = tc
case "gain":
fValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
cfgChannelPtr.Gain = fValue
case "offset":
fValue, err := strconv.ParseFloat(value, 64)
if err != nil {
return err
}
cfgChannelPtr.Offset = fValue
}
return nil
}
/*************************************************************************/
/*************************************************************************/
/*************************************************************************/
func (g *GinAdapter) GetConfigChannelByIdHandler(c *gin.Context) {
var timestamp string
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
2023-12-06 19:21:54 +00:00
c.String(http.StatusBadRequest, err.Error())
2023-12-05 17:22:12 +00:00
return
}
channel, err := g.getConfigByID(id)
if err != nil {
2023-12-06 19:21:54 +00:00
c.String(http.StatusBadRequest, err.Error())
2023-12-05 17:22:12 +00:00
return
}
timestamp = g.getTimestamp()
c.JSON(http.StatusOK, gin.H{
"channel": channel,
"time": timestamp,
})
}
func (g *GinAdapter) GetConfigChannelsHandler(c *gin.Context) {
timestamp := g.getTimestamp()
c.JSON(http.StatusOK, gin.H{
"channels": g.cfg.Channels,
"time": timestamp,
})
}
func (g *GinAdapter) GetConfigDeviceHandler(c *gin.Context) {
timestamp := g.getTimestamp()
c.JSON(http.StatusOK, gin.H{
2023-12-13 11:46:47 +00:00
"device": g.cfg.Board,
2023-12-05 17:22:12 +00:00
"time": timestamp,
})
}
func (g *GinAdapter) GetConfigDBHandler(c *gin.Context) {
var timestamp string
2023-12-12 21:07:04 +00:00
if g.cfg.API.Restricted {
2023-12-06 19:21:54 +00:00
c.String(http.StatusForbidden, ErrConfigRestrictedDB.Error())
2023-12-05 17:22:12 +00:00
return
}
timestamp = g.getTimestamp()
c.JSON(http.StatusOK, gin.H{
"db": g.cfg.DB,
"time": timestamp,
})
}
func (g *GinAdapter) SetConfigDeviceHandler(c *gin.Context) {
var req PostRequest
if err := c.ShouldBind(&req); err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
validKey := configDeviceIsValidKey(req.Key)
if !validKey {
c.String(http.StatusBadRequest, "invalid device config key")
return
}
validValue := configDeviceIsValidValue(req.Key, req.Value)
if !validValue {
c.String(http.StatusBadRequest, "invalid device config value")
return
}
err := g.updateConfigDevice(req.Key, req.Value)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
c.String(http.StatusOK, "OK")
}
// this function can only modify already set up channels, for now.
func (g *GinAdapter) SetConfigChannelByIdHandler(c *gin.Context) {
var req PostRequest
id, err := strconv.Atoi(c.Param("id"))
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
validChannel := g.validConfigChannel(id)
if !validChannel {
c.String(http.StatusBadRequest, "channel not initially configured. TODO fix")
return
}
if err := c.ShouldBind(&req); err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
validKey := configChannelIsValidKey(req.Key)
if !validKey {
c.String(http.StatusBadRequest, "invalid channel config key")
return
}
err = g.configChannelUpdateValue(id, req.Key, req.Value)
if err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
c.String(http.StatusOK, "OK")
}
func (g *GinAdapter) SetConfigDBHandler(c *gin.Context) {
var req PostRequest
2023-12-12 21:07:04 +00:00
if g.cfg.API.Restricted {
2023-12-05 17:22:12 +00:00
c.String(http.StatusForbidden, ErrConfigRestrictedDB.Error())
return
}
if err := c.ShouldBind(&req); err != nil {
c.String(http.StatusBadRequest, err.Error())
return
}
// what could go wrong?
g.cfg.DB[req.Key] = req.Value
c.String(http.StatusOK, "OK")
}