Improve JSON-RPC methods for emlid interaction
This commit is contained in:
@ -1,13 +1,17 @@
|
||||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"forge.cadoles.com/Pyxis/orion/emlid"
|
||||
"forge.cadoles.com/Pyxis/orion/emlid/updater"
|
||||
"forge.cadoles.com/Pyxis/orion/openwrt"
|
||||
"github.com/gorilla/rpc"
|
||||
"github.com/gorilla/rpc/json"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// OrionService is the JSON-RPC API
|
||||
@ -71,6 +75,7 @@ func (o *OrionService) OwrtCreateWifiInterface(r *http.Request,
|
||||
args *CreateIfaceArgs,
|
||||
reply *CreateIfaceResponse) error {
|
||||
reply.Iface = nil
|
||||
|
||||
if args.Cleanup {
|
||||
o.UCI.LoadWirelessConf()
|
||||
w := o.UCI.GetWifiIfaces()
|
||||
@ -153,6 +158,154 @@ func (o *OrionService) OwrtConnectWifiInterface(r *http.Request,
|
||||
return nil
|
||||
}
|
||||
|
||||
// OrionBox describe an fresh Orion box (base or rover)
|
||||
type OrionBox struct {
|
||||
Address string
|
||||
SSID string
|
||||
Security string
|
||||
WifiKey string
|
||||
}
|
||||
|
||||
// OrionServer describe the Orion master server
|
||||
type OrionServer struct {
|
||||
Address string
|
||||
SSID string
|
||||
Security string
|
||||
WifiKey string
|
||||
ClientIface *openwrt.UCIWirelessInterface
|
||||
}
|
||||
|
||||
// UpdateOrionBoxArgs argument structure for exported method OwrtCreateWifiInterface
|
||||
type UpdateOrionBoxArgs struct {
|
||||
Box *OrionBox
|
||||
Server *OrionServer
|
||||
}
|
||||
|
||||
// UpdateOrionBoxResponse argument structure for exported method OwrtCreateWifiInterface
|
||||
type UpdateOrionBoxResponse struct {
|
||||
IP string
|
||||
Netmask string
|
||||
Synced bool
|
||||
Version string
|
||||
Errors []string
|
||||
}
|
||||
|
||||
// Connect wifi interface to a Orion box wifi hotspot!
|
||||
func (o *OrionService) connectBox(box *OrionBox, server *OrionServer) error {
|
||||
o.UCI.LoadWirelessConf()
|
||||
if server == nil {
|
||||
return fmt.Errorf("Server definition is empty")
|
||||
}
|
||||
|
||||
if box == nil {
|
||||
return fmt.Errorf("Box definitioni is emtpy")
|
||||
}
|
||||
fmt.Println("DEBUG")
|
||||
fmt.Println(server)
|
||||
fmt.Println("DEBUG")
|
||||
iface := server.ClientIface
|
||||
cells := iface.Scan()
|
||||
for _, cell := range cells {
|
||||
fmt.Printf("Cell : %s\n", cell.Ssid)
|
||||
if cell.Ssid == box.SSID {
|
||||
cn := iface.Connect(o.UCI, cell, box.WifiKey)
|
||||
if cn.ReturnCode != 0 {
|
||||
return fmt.Errorf("%s\n%s", cn.Stdout, cn.Stderr)
|
||||
}
|
||||
dhcli := openwrt.NewDhcpClient(iface.SysDevName)
|
||||
dhres := dhcli.AskForIP()
|
||||
if dhres.CmdRes.ReturnCode != 0 {
|
||||
return fmt.Errorf("%s\n%s", cn.Stdout, cn.Stderr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("Wifi cell with SSID %s is not available", box.SSID)
|
||||
}
|
||||
|
||||
// UpdateOrionBox starts provisionning process for an Orion box (base or rover)
|
||||
func (o *OrionService) UpdateOrionBox(r *http.Request,
|
||||
args *UpdateOrionBoxArgs,
|
||||
reply *UpdateOrionBoxResponse) error {
|
||||
|
||||
if err := o.connectBox(args.Box, args.Server); err != nil {
|
||||
reply.Errors = append(reply.Errors, err.Error())
|
||||
return errors.Wrap(err, "Connect to box failed")
|
||||
}
|
||||
|
||||
re := o.UCI.Reload()
|
||||
if re.ReturnCode != 0 {
|
||||
return fmt.Errorf("%s\n%s", re.Stdout, re.Stderr)
|
||||
}
|
||||
|
||||
ssid := args.Server.SSID
|
||||
security := args.Server.Security
|
||||
wifiKey := args.Server.WifiKey
|
||||
|
||||
if security == "" {
|
||||
security = string(updater.SecurityWPAPSK)
|
||||
}
|
||||
|
||||
//services, err := emlid.Discover(20 * time.Second)
|
||||
//if err != nil {
|
||||
// return err
|
||||
//}
|
||||
|
||||
//if len(services) == 0 {
|
||||
// return fmt.Errorf("Discovery don't find any Orion Box")
|
||||
//}
|
||||
|
||||
//fmt.Println(services)
|
||||
boxCli := updater.NewClient(
|
||||
//emlid.WithService(services[0]),
|
||||
emlid.WithEndpoint(args.Box.Address, 80),
|
||||
)
|
||||
|
||||
if err := boxCli.Connect(); err != nil {
|
||||
return errors.Wrap(err, "Box connect to master failed")
|
||||
}
|
||||
defer boxCli.Close()
|
||||
|
||||
ctx, addWifiCancel := context.WithTimeout(r.Context(), 55*time.Second)
|
||||
defer addWifiCancel()
|
||||
|
||||
done, err := boxCli.AddWifiNetwork(ctx, ssid, updater.WifiSecurity(security), wifiKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "AddWifiNetworkFailed")
|
||||
}
|
||||
|
||||
if !done {
|
||||
return fmt.Errorf("Impossible to add wifi network")
|
||||
}
|
||||
|
||||
ctx, joinWifiCancel := context.WithTimeout(ctx, 55*time.Second)
|
||||
defer joinWifiCancel()
|
||||
|
||||
if err := boxCli.JoinWifiNetwork(ctx, ssid, true); err != nil {
|
||||
return errors.Wrap(err, "Time sync failed")
|
||||
}
|
||||
|
||||
ctx, timeSyncedCancel := context.WithTimeout(r.Context(), 55*time.Second)
|
||||
defer timeSyncedCancel()
|
||||
synced, err := boxCli.TimeSynced(ctx)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "Time sync failed")
|
||||
}
|
||||
reply.Synced = synced
|
||||
|
||||
ctx, reachviewVersionCancel := context.WithTimeout(r.Context(), 55*time.Second)
|
||||
defer reachviewVersionCancel()
|
||||
version, err := boxCli.ReachViewVersion(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reply.Version = version
|
||||
|
||||
ctx, rebootCancel := context.WithTimeout(r.Context(), 55*time.Second)
|
||||
defer rebootCancel()
|
||||
return boxCli.RebootNow(ctx, true)
|
||||
}
|
||||
|
||||
// NewServer returns a new configured JSON-RPC server
|
||||
func NewServer() *rpc.Server {
|
||||
server := rpc.NewServer()
|
||||
|
Reference in New Issue
Block a user