Files
BatchuKVM/server/service/vm/gpio.go

117 lines
2.3 KiB
Go

package vm
import (
"fmt"
"os"
"strconv"
"time"
"github.com/gin-gonic/gin"
log "github.com/sirupsen/logrus"
"NanoKVM-Server/config"
"NanoKVM-Server/proto"
)
func (s *Service) SetGpio(c *gin.Context) {
var req proto.SetGpioReq
var rsp proto.Response
if err := proto.ParseFormRequest(c, &req); err != nil {
rsp.ErrRsp(c, -1, fmt.Sprintf("invalid arguments: %s", err))
return
}
device := ""
conf := config.GetInstance().Hardware
switch req.Type {
case "power":
device = conf.GPIOPower
case "reset":
device = conf.GPIOReset
default:
rsp.ErrRsp(c, -2, fmt.Sprintf("invalid power event: %s", req.Type))
return
}
var duration time.Duration
if req.Duration > 0 {
duration = time.Duration(req.Duration) * time.Millisecond
} else {
duration = 800 * time.Millisecond
}
if err := writeGpio(device, duration); err != nil {
rsp.ErrRsp(c, -3, fmt.Sprintf("operation failed: %s", err))
return
}
log.Debugf("gpio %s set successfully", device)
rsp.OkRsp(c)
}
func (s *Service) GetGpio(c *gin.Context) {
var rsp proto.Response
conf := config.GetInstance().Hardware
pwr, err := readGpio(conf.GPIOPowerLED)
if err != nil {
rsp.ErrRsp(c, -2, fmt.Sprintf("failed to read power led: %s", err))
return
}
hdd := false
if conf.Version == config.HWVersionAlpha {
hdd, err = readGpio(conf.GPIOHDDLed)
if err != nil {
rsp.ErrRsp(c, -2, fmt.Sprintf("failed to read hdd led: %s", err))
return
}
}
data := &proto.GetGpioRsp{
PWR: pwr,
HDD: hdd,
}
rsp.OkRspWithData(c, data)
}
func writeGpio(device string, duration time.Duration) error {
if err := os.WriteFile(device, []byte("1"), 0o666); err != nil {
log.Errorf("write gpio %s failed: %s", device, err)
return err
}
time.Sleep(duration)
if err := os.WriteFile(device, []byte("0"), 0o666); err != nil {
log.Errorf("write gpio %s failed: %s", device, err)
return err
}
return nil
}
func readGpio(device string) (bool, error) {
content, err := os.ReadFile(device)
if err != nil {
log.Errorf("read gpio %s failed: %s", device, err)
return false, err
}
contentStr := string(content)
if len(contentStr) > 1 {
contentStr = contentStr[:len(contentStr)-1]
}
value, err := strconv.Atoi(contentStr)
if err != nil {
log.Errorf("invalid gpio content: %s", content)
return false, nil
}
return value == 0, nil
}