Skip to content
This repository has been archived by the owner on May 26, 2023. It is now read-only.

Commit

Permalink
feat: add support for core-command read
Browse files Browse the repository at this point in the history
This commit adds support for the `read` command of the `command` endpoint.

```
edgex-cli command read
```

Adds support for the `-j`, `-v` flags, which generate raw JSON output.
Adds support for the `-p` flag; if set, a successful GET will result in
an event being pushed to the EdgeX system
Adds support for the `-r` flag; if set, there will be no Event returned
in the http response

Signed-off-by: Mengyi <mengyi.wang@canonical.com>
  • Loading branch information
MonicaisHer committed Oct 19, 2021
1 parent fa2629c commit 83c667c
Show file tree
Hide file tree
Showing 3 changed files with 166 additions and 2 deletions.
112 changes: 112 additions & 0 deletions internal/cmd/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright (C) 2021 Canonical Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
* SPDX-License-Identifier: Apache-2.0'
*/

package cmd

import (
jsonpkg "encoding/json"
"fmt"
"github.com/spf13/cobra"
"os"
"text/tabwriter"
)

var deviceName, commandName string
var pushEvent, noReturnEvent bool

func init() {
commandCmd := initCommandCommand()
initReadCommand(commandCmd)
}

func initCommandCommand() *cobra.Command {
var cmd = &cobra.Command{
Use: "command",
Short: "read, write and list commands",
Long: ``,
SilenceUsage: true,
}
rootCmd.AddCommand(cmd)
addFormatFlags(cmd)
return cmd
}

func initReadCommand(cmd *cobra.Command) {
var readCmd = &cobra.Command{
Use: "read",
Short: "read command referenced by the command name and device name",
Long: `Issue the specified read command referenced by the command name to the device/sensor that is also referenced by name`,
RunE: handleReadCommand,
SilenceUsage: true,
}
readCmd.Flags().StringVarP(&deviceName, "device", "d", "", "Specify the name of device")
readCmd.Flags().StringVarP(&commandName, "command", "c", "", "Specify the name of the command to be executed")
readCmd.Flags().BoolVarP(&pushEvent, "pushevent", "p", false, "If set, a successful GET will result in an event being pushed to the EdgeX system")
readCmd.Flags().BoolVarP(&noReturnEvent, "noreturnevent", "r", false, "If set, there will be no Event returned in the http response")
readCmd.MarkFlagRequired("device")
readCmd.MarkFlagRequired("command")
cmd.AddCommand(readCmd)
addFormatFlags(readCmd)
}

func handleReadCommand(cmd *cobra.Command, args []string) error {
dsPushEvent := boolToString(pushEvent)
dsReturnEvent := boolToString(!noReturnEvent)

//issue READ command and handle output if nothing can be displayed
response, err := getCoreCommandService().IssueReadCommand(deviceName, commandName, dsPushEvent, dsReturnEvent)
if err != nil {
return err
}

if response == nil {
fmt.Println("Read command issued. Nothing to display. Please retry without flag -r.")
return nil
}

//print READ command's output with one of these formats: JSON, verbose or table
if json || verbose {
stringifiedResponse, err := jsonpkg.Marshal(response)
if err != nil {
return err
}

if verbose {
url := getCoreCommandService().GetReadEndpoint(deviceName, commandName, dsPushEvent, dsReturnEvent)
fmt.Printf("Result:%s\nURL: %s\n", string(stringifiedResponse), url)
} else {
fmt.Printf("%s\n", stringifiedResponse)
}
} else {
w := tabwriter.NewWriter(os.Stdout, 1, 1, 2, ' ', 0)
fmt.Fprintln(w, "Command Name\tDevice Name\tProfile Name\tValue Type\tValue")
for _, reading := range response.Event.Readings {
fmt.Fprintf(w, "%s\t%s\t%s\t%s\t%s\n",
commandName, reading.DeviceName, reading.ProfileName, reading.ValueType, reading.Value)
}
w.Flush()
}
return nil
}

//using by READ when it specified dsPushEvent or dsReturnEvent
func boolToString(b bool) string {
if b {
return "yes"
} else {
return "no"
}
}
8 changes: 6 additions & 2 deletions internal/cmd/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ func getSelectedServiceKey() string {
}
}

func getCoreCommandService() service.Service {
return config.GetCoreService(common.CoreCommandServiceKey)
}

func getSelectedServices() map[string]service.Service {
key := getSelectedServiceKey()
if key == "" {
Expand All @@ -56,13 +60,13 @@ func getSelectedServices() map[string]service.Service {

func addFormatFlags(cmd *cobra.Command) {
cmd.Flags().BoolVarP(&json, "json", "j", false, "show the raw JSON response")
cmd.Flags().BoolVarP(&verbose, "debug", "d", false, "show verbose/debug output")
cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "show verbose/debug output")

}

func addStandardFlags(cmd *cobra.Command) {
addFormatFlags(cmd)
cmd.Flags().BoolVarP(&data, "data", "", false, "use core-data service endpoint")
cmd.Flags().BoolVarP(&data, "data", "d", false, "use core-data service endpoint")
cmd.Flags().BoolVarP(&command, "command", "c", false, "use core-command service endpoint")
cmd.Flags().BoolVarP(&metadata, "metadata", "m", false, "use core-metadata service endpoint")
cmd.Flags().BoolVarP(&scheduler, "scheduler", "s", false, "use support-scheduler service endpoint")
Expand Down
48 changes: 48 additions & 0 deletions internal/service/corecommandservice.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright (C) 2021 Canonical Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
* in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*
* SPDX-License-Identifier: Apache-2.0'
*/

package service

import (
"context"
"fmt"
"github.com/edgexfoundry/go-mod-core-contracts/v2/clients/http"
"github.com/edgexfoundry/go-mod-core-contracts/v2/clients/interfaces"
"github.com/edgexfoundry/go-mod-core-contracts/v2/common"
"github.com/edgexfoundry/go-mod-core-contracts/v2/dtos/responses"
"strings"
)

func (c Service) IssueReadCommand(deviceName string, commandName string, dsPushEvent string, dsReturnEvent string) (response *responses.EventResponse, err error) {
client := c.getCommandClient()
response, err = client.IssueGetCommandByName(context.Background(), deviceName, commandName, dsPushEvent, dsReturnEvent)
return
}

func (c Service) GetReadEndpoint(deviceName string, commandName string, dsPushEvent string, dsReturnEvent string) string {
url := c.getEndpointUrl(common.ApiDeviceNameCommandNameRoute)
replacer := strings.NewReplacer("{name}", deviceName, "{command}", commandName)
return replacer.Replace(url) + "?ds-pushevent=" + dsPushEvent + "&ds-returnevent=" + dsReturnEvent
}

func (c Service) getEndpointUrl(endpoint string) string {
return fmt.Sprintf("http://%s:%v%s", c.Host, c.Port, endpoint)
}

func (c Service) getCommandClient() interfaces.CommandClient {
url := fmt.Sprintf("http://%s:%v", c.Host, c.Port)
return http.NewCommandClient(url)
}

0 comments on commit 83c667c

Please sign in to comment.