first version

This commit is contained in:
Jay
2021-09-16 10:19:48 +08:00
commit 05967cdb98
24 changed files with 1669 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
package api
import (
"context"
"rpirelay/config"
"rpirelay/internal/api/relay"
rt "rpirelay/internal/api/relay/transport"
cc "rpirelay/internal/context"
"rpirelay/internal/middleware"
"rpirelay/internal/server"
"github.com/stianeikeland/go-rpio/v4"
)
func Start(ctx context.Context, cfg *config.Config) chan error {
errChan := make(chan error, 0)
go func() {
if err := startAPIServer(ctx, cfg); err != nil {
errChan <- err
return
}
close(errChan)
}()
return errChan
}
func startAPIServer(ctx context.Context, cfg *config.Config) error {
var err error
// init gpio
err = rpio.Open()
if err != nil {
return err
}
defer rpio.Close()
// set gpio pin
relayPin := rpio.Pin(cfg.Server.RelayPin)
// set pin mode output
relayPin.Output()
defer func() {
relayPin.Low()
}()
// new middleware
mw := middleware.Initialize(cfg.Server.Secret)
svc := server.New(cfg)
apiGroup := svc.Group("/api")
apiGroup.Use(cc.PatchContext(mw.APIPanicCatch()))
{
rt.NewHTTP(relay.Initialize(relayPin), apiGroup, mw.Authorization())
}
svc.Start(ctx)
return nil
}
+23
View File
@@ -0,0 +1,23 @@
package relay
import cc "rpirelay/internal/context"
var _ Service = (*Relay)(nil)
func (r *Relay) SwitchOn(c *cc.C) (err error) {
r.pin.High()
return nil
}
func (r *Relay) SwitchOff(c *cc.C) (err error) {
r.pin.Low()
return nil
}
func (r *Relay) GetState(c *cc.C) (open bool, err error) {
state := r.pin.Read()
return state == 1, nil
}
+21
View File
@@ -0,0 +1,21 @@
package relay
import (
cc "rpirelay/internal/context"
"github.com/stianeikeland/go-rpio/v4"
)
func Initialize(pin rpio.Pin) *Relay {
return &Relay{pin: pin}
}
type Relay struct {
pin rpio.Pin
}
type Service interface {
SwitchOn(c *cc.C) (err error)
SwitchOff(c *cc.C) (err error)
GetState(c *cc.C) (open bool, err error)
}
+86
View File
@@ -0,0 +1,86 @@
package transport
import (
"rpirelay/internal/api/relay"
cc "rpirelay/internal/context"
apierr "rpirelay/internal/errors"
"github.com/gin-gonic/gin"
"github.com/pkg/errors"
)
type HTTP struct {
svc relay.Service
}
func NewHTTP(svc relay.Service, e *gin.RouterGroup, authorizationMW cc.CustomHandler) {
h := &HTTP{svc: svc}
patch := cc.PatchContext
g := e.Group("/relay")
g.Use(patch(authorizationMW))
// swagger:route POST /api/relay/on relay switchOn
// set relay on
// security:
// api_key:
// responses:
// default: respDefault
g.POST("/on", patch(h.switchOn()))
// swagger:route POST /api/relay/off relay switchOff
// set relay off
// security:
// api_key:
// responses:
// default: respDefault
g.POST("/off", patch(h.switchOff()))
// swagger:route GET /api/relay relay getState
// get relay state
// security:
// api_key:
// responses:
// 200: relayStateResp
// default: respDefault
g.GET("/", patch(h.getState()))
g.GET("", patch(h.getState()))
}
func (h *HTTP) switchOn() cc.CustomHandler {
return func(c *cc.C) {
if err := h.svc.SwitchOn(c); err != nil {
panic(apierr.ErrInternalError.SetErr(errors.WithStack(err)))
}
c.Success()
}
}
func (h *HTTP) switchOff() cc.CustomHandler {
return func(c *cc.C) {
if err := h.svc.SwitchOff(c); err != nil {
panic(apierr.ErrInternalError.SetErr(errors.WithStack(err)))
}
c.Success()
}
}
type relayStateResp struct {
Open bool `json:"open"`
}
func (h *HTTP) getState() cc.CustomHandler {
return func(c *cc.C) {
open, err := h.svc.GetState(c)
if err != nil {
panic(apierr.ErrInternalError.SetErr(errors.WithStack(err)))
}
resp := relayStateResp{Open: open}
c.Success(resp)
}
}
+7
View File
@@ -0,0 +1,7 @@
package transport
// swagger:response relayStateResp
type swaggRelayStateResp struct {
// in: body
Body relayStateResp
}
+26
View File
@@ -0,0 +1,26 @@
// RPI Relay API.
//
// Terms Of Service:
//
// there are no TOS at this moment, use at your own risk we take no responsibility
//
// Schemes: http, https
// Host: localhost
// BasePath: /
// Version: 0.0.1
//
// Consumes:
// - application/json
//
// Produces:
// - application/json
//
// SecurityDefinitions:
// api_key:
// type: apiKey
// name: X-Lawsnote-Key
// in: header
// description: secret
//
// swagger:meta
package api