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/04 21:41:10 UTC

[mynewt-newtmgr] 01/05: newtmgr - get / put CoAP resources.

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 8393b298f268b48316d8bd99f4c65088b82dfaf3
Author: Christopher Collins <cc...@apache.org>
AuthorDate: Fri Aug 4 14:14:16 2017 -0700

    newtmgr - get / put CoAP resources.
---
 newtmgr/bll/bll_oic_sesn.go          |  40 ++++++++------
 newtmgr/bll/bll_plain_sesn.go        |   6 +++
 newtmgr/cli/{getres.go => res.go}    |  98 +++++++++++++++++++++++++++--------
 nmxact/bledefs/bledefs.go            |  14 ++---
 nmxact/example/ble_adv/ble_adv       | Bin 14025652 -> 13981316 bytes
 nmxact/nmble/ble_sesn.go             |   6 +++
 nmxact/nmble/ble_util.go             |  22 ++++----
 nmxact/nmserial/serial_oic_sesn.go   |   7 +++
 nmxact/nmserial/serial_plain_sesn.go |   7 +++
 nmxact/nmxutil/nmxutil.go            |  10 ++++
 nmxact/sesn/sesn.go                  |   3 +-
 nmxact/sesn/sesn_util.go             |  21 ++++++++
 nmxact/udp/udp_oic_sesn.go           |   7 +++
 nmxact/udp/udp_plain_sesn.go         |   7 +++
 nmxact/xact/{getres.go => res.go}    |  40 ++++++++++++++
 15 files changed, 231 insertions(+), 57 deletions(-)

diff --git a/newtmgr/bll/bll_oic_sesn.go b/newtmgr/bll/bll_oic_sesn.go
index fc042f5..242d6f3 100644
--- a/newtmgr/bll/bll_oic_sesn.go
+++ b/newtmgr/bll/bll_oic_sesn.go
@@ -46,14 +46,14 @@ type BllOicSesn struct {
 	mtx    sync.Mutex
 	attMtu int
 
-	nmpReqChr     *ble.Characteristic
-	nmpRspChr     *ble.Characteristic
-	publicReqChr  *ble.Characteristic
-	publicRspChr  *ble.Characteristic
-	gwReqChr      *ble.Characteristic
-	gwRspChr      *ble.Characteristic
-	privateReqChr *ble.Characteristic
-	privateRspChr *ble.Characteristic
+	nmpReqChr    *ble.Characteristic
+	nmpRspChr    *ble.Characteristic
+	publicReqChr *ble.Characteristic
+	publicRspChr *ble.Characteristic
+	unauthReqChr *ble.Characteristic
+	unauthRspChr *ble.Characteristic
+	secureReqChr *ble.Characteristic
+	secureRspChr *ble.Characteristic
 }
 
 func NewBllOicSesn(cfg BllSesnCfg) *BllOicSesn {
@@ -133,9 +133,9 @@ func (bls *BllOicSesn) discoverAll() error {
 	ompReqChrUuid, _ := bledefs.ParseUuid(bledefs.OmpUnsecReqChrUuid)
 	ompRspChrUuid, _ := bledefs.ParseUuid(bledefs.OmpUnsecRspChrUuid)
 
-	gwSvcUuid, _ := bledefs.ParseUuid(bledefs.GwSvcUuid)
-	gwReqChrUuid, _ := bledefs.ParseUuid(bledefs.GwReqChrUuid)
-	gwRspChrUuid, _ := bledefs.ParseUuid(bledefs.GwRspChrUuid)
+	unauthSvcUuid, _ := bledefs.ParseUuid(bledefs.UnauthSvcUuid)
+	unauthReqChrUuid, _ := bledefs.ParseUuid(bledefs.UnauthReqChrUuid)
+	unauthRspChrUuid, _ := bledefs.ParseUuid(bledefs.UnauthRspChrUuid)
 
 	bls.nmpReqChr, err = findChr(p, ompSvcUuid, ompReqChrUuid)
 	if err != nil {
@@ -147,12 +147,12 @@ func (bls *BllOicSesn) discoverAll() error {
 		return err
 	}
 
-	bls.gwReqChr, err = findChr(p, gwSvcUuid, gwReqChrUuid)
+	bls.unauthReqChr, err = findChr(p, unauthSvcUuid, unauthReqChrUuid)
 	if err != nil {
 		return err
 	}
 
-	bls.gwRspChr, err = findChr(p, gwSvcUuid, gwRspChrUuid)
+	bls.unauthRspChr, err = findChr(p, unauthSvcUuid, unauthRspChrUuid)
 	if err != nil {
 		return err
 	}
@@ -175,8 +175,8 @@ func (bls *BllOicSesn) subscribe() error {
 		}
 	}
 
-	if bls.gwRspChr != nil {
-		if err := bls.cln.Subscribe(bls.gwRspChr, false,
+	if bls.unauthRspChr != nil {
+		if err := bls.cln.Subscribe(bls.unauthRspChr, false,
 			onNotify); err != nil {
 
 			return err
@@ -323,8 +323,8 @@ func (bls *BllOicSesn) resReqChr(resType sesn.ResourceType) (
 
 	m := map[sesn.ResourceType]*ble.Characteristic{
 		sesn.RES_TYPE_PUBLIC: bls.publicReqChr,
-		sesn.RES_TYPE_UNAUTH: bls.gwReqChr,
-		sesn.RES_TYPE_SECURE: bls.privateReqChr,
+		sesn.RES_TYPE_UNAUTH: bls.unauthReqChr,
+		sesn.RES_TYPE_SECURE: bls.secureReqChr,
 	}
 
 	chr := m[resType]
@@ -375,3 +375,9 @@ 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")
+}
diff --git a/newtmgr/bll/bll_plain_sesn.go b/newtmgr/bll/bll_plain_sesn.go
index 1f6dccc..8fa064d 100644
--- a/newtmgr/bll/bll_plain_sesn.go
+++ b/newtmgr/bll/bll_plain_sesn.go
@@ -257,3 +257,9 @@ func (bps *BllPlainSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 	return 0, nil,
 		fmt.Errorf("Resource API not supported by plain (non-OIC) session")
 }
+
+func (bps *BllPlainSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte, opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("BllPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/newtmgr/cli/getres.go b/newtmgr/cli/res.go
similarity index 52%
rename from newtmgr/cli/getres.go
rename to newtmgr/cli/res.go
index 049fe94..5192645 100644
--- a/newtmgr/cli/getres.go
+++ b/newtmgr/cli/res.go
@@ -21,6 +21,7 @@ package cli
 
 import (
 	"fmt"
+	"strings"
 
 	"github.com/spf13/cobra"
 
@@ -30,27 +31,28 @@ import (
 	"mynewt.apache.org/newtmgr/nmxact/xact"
 )
 
-func getResRunCmd(cmd *cobra.Command, args []string) {
-	if len(args) != 2 {
-		nmUsage(cmd, nil)
-	}
+func extractResKv(params []string) (map[string]interface{}, error) {
+	m := map[string]interface{}{}
 
-	rt, err := sesn.ParseResType(args[0])
-	if err != nil {
-		nmUsage(cmd, err)
-	}
+	for _, param := range params {
+		parts := strings.SplitN(param, "=", 2)
+		if len(parts) != 2 {
+			return nil, util.FmtNewtError("invalid resource specifier: %s",
+				param)
+		}
 
-	uri := args[1]
-
-	s, err := GetSesn()
-	if err != nil {
-		nmUsage(nil, err)
+		// XXX: For now, assume all values are strings.
+		m[parts[0]] = parts[1]
 	}
 
+	return m, nil
+}
+
+func resGetRunCmd(s sesn.Sesn, resType sesn.ResourceType, uri string) {
 	c := xact.NewGetResCmd()
 	c.SetTxOptions(nmutil.TxOptions())
 	c.Uri = uri
-	c.Typ = rt
+	c.Typ = resType
 
 	res, err := c.Run(s)
 	if err != nil {
@@ -65,15 +67,69 @@ func getResRunCmd(cmd *cobra.Command, args []string) {
 	}
 }
 
+func resPutRunCmd(s sesn.Sesn, resType sesn.ResourceType, uri string,
+	value map[string]interface{}) {
+
+	c := xact.NewPutResCmd()
+	c.SetTxOptions(nmutil.TxOptions())
+	c.Uri = uri
+	c.Typ = resType
+	c.Value = value
+
+	res, err := c.Run(s)
+	if err != nil {
+		nmUsage(nil, util.ChildNewtError(err))
+	}
+
+	sres := res.(*xact.PutResResult)
+	if sres.Status() != 0 {
+		fmt.Printf("Error: %d\n", sres.Status())
+	} else {
+		fmt.Printf("Done\n")
+	}
+}
+
+func resRunCmd(cmd *cobra.Command, args []string) {
+	if len(args) != 2 {
+		nmUsage(cmd, nil)
+	}
+
+	rt, err := sesn.ParseResType(args[0])
+	if err != nil {
+		nmUsage(cmd, err)
+	}
+
+	uri := args[1]
+
+	var m map[string]interface{}
+	if len(args) >= 3 {
+		m, err = extractResKv(args[2:])
+		if err != nil {
+			nmUsage(cmd, err)
+		}
+	}
+
+	s, err := GetSesn()
+	if err != nil {
+		nmUsage(nil, err)
+	}
+
+	if m == nil {
+		resGetRunCmd(s, rt, uri)
+	} else {
+		resPutRunCmd(s, rt, uri, m)
+	}
+}
+
 func getResCmd() *cobra.Command {
-	getResEx := "   newtmgr -c olimex getres public mynewt.value.0\n"
+	resEx := "   newtmgr -c olimex res public mynewt.value.0\n"
 
-	getResCmd := &cobra.Command{
-		Use:     "getres <type> <uri>",
-		Short:   "Read a CoAP resource on a device",
-		Example: getResEx,
-		Run:     getResRunCmd,
+	resCmd := &cobra.Command{
+		Use:     "res <type> <uri> [k=v] [k=v] [...]",
+		Short:   "Read or write a CoAP resource on a device",
+		Example: resEx,
+		Run:     resRunCmd,
 	}
 
-	return getResCmd
+	return resCmd
 }
diff --git a/nmxact/bledefs/bledefs.go b/nmxact/bledefs/bledefs.go
index 4f0b8c9..d19d7e9 100644
--- a/nmxact/bledefs/bledefs.go
+++ b/nmxact/bledefs/bledefs.go
@@ -44,9 +44,9 @@ const OmpSecSvcUuid = 0xfe18
 const OmpSecReqChrUuid = 0x1000
 const OmpSecRspChrUuid = 0x1001
 
-const GwSvcUuid = "0c08c213-98ed-4e43-a499-7e1137c39567"
-const GwReqChrUuid = "69b8a928-2ab2-487b-923e-54ce53a18bc1"
-const GwRspChrUuid = "bca10aea-5df1-4248-b72b-f52955ad9c88"
+const UnauthSvcUuid = "0c08c213-98ed-4e43-a499-7e1137c39567"
+const UnauthReqChrUuid = "69b8a928-2ab2-487b-923e-54ce53a18bc1"
+const UnauthRspChrUuid = "bca10aea-5df1-4248-b72b-f52955ad9c88"
 
 type BleAddrType int
 
@@ -814,8 +814,8 @@ type BleMgmtChrs struct {
 	NmpRspChr        *BleChrId
 	ResPublicReqChr  *BleChrId
 	ResPublicRspChr  *BleChrId
-	ResGwReqChr      *BleChrId
-	ResGwRspChr      *BleChrId
-	ResPrivateReqChr *BleChrId
-	ResPrivateRspChr *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 a3f23f3..62b93a0 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 0918e58..63e0d96 100644
--- a/nmxact/nmble/ble_sesn.go
+++ b/nmxact/nmble/ble_sesn.go
@@ -340,3 +340,9 @@ func (s *BleSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 
 	return rsp.Code(), rsp.Payload(), nil
 }
+
+func (s *BleSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte, opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("SerialPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/nmxact/nmble/ble_util.go b/nmxact/nmble/ble_util.go
index 2630536..b620d78 100644
--- a/nmxact/nmble/ble_util.go
+++ b/nmxact/nmble/ble_util.go
@@ -715,9 +715,9 @@ func GenCoapService(x *BleXport, svcUuid BleUuid, reqChrUuid BleUuid,
 }
 
 func GwService(x *BleXport) (BleSvc, error) {
-	svcUuid, _ := ParseUuid(GwSvcUuid)
-	reqChrUuid, _ := ParseUuid(GwReqChrUuid)
-	rspChrUuid, _ := ParseUuid(GwRspChrUuid)
+	svcUuid, _ := ParseUuid(UnauthSvcUuid)
+	reqChrUuid, _ := ParseUuid(UnauthReqChrUuid)
+	rspChrUuid, _ := ParseUuid(UnauthRspChrUuid)
 
 	resources := []oic.Resource{
 		oic.Resource{
@@ -733,9 +733,9 @@ func GwService(x *BleXport) (BleSvc, error) {
 
 func ResChrIdLookup(mgmtChrs BleMgmtChrs, resType sesn.ResourceType) *BleChrId {
 	m := map[sesn.ResourceType]*BleChrId{
-		sesn.RES_TYPE_PUBLIC:  mgmtChrs.ResPublicReqChr,
-		sesn.RES_TYPE_UNAUTH: mgmtChrs.ResGwReqChr,
-		sesn.RES_TYPE_SECURE: mgmtChrs.ResPrivateReqChr,
+		sesn.RES_TYPE_PUBLIC: mgmtChrs.ResPublicReqChr,
+		sesn.RES_TYPE_UNAUTH: mgmtChrs.ResUnauthReqChr,
+		sesn.RES_TYPE_SECURE: mgmtChrs.ResSecureReqChr,
 	}
 
 	return m[resType]
@@ -751,9 +751,9 @@ func BuildMgmtChrs(mgmtProto sesn.MgmtProto) (BleMgmtChrs, error) {
 	ompReqChrUuid, _ := ParseUuid(OmpUnsecReqChrUuid)
 	ompRspChrUuid, _ := ParseUuid(OmpUnsecRspChrUuid)
 
-	gwSvcUuid, _ := ParseUuid(GwSvcUuid)
-	gwReqChrUuid, _ := ParseUuid(GwReqChrUuid)
-	gwRspChrUuid, _ := ParseUuid(GwRspChrUuid)
+	unauthSvcUuid, _ := ParseUuid(UnauthSvcUuid)
+	unauthReqChrUuid, _ := ParseUuid(UnauthReqChrUuid)
+	unauthRspChrUuid, _ := ParseUuid(UnauthRspChrUuid)
 
 	switch mgmtProto {
 	case sesn.MGMT_PROTO_NMP:
@@ -769,8 +769,8 @@ func BuildMgmtChrs(mgmtProto sesn.MgmtProto) (BleMgmtChrs, error) {
 			fmt.Errorf("invalid management protocol: %+v", mgmtProto)
 	}
 
-	mgmtChrs.ResGwReqChr = &BleChrId{gwSvcUuid, gwReqChrUuid}
-	mgmtChrs.ResGwRspChr = &BleChrId{gwSvcUuid, gwRspChrUuid}
+	mgmtChrs.ResUnauthReqChr = &BleChrId{unauthSvcUuid, unauthReqChrUuid}
+	mgmtChrs.ResUnauthRspChr = &BleChrId{unauthSvcUuid, unauthRspChrUuid}
 
 	return mgmtChrs, nil
 }
diff --git a/nmxact/nmserial/serial_oic_sesn.go b/nmxact/nmserial/serial_oic_sesn.go
index 8279065..f97655e 100644
--- a/nmxact/nmserial/serial_oic_sesn.go
+++ b/nmxact/nmserial/serial_oic_sesn.go
@@ -183,3 +183,10 @@ func (sos *SerialOicSesn) GetResourceOnce(resType sesn.ResourceType,
 		}
 	}
 }
+
+func (sos *SerialOicSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("SerialOicSesn.PutResourceOnce() unsupported")
+}
diff --git a/nmxact/nmserial/serial_plain_sesn.go b/nmxact/nmserial/serial_plain_sesn.go
index 5f219da..c6a88db 100644
--- a/nmxact/nmserial/serial_plain_sesn.go
+++ b/nmxact/nmserial/serial_plain_sesn.go
@@ -162,3 +162,10 @@ func (sps *SerialPlainSesn) GetResourceOnce(resType sesn.ResourceType,
 
 	return 0, nil, fmt.Errorf("SerialPlainSesn.GetResourceOnce() unsupported")
 }
+
+func (sps *SerialPlainSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("SerialPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/nmxact/nmxutil/nmxutil.go b/nmxact/nmxutil/nmxutil.go
index d95c368..ff1e5f8 100644
--- a/nmxact/nmxutil/nmxutil.go
+++ b/nmxact/nmxutil/nmxutil.go
@@ -116,6 +116,16 @@ func DecodeCborMap(cbor []byte) (map[string]interface{}, error) {
 	return m, nil
 }
 
+func EncodeCborMap(value map[string]interface{}) ([]byte, error) {
+	b := []byte{}
+	enc := codec.NewEncoderBytes(&b, new(codec.CborHandle))
+	if err := enc.Encode(value); err != nil {
+		return nil, fmt.Errorf("failure encoding cbor; %s", err.Error())
+	}
+
+	return b, nil
+}
+
 var nextId uint32
 
 func GetNextId() uint32 {
diff --git a/nmxact/sesn/sesn.go b/nmxact/sesn/sesn.go
index 8db9438..0c7507f 100644
--- a/nmxact/sesn/sesn.go
+++ b/nmxact/sesn/sesn.go
@@ -97,5 +97,6 @@ type Sesn interface {
 	GetResourceOnce(resType ResourceType, uri string, opt TxOptions) (
 		coap.COAPCode, []byte, error)
 
-	//SetResource(uri string, value []byte, opt TxOptions) error
+	PutResourceOnce(resType ResourceType, uri string,
+		value []byte, opt TxOptions) (coap.COAPCode, error)
 }
diff --git a/nmxact/sesn/sesn_util.go b/nmxact/sesn/sesn_util.go
index 6399ee9..a66aed6 100644
--- a/nmxact/sesn/sesn_util.go
+++ b/nmxact/sesn/sesn_util.go
@@ -55,3 +55,24 @@ 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
+	}
+
+	retries := o.Tries - 1
+	for i := 0; ; i++ {
+		code, err := s.PutResourceOnce(resType, uri, b, o)
+		if err == nil {
+			return code, nil
+		}
+
+		if !nmxutil.IsRspTimeout(err) || i >= retries {
+			return code, err
+		}
+	}
+}
diff --git a/nmxact/udp/udp_oic_sesn.go b/nmxact/udp/udp_oic_sesn.go
index 9690221..9244048 100644
--- a/nmxact/udp/udp_oic_sesn.go
+++ b/nmxact/udp/udp_oic_sesn.go
@@ -176,3 +176,10 @@ func (uos *UdpOicSesn) GetResourceOnce(resType sesn.ResourceType, uri string,
 		}
 	}
 }
+
+func (uos *UdpOicSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("UdpOicSesn.PutResourceOnce() unsupported")
+}
diff --git a/nmxact/udp/udp_plain_sesn.go b/nmxact/udp/udp_plain_sesn.go
index 4f79310..e6265f1 100644
--- a/nmxact/udp/udp_plain_sesn.go
+++ b/nmxact/udp/udp_plain_sesn.go
@@ -139,3 +139,10 @@ func (ups *UdpPlainSesn) GetResourceOnce(resType sesn.ResourceType,
 
 	return 0, nil, fmt.Errorf("UdpPlainSesn.GetResourceOnce() unsupported")
 }
+
+func (ups *UdpPlainSesn) PutResourceOnce(resType sesn.ResourceType,
+	uri string, value []byte,
+	opt sesn.TxOptions) (coap.COAPCode, error) {
+
+	return 0, fmt.Errorf("UdpPlainSesn.PutResourceOnce() unsupported")
+}
diff --git a/nmxact/xact/getres.go b/nmxact/xact/res.go
similarity index 70%
rename from nmxact/xact/getres.go
rename to nmxact/xact/res.go
index e56067d..6cfa47e 100644
--- a/nmxact/xact/getres.go
+++ b/nmxact/xact/res.go
@@ -65,3 +65,43 @@ func (c *GetResCmd) Run(s sesn.Sesn) (Result, error) {
 	res.Value = val
 	return res, nil
 }
+
+type PutResCmd struct {
+	CmdBase
+	Uri   string
+	Typ   sesn.ResourceType
+	Value map[string]interface{}
+}
+
+func NewPutResCmd() *PutResCmd {
+	return &PutResCmd{
+		CmdBase: NewCmdBase(),
+	}
+}
+
+type PutResResult struct {
+	Code coap.COAPCode
+}
+
+func newPutResResult() *PutResResult {
+	return &PutResResult{}
+}
+
+func (r *PutResResult) Status() int {
+	if r.Code == coap.Content {
+		return 0
+	} else {
+		return int(r.Code)
+	}
+}
+
+func (c *PutResCmd) Run(s sesn.Sesn) (Result, error) {
+	status, err := sesn.PutResource(s, c.Typ, c.Uri, c.Value, c.TxOptions())
+	if err != nil {
+		return nil, err
+	}
+
+	res := newPutResResult()
+	res.Code = status
+	return res, nil
+}

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