Skip to content

Commit 2e65f08

Browse files
authored
Merge pull request #2 from mainflux/refactor
NOISSUE - Refactor CoAP CLI tool
2 parents 43f8edd + b7841ed commit 2e65f08

File tree

757 files changed

+213601
-1285
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

757 files changed

+213601
-1285
lines changed

README.md

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,26 @@ Simple CoAP cli client written in Go.
33

44

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

10-
| Flag | Description | Default value |
11-
|-------|--------------------------------|----------------------------------------|
12-
| ACK | Acknowledgement | false |
13-
| C | Confirmable | false |
14-
| NC | Non-Confirmable | false |
15-
| O | Observe | false |
16-
| d | Data to be sent in POST or PUT | "" |
17-
| id | Message ID | 0 |
18-
| token | Token | Byte array of empty string: [49 50 51] |
10+
| Flag | Description | Default value |
11+
| ---- | ---------------------------------------------- | ------------- |
12+
| o | Observe option - only valid with Get request | false |
13+
| auth | Auth option sent as URI Query | "" |
14+
| h | Host | "localhost" |
15+
| p | port | "5683" |
16+
| d | Data to be sent in POST or PUT | "" |
17+
| cf | Content format | 50 - JSON |
1918
# Examples:
2019

2120
```bash
22-
coap-cli get coap://localhost/channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic\?authorization=1e1017e6-dee7-45b4-8a13-00e6afeb66eb -O
21+
coap-cli get channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth=1e1017e6-dee7-45b4-8a13-00e6afeb66eb -o
2322
```
2423
```bash
25-
coap-cli post coap://localhost/channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic\?authorization=1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world"
24+
coap-cli post channels/0bb5ba61-a66e-4972-bab6-26f19962678f/messages/subtopic -auth=1e1017e6-dee7-45b4-8a13-00e6afeb66eb -d "hello world"
25+
```
26+
```bash
27+
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
2628
```

cmd/main.go

Lines changed: 49 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,21 @@
11
package main
22

33
import (
4+
"context"
45
"errors"
56
"flag"
7+
"fmt"
68
"log"
7-
"net/url"
89
"os"
10+
"os/signal"
911
"strings"
12+
"syscall"
1013

1114
coap "github.com/mainflux/coap-cli/coap"
12-
13-
gocoap "github.com/dustin/go-coap"
15+
"github.com/plgd-dev/go-coap/v2/message"
16+
coapmsg "github.com/plgd-dev/go-coap/v2/message"
17+
"github.com/plgd-dev/go-coap/v2/message/codes"
18+
"github.com/plgd-dev/go-coap/v2/udp/message/pool"
1419
)
1520

1621
const (
@@ -20,48 +25,23 @@ const (
2025
delete = "DELETE"
2126
)
2227

23-
func parseCode(code string) (gocoap.COAPCode, error) {
28+
func parseCode(code string) (codes.Code, error) {
2429
switch code {
2530
case get:
26-
return gocoap.GET, nil
31+
return codes.GET, nil
2732
case put:
28-
return gocoap.PUT, nil
33+
return codes.PUT, nil
2934
case post:
30-
return gocoap.POST, nil
35+
return codes.POST, nil
3136
case delete:
32-
return gocoap.DELETE, nil
37+
return codes.DELETE, nil
3338
}
3439
return 0, errors.New("Message can be GET, POST, PUT or DELETE")
3540
}
3641

37-
func checkType(c, n, a, r *bool) (gocoap.COAPType, error) {
38-
arr := []bool{*c, *n, *a, *r}
39-
var counter int
40-
for _, v := range arr {
41-
if v {
42-
counter++
43-
}
44-
}
45-
if counter > 1 {
46-
return 0, errors.New("invalid message type")
47-
}
48-
switch {
49-
case *c:
50-
return gocoap.Confirmable, nil
51-
case *n:
52-
return gocoap.NonConfirmable, nil
53-
case *a:
54-
return gocoap.Acknowledgement, nil
55-
case *r:
56-
return gocoap.Reset, nil
57-
}
58-
return gocoap.Confirmable, nil
59-
}
60-
61-
func printMsg(m *gocoap.Message) {
42+
func printMsg(m *pool.Message) {
6243
if m != nil {
63-
log.Printf("\nMESSAGE:\nType: %d\nCode: %s\nMessageID: %d\nToken: %s\nPayload: %s\n",
64-
m.Type, m.Code.String(), m.MessageID, m.Token, m.Payload)
44+
log.Printf("\nMESSAGE:\n %v", m)
6545
}
6646
}
6747

@@ -71,85 +51,56 @@ func main() {
7151
}
7252
code, err := parseCode(strings.ToUpper(os.Args[1]))
7353
if err != nil {
74-
log.Fatal("ERROR: ", err)
54+
log.Fatal("error: ", err)
7555
}
7656
if len(os.Args) < 3 {
7757
log.Fatal("Please enter valid CoAP URL")
7858
}
79-
addr := os.Args[2]
59+
path := os.Args[2]
8060
os.Args = os.Args[2:]
8161

82-
c := flag.Bool("C", false, "Confirmable")
83-
n := flag.Bool("NC", false, "Non-confirmable")
84-
a := flag.Bool("ACK", false, "Acknowledgement")
85-
r := flag.Bool("RST", false, "Reset")
86-
o := flag.Bool("O", false, "Observe")
62+
o := flag.Bool("o", false, "Observe")
63+
h := flag.String("h", "localhost", "Host")
64+
p := flag.String("p", "5683", "Port")
8765
// Default type is JSON.
88-
cf := flag.Int("CF", 50, "Content format")
66+
cf := flag.Int("q", 50, "Content format")
8967
d := flag.String("d", "", "Message data")
90-
id := flag.Uint("id", 0, "Message ID")
91-
token := flag.String("token", "", "Message data")
68+
a := flag.String("auth", "", "Auth token")
9269

9370
flag.Parse()
9471

95-
t, err := checkType(c, n, a, r)
72+
fmt.Println(*h + ":" + *p)
73+
client, err := coap.New(*h + ":" + *p)
9674
if err != nil {
97-
log.Fatal("ERR TYPE: ", err)
75+
log.Fatal("Error creating client: ", err)
9876
}
99-
address, err := url.Parse(addr)
100-
if err != nil {
101-
log.Fatal("ERR PARSING ADDR:", err)
102-
}
103-
client, err := coap.New(address)
104-
if err != nil {
105-
log.Fatal("ERROR CREATING CLIENT: ", err)
77+
var opts coapmsg.Options
78+
if a != nil {
79+
opts = append(opts, coapmsg.Option{ID: coapmsg.URIQuery, Value: []byte(fmt.Sprintf("auth=%s", *a))})
10680
}
10781

108-
opts := coap.ParseOptions(address)
109-
if *o {
110-
opts = append(opts, coap.Option{
111-
ID: gocoap.Observe,
112-
Value: 0,
113-
})
114-
}
115-
if *cf != 0 {
116-
opts = append(opts, coap.Option{
117-
ID: gocoap.ContentFormat,
118-
Value: *cf,
119-
})
120-
}
82+
if o == nil {
83+
pld := strings.NewReader(*d)
12184

122-
res, err := client.Send(t, code, uint16(*id), []byte(*token), []byte(*d), opts)
123-
if err != nil {
124-
log.Fatal("ERROR: ", err)
125-
}
126-
printMsg(res)
127-
if res == nil {
128-
os.Exit(0)
129-
}
130-
switch res.Code {
131-
case gocoap.Forbidden, gocoap.BadRequest, gocoap.InternalServerError, gocoap.NotFound:
132-
log.Fatalf("Response code: %s", res.Code)
133-
}
134-
if *o {
135-
if code != gocoap.GET {
136-
log.Fatalln("Can observe non GET requests.")
137-
}
138-
msgs := make(chan *gocoap.Message)
139-
go func() {
140-
for {
141-
msg, err := client.Receive()
142-
if err != nil {
143-
log.Fatal("ERROR RECEIVING: ", err)
144-
}
145-
msgs <- msg
146-
}
147-
}()
148-
for {
149-
select {
150-
case m := <-msgs:
151-
printMsg(m)
152-
}
85+
res, err := client.Send(path, code, message.MediaType(*cf), pld, opts...)
86+
if err != nil {
87+
log.Fatal("Error sending message: ", err)
15388
}
89+
printMsg(res)
90+
return
15491
}
92+
obs, err := client.Receive(path, opts...)
93+
if err != nil {
94+
log.Fatal("Error observing resource: ", err)
95+
}
96+
errs := make(chan error, 2)
97+
go func() {
98+
c := make(chan os.Signal)
99+
signal.Notify(c, syscall.SIGINT)
100+
errs <- fmt.Errorf("%s", <-c)
101+
}()
102+
103+
err = <-errs
104+
obs.Cancel(context.Background())
105+
log.Fatal("Observation terminated: ", err)
155106
}

coap/client.go

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,67 @@
11
package coap
22

33
import (
4-
"net/url"
4+
"context"
5+
"errors"
6+
"fmt"
7+
"io"
8+
"log"
9+
"time"
510

6-
gocoap "github.com/dustin/go-coap"
11+
"github.com/plgd-dev/go-coap/v2/message"
12+
"github.com/plgd-dev/go-coap/v2/message/codes"
13+
"github.com/plgd-dev/go-coap/v2/udp"
14+
"github.com/plgd-dev/go-coap/v2/udp/client"
15+
"github.com/plgd-dev/go-coap/v2/udp/message/pool"
716
)
817

918
// Client represents CoAP client.
1019
type Client struct {
11-
conn *conn
20+
conn *client.ClientConn
1221
}
1322

1423
// New returns new CoAP client connecting it to the server.
15-
func New(addr *url.URL) (Client, error) {
16-
address, err := parseAddr(addr)
24+
func New(addr string) (Client, error) {
25+
c, err := udp.Dial(addr)
1726
if err != nil {
18-
return Client{}, err
19-
}
20-
c, err := dial(address)
21-
if err != nil {
22-
return Client{}, err
27+
log.Fatalf("Error dialing: %v", err)
2328
}
29+
2430
return Client{conn: c}, nil
2531
}
2632

2733
// Send send a message.
28-
func (c Client) Send(msgType gocoap.COAPType, msgCode gocoap.COAPCode, msgID uint16, token, payload []byte, opts []Option) (*gocoap.Message, error) {
29-
msg := gocoap.Message{
30-
Type: msgType,
31-
Code: msgCode,
32-
MessageID: msgID,
33-
Token: token,
34-
Payload: payload,
35-
}
34+
func (c Client) Send(path string, msgCode codes.Code, cf message.MediaType, payload io.ReadSeeker, opts ...message.Option) (*pool.Message, error) {
35+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
36+
defer cancel()
3637

37-
for _, o := range opts {
38-
msg.SetOption(o.ID, o.Value)
38+
switch msgCode {
39+
case codes.GET:
40+
return c.conn.Get(ctx, path, opts...)
41+
case codes.POST:
42+
return c.conn.Post(ctx, path, cf, payload, opts...)
43+
case codes.PUT:
44+
return c.conn.Put(ctx, path, cf, payload, opts...)
45+
case codes.DELETE:
46+
return c.conn.Delete(ctx, path, opts...)
3947
}
40-
return c.conn.send(msg)
48+
return nil, errors.New("Invalid message code")
4149
}
4250

4351
// Receive receives a message.
44-
func (c Client) Receive() (*gocoap.Message, error) {
45-
return c.conn.receive()
52+
func (c Client) Receive(path string, opts ...message.Option) (*client.Observation, error) {
53+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
54+
defer cancel()
55+
56+
return c.conn.Observe(ctx, path, func(res *pool.Message) {
57+
fmt.Printf("\nRECEIVED OBSERVE: %v\n", res)
58+
body, err := res.ReadBody()
59+
if err != nil {
60+
fmt.Println("Error reading message body: ", err)
61+
return
62+
}
63+
if len(body) > 0 {
64+
fmt.Println("Payload: ", string(body))
65+
}
66+
}, opts...)
4667
}

coap/options.go

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)