Skip to content

Commit

Permalink
feat: Migrate gocoap from v2 to v3.3
Browse files Browse the repository at this point in the history
Signed-off-by: 1998-felix <[email protected]>
  • Loading branch information
felixgateru committed Apr 22, 2024
1 parent cf8155f commit bb2d8c1
Show file tree
Hide file tree
Showing 763 changed files with 292 additions and 211,161 deletions.
9 changes: 9 additions & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
COAP_CLI_HOST=localhost
COAP_CLI_PORT=5683
COAP_CLI_CONTENT_FORMAT=50
COAP_CLI_AUTH=
COAP_CLI_OBSERVE=
COAP_CLI_CERT_FILE=
COAP_CLI_KEY_FILE=
COAP_CLI_SERVER_CA_FILE=
COAP_CLI_CLIENT_CA_FILE=
15 changes: 4 additions & 11 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0

# Test binary, build with `go test -c`
*.test
build/*
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# build dirs
build
10 changes: 7 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Copyright (c) Abstract Machines
# SPDX-License-Identifier: Apache-2.0

all:
CGO_ENABLED=0 GOOS=linux go build -mod=vendor -ldflags "-s -w" -o build/coap-cli-linux cmd/main.go
CGO_ENABLED=0 GOOS=darwin go build -mod=vendor -ldflags "-s -w" -o build/coap-cli-darwin cmd/main.go
CGO_ENABLED=0 GOOS=windows go build -mod=vendor -ldflags "-s -w" -o build/coap-cli-windows cmd/main.go
CGO_ENABLED=0 GOOS=linux go build -ldflags "-s -w" -o build/coap-cli-linux cmd/main.go
CGO_ENABLED=0 GOOS=darwin go build -ldflags "-s -w" -o build/coap-cli-darwin cmd/main.go
CGO_ENABLED=0 GOOS=windows go build -ldflags "-s -w" -o build/coap-cli-windows cmd/main.go

29 changes: 17 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
# CoAP CLI
Simple CoAP cli client written in Go.

Simple CoAP cli client written in Go.

## Usage

Pre-built binary can be found here: https://github.com/mainflux/coap-cli/releases/tag/v0.3.3.
When running, please provide following format:
`coap-cli` followed by method code (`get`, `put`, `post`, `delete`) and CoAP URL. After that, you can pass following flags:

| Flag | Description | Default value |
| ---- | ---------------------------------------------- | ---------------- |
| o | observe option - only valid with GET request | false |
| auth | auth option sent as URI Query | "" |
| h | host | "localhost" |
| p | port | "5683" |
| d | data to be sent in POST or PUT | "" |
| cf | content format | 50 (JSON format) |
| Flag | Description | Default value |
| ---- | -------------------------------------------- | ---------------- |
| o | observe option - only valid with GET request | false |
| a | auth option sent as URI Query | "" |
| H | host | "localhost" |
| p | port | "5683" |
| d | data to be sent in POST or PUT | "" |
| cf | content format | 50 (JSON format) |

The default values are as set in the [.env](.env) file. Modify them as required.

## Examples:

```bash
coap-cli get channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -o
coap-cli get channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic --auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -o
```

```bash
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world"
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -a 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world"
```

```bash
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world" -h 0.0.0.0 -p 1234
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic --auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world" -H 0.0.0.0 -p 1234
```
190 changes: 108 additions & 82 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -1,125 +1,150 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package main

import (
"context"
"errors"
"flag"
"fmt"
"log"
"os"
"os/signal"
"strings"
"syscall"

cli "github.com/mainflux/coap-cli"
coap "github.com/mainflux/coap-cli/coap"
"github.com/plgd-dev/go-coap/v2/message"
coapmsg "github.com/plgd-dev/go-coap/v2/message"
"github.com/plgd-dev/go-coap/v2/message/codes"
"github.com/plgd-dev/go-coap/v2/udp/message/pool"
)

const (
get = "GET"
put = "PUT"
post = "POST"
delete = "DELETE"
coapmsg "github.com/plgd-dev/go-coap/v3/message"
"github.com/plgd-dev/go-coap/v3/message/codes"
"github.com/plgd-dev/go-coap/v3/message/pool"
"github.com/spf13/cobra"
)

const (
helpCmd = `Use "coap-cli --help" for help.`
helpMsg = `
Usage: coap-cli <method> <URL> [options]
mathod: get, put, post or delete
-o observe option - only valid with GET request (default: false)
-auth auth option sent as URI Query (default: "")
-h host (default: "localhost")
-p port (default: "5683")
-d data to be sent in POST or PUT (default: "")
-cf content format (default: 50 - JSON format))
Examples:
coap-cli get channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -o
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world"
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world" -h 0.0.0.0 -p 1234
`
var (
host string
port string
contentFormat int
auth string
observe bool
data string
)

func parseCode(code string) (codes.Code, error) {
switch code {
case get:
return codes.GET, nil
case put:
return codes.PUT, nil
case post:
return codes.POST, nil
case delete:
return codes.DELETE, nil
}
return 0, errors.New("Message can be GET, POST, PUT or DELETE")
}

func printMsg(m *pool.Message) {
if m != nil {
log.Printf("\nMESSAGE:\n %v", m)
}
}

func main() {
if len(os.Args) < 2 {
log.Fatal(helpCmd)
config, err := cli.LoadConfig()
if err != nil {
log.Fatalf("Error loading config: %v", err)
}
help := strings.ToLower(os.Args[1])
if help == "-h" || help == "--help" {
log.Println(helpMsg)
os.Exit(0)

var rootCmd = &cobra.Command{
Use: "coap-cli <method> <URL> [options]",
Short: "CLI for CoAP",
}

code, err := parseCode(strings.ToUpper(os.Args[1]))
if err != nil {
log.Fatalf("Can't read request code: %s\n%s", err, helpCmd)
var getCmd = &cobra.Command{
Use: "get [url]",
Short: "Perform a GET request on a COAP resource",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Println("Error: URL argument is required")
cmd.Help()
return
}
executeRequest(codes.GET, args)
},
}
getCmd.Flags().BoolVarP(&observe, "observe", "o", config.Observe, "Observe resource")
getCmd.Example = `coap-cli get channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -a 1e1017e6-dee7-45b4-8a13-00e6afeb66eb \n
coap-cli get channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic --auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -o `

if len(os.Args) < 3 {
log.Fatalf("CoAP URL must not be empty.\n%s", helpCmd)
var putCmd = &cobra.Command{
Use: "put [url]",
Short: "Perform a PUT request on a COAP resource",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Println("Error: URL argument is required")
cmd.Help()
return
}
executeRequest(codes.PUT, args)
},
}
path := os.Args[2]
if strings.HasPrefix(path, "-") {
log.Fatalf("Please enter a valid CoAP URL.\n%s", helpCmd)
putCmd.Flags().StringVarP(&data, "data", "d", "", "Data")

var postCmd = &cobra.Command{
Use: "post [url]",
Short: "Perform a POST request on a COAP resource",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Println("Error: URL argument is required")
cmd.Help()
return
}
executeRequest(codes.POST, args)
},
}
postCmd.Flags().StringVarP(&data, "data", "d", "", "Data")
postCmd.Example = "coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic --auth 1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d \"hello world\""

os.Args = os.Args[2:]
o := flag.Bool("o", false, "Observe")
h := flag.String("h", "localhost", "Host")
p := flag.String("p", "5683", "Port")
// Default type is JSON.
cf := flag.Int("cf", 50, "Content format")
d := flag.String("d", "", "Message data")
a := flag.String("auth", "", "Auth token")
flag.Parse()

client, err := coap.New(*h + ":" + *p)
if err != nil {
log.Fatal("Error creating client: ", err)
var deleteCmd = &cobra.Command{
Use: "delete [url]",
Short: "Perform a DELETE request on a COAP resource",
Run: func(cmd *cobra.Command, args []string) {
if len(args) < 1 {
cmd.Println("Error: URL argument is required")
cmd.Help()
return
}
executeRequest(codes.DELETE, args)
},
}
var opts coapmsg.Options
if a != nil {
opts = append(opts, coapmsg.Option{ID: coapmsg.URIQuery, Value: []byte(fmt.Sprintf("auth=%s", *a))})
deleteCmd.Flags().StringVarP(&data, "data", "d", "", "Data")

rootCmd.AddCommand(getCmd, putCmd, postCmd, deleteCmd)
rootCmd.PersistentFlags().StringVarP(&host, "host", "H", config.Host, "Host")
rootCmd.PersistentFlags().StringVarP(&port, "port", "p", config.Port, "Port")
rootCmd.PersistentFlags().StringVarP(&auth, "auth", "a", config.Auth, "Auth")
rootCmd.PersistentFlags().IntVarP(&contentFormat, "content-format", "c", config.ContentFormat, "Content format")

if err := rootCmd.Execute(); err != nil {
log.Fatalf("Error executing command: %v", err)
}

if o == nil || (!*o) {
pld := strings.NewReader(*d)
}

res, err := client.Send(path, code, message.MediaType(*cf), pld, opts...)
func executeRequest(code codes.Code, args []string) {
client, err := coap.New(host + ":" + port)
if err != nil {
log.Fatalf("Error coap creating client: %v", err)
}
var opts coapmsg.Options
if auth != "" {
opts = append(opts, coapmsg.Option{ID: coapmsg.URIQuery, Value: []byte("auth=" + auth)})
}
if !observe {
if code != codes.GET {
pld := strings.NewReader(data)
res, err := client.Send(args[0], code, coapmsg.MediaType(contentFormat), pld, opts...)
if err != nil {
log.Fatalf("Error sending message: %v", err)
}
printMsg(res)
return
}
res, err := client.Send(args[0], code, coapmsg.MediaType(contentFormat), nil, opts...)
if err != nil {
log.Fatal("Error sending message: ", err)
log.Fatalf("Error sending message: %v", err)
}
printMsg(res)
return

}
if code != codes.GET {
log.Fatal("Only GET requests accept observe option.")
}
obs, err := client.Receive(path, opts...)
obs, err := client.Receive(args[0], opts...)
if err != nil {
log.Fatal("Error observing resource: ", err)
}
Expand All @@ -133,4 +158,5 @@ func main() {
err = <-errs
obs.Cancel(context.Background())
log.Fatal("Observation terminated: ", err)
return
}
22 changes: 15 additions & 7 deletions coap/client.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// Copyright (c) Abstract Machines
// SPDX-License-Identifier: Apache-2.0

package coap

import (
Expand All @@ -8,16 +11,21 @@ import (
"log"
"time"

"github.com/plgd-dev/go-coap/v2/message"
"github.com/plgd-dev/go-coap/v2/message/codes"
"github.com/plgd-dev/go-coap/v2/udp"
"github.com/plgd-dev/go-coap/v2/udp/client"
"github.com/plgd-dev/go-coap/v2/udp/message/pool"
"github.com/plgd-dev/go-coap/v3/message"
"github.com/plgd-dev/go-coap/v3/message/codes"
"github.com/plgd-dev/go-coap/v3/message/pool"
"github.com/plgd-dev/go-coap/v3/udp"
"github.com/plgd-dev/go-coap/v3/udp/client"
)

// Client represents CoAP client.
type Client struct {
conn *client.ClientConn
conn *client.Conn
}

type Observation interface {
Cancel(ctx context.Context, opts ...message.Option) error
Canceled() bool
}

// New returns new CoAP client connecting it to the server.
Expand Down Expand Up @@ -49,7 +57,7 @@ func (c Client) Send(path string, msgCode codes.Code, cf message.MediaType, payl
}

// Receive receives a message.
func (c Client) Receive(path string, opts ...message.Option) (*client.Observation, error) {
func (c Client) Receive(path string, opts ...message.Option) (Observation, error) {
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()

Expand Down
26 changes: 26 additions & 0 deletions configs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package coapcli

import (
"github.com/caarlos0/env/v10"
"github.com/joho/godotenv"
)

type Config struct {
Host string `env:"COAP_CLI_HOST"`
Port string `env:"COAP_CLI_PORT"`
ContentFormat int `env:"COAP_CLI_CONTENT_FORMAT"`
Auth string `env:"COAP_CLI_AUTH"`
Observe bool `env:"COAP_CLI_OBSERVE"`
}

func LoadConfig() (Config, error) {
c := Config{}
err := godotenv.Load()
if err != nil {
panic(err)
}
if err := env.Parse(&c); err != nil {
return Config{}, err
}
return c, nil
}
Loading

0 comments on commit bb2d8c1

Please sign in to comment.