You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by cc...@apache.org on 2017/08/07 20:14:24 UTC

[mynewt-newtmgr] 02/06: newtmgr - "res" command

This is an automated email from the ASF dual-hosted git repository.

ccollins pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-newtmgr.git

commit 566e56c0243ba504918c0156b648c13f841be726
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Fri Aug 4 17:32:10 2017 -0700

    newtmgr - "res" command
    
    Get or set a CoAP resource.
---
 newtmgr/bll/bll_oic_sesn.go    |  36 ++++++++++++++++++++++-
 newtmgr/cli/commands.go        |   2 +-
 newtmgr/cli/res.go             |  40 ++++++++++++++++++++++----
 nmxact/bledefs/bledefs.go      |  16 +++++++----
 nmxact/example/ble_adv/ble_adv | Bin 14030132 -> 14030132 bytes
 nmxact/nmble/ble_sesn.go       |  29 ++++++++++++++++---
 nmxact/nmble/ble_util.go       |  16 ++++++++++-
 nmxact/nmble/temp.go           |   7 +++--
 nmxact/oic/oic.go              |  64 +++++++++++++++++++++++++++++++++++------
 nmxact/oic/resmgr.go           |  17 ++++-------
 nmxact/sesn/sesn_util.go       |  20 ++++++++-----
 nmxact/xact/res.go             |   4 +--
 12 files changed, 200 insertions(+), 51 deletions(-)

diff --git a/newtmgr/bll/bll_oic_sesn.go b/newtmgr/bll/bll_oic_sesn.go
index 2cb141d..e813967 100644
--- a/newtmgr/bll/bll_oic_sesn.go
+++ b/newtmgr/bll/bll_oic_sesn.go
@@ -405,5 +405,39 @@ func (bls *BllOicSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 func (bls *BllOicSesn) PutResourceOnce(resType sesn.ResourceType,
 	uri string, value []byte, opt sesn.TxOptions) (coap.COAPCode, error) {
 
-	return 0, fmt.Errorf("BllOicSesn.PutResourceOnce() unsupported")
+	chr, err := bls.resReqChr(resType)
+	if err != nil {
+		return 0, err
+	}
+
+	token := nmxutil.NextToken()
+
+	ol, err := bls.d.AddOicListener(token)
+	if err != nil {
+		return 0, err
+	}
+	defer bls.d.RemoveOicListener(token)
+
+	req, err := oic.EncodePut(true, uri, token, value)
+	if err != nil {
+		return 0, err
+	}
+
+	// Send request.
+	if err := bls.cln.WriteCharacteristic(chr, req, true); err != nil {
+		return 0, err
+	}
+
+	// Now wait for CoAP response.
+	for {
+		select {
+		case err := <-ol.ErrChan:
+			return 0, err
+		case rsp := <-ol.RspChan:
+			return rsp.Code(), nil
+		case <-ol.AfterTimeout(opt.Timeout):
+			msg := fmt.Sprintf("CoAP timeout; uri=%s", uri)
+			return 0, nmxutil.NewRspTimeoutError(msg)
+		}
+	}
 }
diff --git a/newtmgr/cli/commands.go b/newtmgr/cli/commands.go
index 41a9120..cde0416 100644
--- a/newtmgr/cli/commands.go
+++ b/newtmgr/cli/commands.go
@@ -81,7 +81,7 @@ func Commands() *cobra.Command {
 	nmCmd.AddCommand(configCmd())
 	nmCmd.AddCommand(connProfileCmd())
 	nmCmd.AddCommand(echoCmd())
-	nmCmd.AddCommand(getResCmd())
+	nmCmd.AddCommand(resCmd())
 
 	return nmCmd
 }
diff --git a/newtmgr/cli/res.go b/newtmgr/cli/res.go
index 5192645..560b30c 100644
--- a/newtmgr/cli/res.go
+++ b/newtmgr/cli/res.go
@@ -20,13 +20,16 @@
 package cli
 
 import (
+	"encoding/hex"
 	"fmt"
 	"strings"
 
+	"github.com/runtimeco/go-coap"
 	"github.com/spf13/cobra"
 
 	"mynewt.apache.org/newt/util"
 	"mynewt.apache.org/newtmgr/newtmgr/nmutil"
+	"mynewt.apache.org/newtmgr/nmxact/nmxutil"
 	"mynewt.apache.org/newtmgr/nmxact/sesn"
 	"mynewt.apache.org/newtmgr/nmxact/xact"
 )
@@ -61,20 +64,44 @@ func resGetRunCmd(s sesn.Sesn, resType sesn.ResourceType, uri string) {
 
 	sres := res.(*xact.GetResResult)
 	if sres.Status() != 0 {
-		fmt.Printf("Error: %d\n", sres.Status())
+		fmt.Printf("Error: %s (%d)\n",
+			coap.COAPCode(sres.Status()), sres.Status())
+		return
+	}
+
+	var valstr string
+
+	m, err := nmxutil.DecodeCborMap(sres.Value)
+	if err != nil {
+		valstr = hex.Dump(sres.Value)
+	} else if len(m) == 0 {
+		valstr = "<empty>"
+	} else if len(m) == 1 {
+		for k, v := range m {
+			valstr = fmt.Sprintf("%s=%+v", k, v)
+		}
 	} else {
-		fmt.Printf("%s: %+v\n", uri, sres.Value)
+		for k, v := range m {
+			valstr += fmt.Sprintf("\n    %s=%+v", k, v)
+		}
 	}
+
+	fmt.Printf("%s: %s\n", uri, valstr)
 }
 
 func resPutRunCmd(s sesn.Sesn, resType sesn.ResourceType, uri string,
 	value map[string]interface{}) {
 
+	b, err := nmxutil.EncodeCborMap(value)
+	if err != nil {
+		nmUsage(nil, util.ChildNewtError(err))
+	}
+
 	c := xact.NewPutResCmd()
 	c.SetTxOptions(nmutil.TxOptions())
 	c.Uri = uri
 	c.Typ = resType
-	c.Value = value
+	c.Value = b
 
 	res, err := c.Run(s)
 	if err != nil {
@@ -83,14 +110,15 @@ func resPutRunCmd(s sesn.Sesn, resType sesn.ResourceType, uri string,
 
 	sres := res.(*xact.PutResResult)
 	if sres.Status() != 0 {
-		fmt.Printf("Error: %d\n", sres.Status())
+		fmt.Printf("Error: %s (%d)\n",
+			coap.COAPCode(sres.Status()), sres.Status())
 	} else {
 		fmt.Printf("Done\n")
 	}
 }
 
 func resRunCmd(cmd *cobra.Command, args []string) {
-	if len(args) != 2 {
+	if len(args) < 2 {
 		nmUsage(cmd, nil)
 	}
 
@@ -121,7 +149,7 @@ func resRunCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
-func getResCmd() *cobra.Command {
+func resCmd() *cobra.Command {
 	resEx := "   newtmgr -c olimex res public mynewt.value.0\n"
 
 	resCmd := &cobra.Command{
diff --git a/nmxact/bledefs/bledefs.go b/nmxact/bledefs/bledefs.go
index d19d7e9..8a243ef 100644
--- a/nmxact/bledefs/bledefs.go
+++ b/nmxact/bledefs/bledefs.go
@@ -809,13 +809,17 @@ type BleChrId struct {
 	ChrUuid BleUuid
 }
 
+func (b *BleChrId) String() string {
+	return fmt.Sprintf("s=%s c=%s", b.SvcUuid.String(), b.ChrUuid.String())
+}
+
 type BleMgmtChrs struct {
-	NmpReqChr        *BleChrId
-	NmpRspChr        *BleChrId
-	ResPublicReqChr  *BleChrId
-	ResPublicRspChr  *BleChrId
-	ResUnauthReqChr  *BleChrId
-	ResUnauthRspChr  *BleChrId
+	NmpReqChr       *BleChrId
+	NmpRspChr       *BleChrId
+	ResPublicReqChr *BleChrId
+	ResPublicRspChr *BleChrId
+	ResUnauthReqChr *BleChrId
+	ResUnauthRspChr *BleChrId
 	ResSecureReqChr *BleChrId
 	ResSecureRspChr *BleChrId
 }
diff --git a/nmxact/example/ble_adv/ble_adv b/nmxact/example/ble_adv/ble_adv
index d57f915..d1fcdab 100755
Binary files a/nmxact/example/ble_adv/ble_adv and b/nmxact/example/ble_adv/ble_adv differ
diff --git a/nmxact/nmble/ble_sesn.go b/nmxact/nmble/ble_sesn.go
index 63e0d96..6d9c889 100644
--- a/nmxact/nmble/ble_sesn.go
+++ b/nmxact/nmble/ble_sesn.go
@@ -117,7 +117,7 @@ func (s *BleSesn) getChr(chrId *BleChrId) (*Characteristic, error) {
 	chr := s.conn.Profile().FindChrByUuid(*chrId)
 	if chr == nil {
 		return nil, fmt.Errorf("BLE peer doesn't support required "+
-			"characteristic: %s", *chrId)
+			"characteristic: %s", chrId.String())
 	}
 
 	return chr, nil
@@ -323,14 +323,14 @@ func (s *BleSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 		return 0, nil, err
 	}
 
-	chrId := ResChrIdLookup(s.mgmtChrs, resType)
+	chrId := ResChrReqIdLookup(s.mgmtChrs, resType)
 	chr, err := s.getChr(chrId)
 	if err != nil {
 		return 0, nil, err
 	}
 
 	txRaw := func(b []byte) error {
-		return s.conn.WriteChrNoRsp(chr, b, "oic")
+		return s.conn.WriteChrNoRsp(chr, b, "oic-get")
 	}
 
 	rsp, err := s.txvr.TxOic(txRaw, req, opt.Timeout)
@@ -344,5 +344,26 @@ func (s *BleSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 func (s *BleSesn) PutResourceOnce(resType sesn.ResourceType,
 	uri string, value []byte, opt sesn.TxOptions) (coap.COAPCode, error) {
 
-	return 0, fmt.Errorf("SerialPlainSesn.PutResourceOnce() unsupported")
+	token := nmxutil.NextToken()
+	req, err := oic.CreatePut(true, uri, token, value)
+	if err != nil {
+		return 0, err
+	}
+
+	chrId := ResChrReqIdLookup(s.mgmtChrs, resType)
+	chr, err := s.getChr(chrId)
+	if err != nil {
+		return 0, err
+	}
+
+	txRaw := func(b []byte) error {
+		return s.conn.WriteChrNoRsp(chr, b, "oic-put")
+	}
+
+	rsp, err := s.txvr.TxOic(txRaw, req, opt.Timeout)
+	if err != nil {
+		return 0, err
+	}
+
+	return rsp.Code(), nil
 }
diff --git a/nmxact/nmble/ble_util.go b/nmxact/nmble/ble_util.go
index 7d5b316..0f530e3 100644
--- a/nmxact/nmble/ble_util.go
+++ b/nmxact/nmble/ble_util.go
@@ -713,7 +713,9 @@ func GenCoapService(x *BleXport, svcUuid BleUuid, reqChrUuid BleUuid,
 	return svc, nil
 }
 
-func ResChrIdLookup(mgmtChrs BleMgmtChrs, resType sesn.ResourceType) *BleChrId {
+func ResChrReqIdLookup(mgmtChrs BleMgmtChrs,
+	resType sesn.ResourceType) *BleChrId {
+
 	m := map[sesn.ResourceType]*BleChrId{
 		sesn.RES_TYPE_PUBLIC: mgmtChrs.ResPublicReqChr,
 		sesn.RES_TYPE_UNAUTH: mgmtChrs.ResUnauthReqChr,
@@ -723,6 +725,18 @@ func ResChrIdLookup(mgmtChrs BleMgmtChrs, resType sesn.ResourceType) *BleChrId {
 	return m[resType]
 }
 
+func ResChrRspIdLookup(mgmtChrs BleMgmtChrs,
+	resType sesn.ResourceType) *BleChrId {
+
+	m := map[sesn.ResourceType]*BleChrId{
+		sesn.RES_TYPE_PUBLIC: mgmtChrs.ResPublicRspChr,
+		sesn.RES_TYPE_UNAUTH: mgmtChrs.ResUnauthRspChr,
+		sesn.RES_TYPE_SECURE: mgmtChrs.ResSecureRspChr,
+	}
+
+	return m[resType]
+}
+
 func BuildMgmtChrs(mgmtProto sesn.MgmtProto) (BleMgmtChrs, error) {
 	mgmtChrs := BleMgmtChrs{}
 
diff --git a/nmxact/nmble/temp.go b/nmxact/nmble/temp.go
index 2c19fb5..b7371cf 100644
--- a/nmxact/nmble/temp.go
+++ b/nmxact/nmble/temp.go
@@ -16,8 +16,11 @@ func GwService(x *BleXport) (BleSvc, error) {
 	resources := []oic.Resource{
 		oic.NewFixedResource(
 			"mynewt.yourmom",
-			map[string]interface{}{"yourmom": "fat"},
-			func(val map[string]interface{}) coap.COAPCode {
+			map[string]interface{}{
+				"yourmom":     "fat",
+				"yourmomsmom": "hella fat",
+			},
+			func(uri string, val map[string]interface{}) coap.COAPCode {
 				return coap.Changed
 			},
 		)}
diff --git a/nmxact/oic/oic.go b/nmxact/oic/oic.go
index f5052ed..285600a 100644
--- a/nmxact/oic/oic.go
+++ b/nmxact/oic/oic.go
@@ -38,6 +38,22 @@ func NextMessageId() uint16 {
 	return id
 }
 
+func validateToken(t []byte) error {
+	if len(t) > 8 {
+		return fmt.Errorf("Invalid token; len=%d, must be <= 8", len(t))
+	}
+
+	return nil
+}
+
+func buildMessage(isTcp bool, p coap.MessageParams) coap.Message {
+	if isTcp {
+		return coap.NewTcpMessage(p)
+	} else {
+		return coap.NewDgramMessage(p)
+	}
+}
+
 func Encode(m coap.Message) ([]byte, error) {
 	b, err := m.MarshalBinary()
 	if err != nil {
@@ -48,9 +64,8 @@ func Encode(m coap.Message) ([]byte, error) {
 }
 
 func CreateGet(isTcp bool, resUri string, token []byte) (coap.Message, error) {
-	if len(token) > 8 {
-		return nil,
-			fmt.Errorf("Invalid token; len=%d, must be < 8", len(token))
+	if err := validateToken(token); err != nil {
+		return nil, err
 	}
 
 	p := coap.MessageParams{
@@ -59,12 +74,7 @@ func CreateGet(isTcp bool, resUri string, token []byte) (coap.Message, error) {
 		Token: token,
 	}
 
-	var m coap.Message
-	if isTcp {
-		m = coap.NewTcpMessage(p)
-	} else {
-		m = coap.NewDgramMessage(p)
-	}
+	m := buildMessage(isTcp, p)
 	m.SetPathString(resUri)
 
 	return m, nil
@@ -83,3 +93,39 @@ func EncodeGet(isTcp bool, resUri string, token []byte) ([]byte, error) {
 
 	return b, nil
 }
+
+func CreatePut(isTcp bool, resUri string, token []byte,
+	val []byte) (coap.Message, error) {
+
+	if err := validateToken(token); err != nil {
+		return nil, err
+	}
+
+	p := coap.MessageParams{
+		Type:    coap.Confirmable,
+		Code:    coap.PUT,
+		Token:   token,
+		Payload: val,
+	}
+
+	m := buildMessage(isTcp, p)
+	m.SetPathString(resUri)
+
+	return m, nil
+}
+
+func EncodePut(isTcp bool, resUri string, token []byte, val []byte) (
+	[]byte, error) {
+
+	m, err := CreatePut(isTcp, resUri, token, val)
+	if err != nil {
+		return nil, err
+	}
+
+	b, err := Encode(m)
+	if err != nil {
+		return nil, err
+	}
+
+	return b, nil
+}
diff --git a/nmxact/oic/resmgr.go b/nmxact/oic/resmgr.go
index c6d9e6d..f715f13 100644
--- a/nmxact/oic/resmgr.go
+++ b/nmxact/oic/resmgr.go
@@ -38,12 +38,7 @@ func (rm *ResMgr) Add(r Resource) error {
 }
 
 func (rm *ResMgr) Access(m coap.Message) (coap.COAPCode, []byte) {
-	paths := m.Path()
-	if len(paths) == 0 {
-		log.Debugf("Incoming CoAP message does not specify a URI path")
-		return coap.NotFound, nil
-	}
-	path := paths[0]
+	path := m.PathString()
 
 	r, ok := rm.uriResMap[path]
 	if !ok {
@@ -73,7 +68,8 @@ func (rm *ResMgr) Access(m coap.Message) (coap.COAPCode, []byte) {
 	}
 }
 
-type FixedResourceWriteFn func(val map[string]interface{}) coap.COAPCode
+type FixedResourceWriteFn func(uri string,
+	val map[string]interface{}) coap.COAPCode
 
 func NewFixedResource(uri string, val map[string]interface{},
 	writeCb FixedResourceWriteFn) Resource {
@@ -95,11 +91,8 @@ func NewFixedResource(uri string, val map[string]interface{},
 				return coap.BadRequest
 			}
 
-			code := writeCb(m)
-			if code == coap.Created ||
-				code == coap.Deleted ||
-				code == coap.Changed {
-
+			code := writeCb(uri, m)
+			if code == coap.Created || code == coap.Changed {
 				val = m
 			}
 			return code
diff --git a/nmxact/sesn/sesn_util.go b/nmxact/sesn/sesn_util.go
index a66aed6..b38634c 100644
--- a/nmxact/sesn/sesn_util.go
+++ b/nmxact/sesn/sesn_util.go
@@ -57,16 +57,11 @@ func GetResource(s Sesn, resType ResourceType, uri string, o TxOptions) (
 }
 
 func PutResource(s Sesn, resType ResourceType, uri string,
-	value map[string]interface{}, o TxOptions) (coap.COAPCode, error) {
-
-	b, err := nmxutil.EncodeCborMap(value)
-	if err != nil {
-		return 0, err
-	}
+	value []byte, o TxOptions) (coap.COAPCode, error) {
 
 	retries := o.Tries - 1
 	for i := 0; ; i++ {
-		code, err := s.PutResourceOnce(resType, uri, b, o)
+		code, err := s.PutResourceOnce(resType, uri, value, o)
 		if err == nil {
 			return code, nil
 		}
@@ -76,3 +71,14 @@ func PutResource(s Sesn, resType ResourceType, uri string,
 		}
 	}
 }
+
+func PutCborResource(s Sesn, resType ResourceType, uri string,
+	value map[string]interface{}, o TxOptions) (coap.COAPCode, error) {
+
+	b, err := nmxutil.EncodeCborMap(value)
+	if err != nil {
+		return 0, err
+	}
+
+	return PutResource(s, resType, uri, b, o)
+}
diff --git a/nmxact/xact/res.go b/nmxact/xact/res.go
index 6cfa47e..4c0ffd5 100644
--- a/nmxact/xact/res.go
+++ b/nmxact/xact/res.go
@@ -70,7 +70,7 @@ type PutResCmd struct {
 	CmdBase
 	Uri   string
 	Typ   sesn.ResourceType
-	Value map[string]interface{}
+	Value []byte
 }
 
 func NewPutResCmd() *PutResCmd {
@@ -88,7 +88,7 @@ func newPutResResult() *PutResResult {
 }
 
 func (r *PutResResult) Status() int {
-	if r.Code == coap.Content {
+	if r.Code == coap.Created || r.Code == coap.Changed {
 		return 0
 	} else {
 		return int(r.Code)

-- 
To stop receiving notification emails like this one, please contact
"commits@mynewt.apache.org" <co...@mynewt.apache.org>.