533 lines
16 KiB
Go
533 lines
16 KiB
Go
package cli_client
|
|
|
|
import (
|
|
"fmt"
|
|
pb "github.com/mame82/P4wnP1_go/proto"
|
|
"errors"
|
|
"context"
|
|
"google.golang.org/grpc"
|
|
"io"
|
|
"log"
|
|
"time"
|
|
)
|
|
|
|
|
|
|
|
func ClientConnectServer(rpcHost string, rpcPort string) (
|
|
connection *grpc.ClientConn,
|
|
client pb.P4WNP1Client,
|
|
ctx context.Context,
|
|
cancel context.CancelFunc,
|
|
err error) {
|
|
// Set up a connection to the server.
|
|
address := rpcHost + ":" + rpcPort
|
|
//log.Printf("Connecting %s ...", address)
|
|
connection, err = grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {
|
|
log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err)
|
|
}
|
|
//defer conn.Close()
|
|
|
|
client = pb.NewP4WNP1Client(connection)
|
|
|
|
// Contact the server
|
|
ctx, cancel = context.WithTimeout(context.Background(), time.Second*3)
|
|
//defer cancel()
|
|
|
|
err = nil
|
|
return
|
|
}
|
|
|
|
func ClientTriggerGroupWait(host string, port string, groupname string, value int32) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { return errors.New(fmt.Sprintf("Could not connect to P4wnP1 RPC server: %v", err)) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
|
|
_,err = rpcClient.WaitTriggerGroupReceive(ctx, &pb.TriggerGroupReceive{GroupName: groupname, Value: value})
|
|
|
|
return
|
|
}
|
|
func ClientTriggerGroupSend(host string, port string, groupname string, value int32) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { return errors.New(fmt.Sprintf("Could not connect to P4wnP1 RPC server: %v", err)) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
ctx,cancel := context.WithTimeout(ctx,TIMEOUT_SHORT)
|
|
defer cancel()
|
|
|
|
_,err = rpcClient.FireActionGroupSend(ctx, &pb.ActionGroupSend{GroupName: groupname, Value: value})
|
|
|
|
return
|
|
}
|
|
|
|
func ClientCreateTempDir(host string, port string, dir string, prefix string) (resultPath string, err error) {
|
|
return clientCreateTempDirOfFile(host,port,dir,prefix,true)
|
|
}
|
|
|
|
func ClientCreateTempFile(host string, port string, dir string, prefix string) (resultPath string, err error) {
|
|
return clientCreateTempDirOfFile(host,port,dir,prefix,false)
|
|
}
|
|
|
|
func ClientMountUMSImage(host string, port string, file string, cdrom bool) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {return}
|
|
defer connection.Close()
|
|
client := pb.NewP4WNP1Client(connection)
|
|
_,err = client.MountUMSFile(
|
|
context.Background(),
|
|
&pb.GadgetSettingsUMS{
|
|
File: file,
|
|
Cdrom: cdrom,
|
|
})
|
|
return
|
|
}
|
|
|
|
func clientCreateTempDirOfFile(host string, port string, dir string, prefix string, dirOnlyNoFile bool) (resultPath string, err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {return}
|
|
defer connection.Close()
|
|
client := pb.NewP4WNP1Client(connection)
|
|
resp, err := client.FSCreateTempDirOrFile(
|
|
context.Background(),
|
|
&pb.TempDirOrFileRequest{
|
|
Prefix: prefix,
|
|
Dir: dir,
|
|
OnlyFolder: dirOnlyNoFile,
|
|
})
|
|
if err != nil {return}
|
|
resultPath = resp.ResultPath
|
|
return
|
|
}
|
|
|
|
|
|
func ClientRegisterEvent(host string, port string, evtType int64) (err error) {
|
|
// open gRPC Client
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {return}
|
|
defer connection.Close()
|
|
client := pb.NewP4WNP1Client(connection)
|
|
evStream, err := client.EventListen(context.Background(), &pb.EventRequest{ListenType: evtType})
|
|
if err != nil { return err }
|
|
|
|
for {
|
|
event, err := evStream.Recv()
|
|
if err == io.EOF { break }
|
|
if err != nil { return err }
|
|
|
|
log.Printf("Event: %+v", event)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func ClientUploadFile(host string, port string, src io.Reader, folder pb.AccessibleFolder, filename string, forceOverwrite bool) (err error) {
|
|
|
|
// open gRPC Client
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {return}
|
|
defer connection.Close()
|
|
client := pb.NewP4WNP1Client(connection)
|
|
|
|
//try to create remote file
|
|
_, err = client.FSWriteFile(
|
|
context.Background(),
|
|
&pb.WriteFileRequest{
|
|
Folder:folder,
|
|
Filename: filename,
|
|
Data: []byte{}, //empty chunk
|
|
Append: false,
|
|
MustNotExist: !forceOverwrite,
|
|
})
|
|
if err != nil {return}
|
|
|
|
fmt.Printf("Start appending to '%s' in folder '%s'\n", filename, pb.AccessibleFolder_name[int32(folder)])
|
|
|
|
// start appending chunks read from source file to remote file (Remote file is closed and opened every time, but
|
|
// this avoids client to server streaming, which would be hard to implement for gRPC-web
|
|
chunksize := 1024
|
|
buf := make([]byte,chunksize)
|
|
pos := int64(0)
|
|
for {
|
|
n,rErr := src.Read(buf)
|
|
if rErr != nil {
|
|
if rErr == io.EOF { break } else { return rErr }
|
|
}
|
|
|
|
sendData := buf[:n]
|
|
client.FSWriteFile(
|
|
context.Background(),
|
|
&pb.WriteFileRequest{
|
|
Folder:folder,
|
|
Filename: filename,
|
|
Data: sendData,
|
|
Append: true,
|
|
MustNotExist: false,
|
|
})
|
|
|
|
pos += int64(n)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func ClientGetLED(host string, port string) (ls *pb.LEDSettings, err error) {
|
|
conn, client, ctx, cancel, err := ClientConnectServer(host, port)
|
|
defer conn.Close()
|
|
defer cancel()
|
|
if err != nil { return }
|
|
|
|
ls, err = client.GetLEDSettings(ctx, &pb.Empty{})
|
|
if err != nil {
|
|
log.Printf("Error getting LED blink count: %v", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func ClientReboot(host string, port string, timeout time.Duration) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
_,err = rpcClient.Reboot(ctx, &pb.Empty{})
|
|
return
|
|
}
|
|
|
|
func ClientShutdown(host string, port string, timeout time.Duration) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
_,err = rpcClient.Shutdown(ctx, &pb.Empty{})
|
|
return
|
|
}
|
|
|
|
|
|
func ClientDeployGadgetSettings(host string, port string, newGs *pb.GadgetSettings) (gs *pb.GadgetSettings, err error) {
|
|
conn, client, ctx, cancel, err := ClientConnectServer(host, port)
|
|
defer conn.Close()
|
|
defer cancel()
|
|
if err != nil { return }
|
|
|
|
|
|
gs, err = client.DeployGadgetSetting(ctx, newGs)
|
|
if err != nil {
|
|
log.Printf("Error deploying current USB Gadget Settings: %+v", err)
|
|
//We have an error case, thus gs isn't submitted by the gRPC server (even if the value is provided)
|
|
//in case of an error `gs`should reflect the Gadget Settings which are deployed, now that deployment of the
|
|
//new settings failed. So we fetch the result manually
|
|
gs, _ = client.GetDeployedGadgetSetting(ctx, &pb.Empty{}) //We ignore a new error this time, if it occures `gs` will be nil
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func ClientGetDeployedGadgetSettings(host string, port string) (gs *pb.GadgetSettings, err error) {
|
|
conn, client, ctx, cancel, err := ClientConnectServer(host, port)
|
|
defer conn.Close()
|
|
defer cancel()
|
|
if err != nil { return }
|
|
|
|
gs, err = client.GetDeployedGadgetSetting(ctx, &pb.Empty{})
|
|
if err != nil {
|
|
log.Printf("Error getting USB Gadget Settings count: %+v", err)
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func ClientSetLED(host string, port string, ls pb.LEDSettings) (err error) {
|
|
conn, client, ctx, cancel, err := ClientConnectServer(host, port)
|
|
defer conn.Close()
|
|
defer cancel()
|
|
if err != nil { return }
|
|
|
|
_, err = client.SetLEDSettings(ctx, &ls)
|
|
if err != nil {
|
|
log.Printf("Error setting LED blink count %d: %v", ls.BlinkCount, err)
|
|
}
|
|
|
|
|
|
return
|
|
}
|
|
|
|
func ClientDeployEthernetInterfaceSettings(host string, port string, settings *pb.EthernetInterfaceSettings) (err error) {
|
|
// Set up a connection to the server.
|
|
address := host + ":" + port
|
|
//log.Printf("Connecting %s ...", address)
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {
|
|
log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err)
|
|
}
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
|
|
// Contact the server
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30)
|
|
defer cancel()
|
|
|
|
_, err = rpcClient.DeployEthernetInterfaceSettings(ctx, settings)
|
|
return
|
|
|
|
}
|
|
|
|
func ClientDeployWifiSettings(host string, port string, settings *pb.WiFiSettings) (state *pb.WiFiState, err error) {
|
|
// Set up a connection to the server.
|
|
address := host + ":" + port
|
|
//log.Printf("Connecting %s ...", address)
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil {
|
|
log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err)
|
|
}
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
|
|
// Contact the server
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30)
|
|
defer cancel()
|
|
|
|
state,err = rpcClient.DeployWiFiSettings(ctx, settings)
|
|
return
|
|
}
|
|
|
|
func ClientHIDRunScript(host string, port string, ctx context.Context, scriptPath string, timeoutSeconds uint32) (scriptRes *pb.HIDScriptResult, err error) {
|
|
scriptReq := &pb.HIDScriptRequest{
|
|
ScriptPath: scriptPath,
|
|
TimeoutSeconds: timeoutSeconds,
|
|
}
|
|
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
|
|
scriptRes,err = rpcClient.HIDRunScript(ctx, scriptReq)
|
|
return
|
|
}
|
|
|
|
func ClientHIDRunScriptJob(host string, port string, scriptPath string, timeoutSeconds uint32) (scriptJob *pb.HIDScriptJob, err error) {
|
|
scriptReq := &pb.HIDScriptRequest{
|
|
ScriptPath: scriptPath,
|
|
TimeoutSeconds: timeoutSeconds,
|
|
}
|
|
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30)
|
|
defer cancel()
|
|
|
|
scriptJob,err = rpcClient.HIDRunScriptJob(ctx, scriptReq)
|
|
return
|
|
}
|
|
|
|
func ClientHIDCancelScriptJob(host string, port string, jobID uint32) (err error) {
|
|
cancelReq := &pb.HIDScriptJob{
|
|
Id: jobID,
|
|
}
|
|
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30)
|
|
defer cancel()
|
|
|
|
_,err = rpcClient.HIDCancelScriptJob(ctx, cancelReq)
|
|
return
|
|
}
|
|
|
|
|
|
func ClientHIDGetScriptJobResult(host string, port string, jobID uint32) (scriptRes *pb.HIDScriptResult, err error) {
|
|
req := &pb.HIDScriptJob{
|
|
Id: jobID,
|
|
}
|
|
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
// ctx, cancel := context.WithTimeout(context.Background(), time.Second * 30)
|
|
// defer cancel()
|
|
|
|
scriptRes,err = rpcClient.HIDGetScriptJobResult(context.Background(), req)
|
|
return
|
|
}
|
|
|
|
func ClientListTemplateType(timeout time.Duration, host string, port string, ttype pb.ActionDeploySettingsTemplate_TemplateType) (res []string, err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
switch ttype {
|
|
case pb.ActionDeploySettingsTemplate_USB:
|
|
ma,err := rpcClient.ListStoredUSBSettings(ctx, &pb.Empty{})
|
|
if err != nil { return res,err }
|
|
return ma.MsgArray,nil
|
|
case pb.ActionDeploySettingsTemplate_TRIGGER_ACTIONS:
|
|
ma,err := rpcClient.ListStoredTriggerActionSets(ctx, &pb.Empty{})
|
|
if err != nil { return res,err }
|
|
return ma.MsgArray,nil
|
|
case pb.ActionDeploySettingsTemplate_WIFI:
|
|
ma,err := rpcClient.ListStoredWifiSettings(ctx, &pb.Empty{})
|
|
if err != nil { return res,err }
|
|
return ma.MsgArray,nil
|
|
case pb.ActionDeploySettingsTemplate_NETWORK:
|
|
ma,err := rpcClient.ListStoredEthernetInterfaceSettings(ctx, &pb.Empty{})
|
|
if err != nil { return res,err }
|
|
return ma.MsgArray,nil
|
|
case pb.ActionDeploySettingsTemplate_BLUETOOTH:
|
|
ma,err := rpcClient.ListStoredBluetoothSettings(ctx, &pb.Empty{})
|
|
if err != nil { return res,err }
|
|
return ma.MsgArray,nil
|
|
case pb.ActionDeploySettingsTemplate_FULL_SETTINGS:
|
|
ma,err := rpcClient.ListStoredMasterTemplate(ctx, &pb.Empty{})
|
|
if err != nil { return res,err }
|
|
return ma.MsgArray,nil
|
|
default:
|
|
return res,errors.New("unknown template type")
|
|
}
|
|
|
|
|
|
}
|
|
|
|
func ClientDeployTemplateType(timeout time.Duration, host string, port string, ttype pb.ActionDeploySettingsTemplate_TemplateType, name string) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
switch ttype {
|
|
case pb.ActionDeploySettingsTemplate_USB:
|
|
_,err = rpcClient.DeployStoredUSBSettings(ctx, &pb.StringMessage{Msg:name})
|
|
case pb.ActionDeploySettingsTemplate_TRIGGER_ACTIONS:
|
|
_,err = rpcClient.DeployStoredTriggerActionSetReplace(ctx, &pb.StringMessage{Msg:name})
|
|
case pb.ActionDeploySettingsTemplate_WIFI:
|
|
_,err = rpcClient.DeployStoredWifiSettings(ctx, &pb.StringMessage{Msg:name})
|
|
case pb.ActionDeploySettingsTemplate_NETWORK:
|
|
_,err = rpcClient.DeployStoredEthernetInterfaceSettings(ctx, &pb.StringMessage{Msg:name})
|
|
case pb.ActionDeploySettingsTemplate_BLUETOOTH:
|
|
_,err = rpcClient.DeployStoredBluetoothSettings(ctx, &pb.StringMessage{Msg:name})
|
|
case pb.ActionDeploySettingsTemplate_FULL_SETTINGS:
|
|
_,err = rpcClient.DeployStoredMasterTemplate(ctx, &pb.StringMessage{Msg:name})
|
|
default:
|
|
return errors.New("unknown template type")
|
|
}
|
|
|
|
return
|
|
}
|
|
|
|
func ClientDBBackup(timeout time.Duration, host string, port string, name string) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
_,err = rpcClient.DBBackup(ctx, &pb.StringMessage{Msg:name})
|
|
|
|
return
|
|
}
|
|
|
|
func ClientDBRestore(timeout time.Duration, host string, port string, name string) (err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
_,err = rpcClient.DBRestore(ctx, &pb.StringMessage{Msg:name})
|
|
|
|
return
|
|
}
|
|
|
|
func ClientDBList(timeout time.Duration, host string, port string) (names []string, err error) {
|
|
address := host + ":" + port
|
|
connection, err := grpc.Dial(address, grpc.WithInsecure())
|
|
if err != nil { log.Fatalf("Could not connect to P4wnP1 RPC server: %v", err) }
|
|
defer connection.Close()
|
|
|
|
rpcClient := pb.NewP4WNP1Client(connection)
|
|
ctx := context.Background()
|
|
if timeout > 0 {
|
|
ctxNew,cancel := context.WithTimeout(ctx, timeout)
|
|
ctx = ctxNew
|
|
defer cancel()
|
|
}
|
|
|
|
backups,err := rpcClient.ListStoredDBBackups(ctx, &pb.Empty{})
|
|
if err != nil { return names, err}
|
|
|
|
return backups.MsgArray,nil
|
|
}
|