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 a5f4d5fb34a66316544f51ef99135ae85caddee2 Author: Christopher Collins <ccoll...@apache.org> AuthorDate: Fri Aug 4 12:22:17 2017 -0700 newtmgr - getres --- newtmgr/bll/bll_oic_sesn.go | 141 ++++++++++++++++----------- newtmgr/bll/bll_plain_sesn.go | 5 +- newtmgr/cli/commands.go | 1 + newtmgr/cli/getres.go | 74 ++++++++++++++ nmxact/nmble/ble_oic_sesn.go | 8 +- nmxact/sesn/sesn.go | 8 ++ nmxact/sesn/sesn_util.go | 8 +- nmxact/{sesn/sesn_util.go => xact/getres.go} | 60 +++++++----- 8 files changed, 213 insertions(+), 92 deletions(-) diff --git a/newtmgr/bll/bll_oic_sesn.go b/newtmgr/bll/bll_oic_sesn.go index c4f32e4..0aca6ca 100644 --- a/newtmgr/bll/bll_oic_sesn.go +++ b/newtmgr/bll/bll_oic_sesn.go @@ -25,6 +25,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/currantlabs/ble" + "github.com/runtimeco/go-coap" "golang.org/x/net/context" "mynewt.apache.org/newtmgr/newtmgr/nmutil" @@ -32,6 +33,7 @@ import ( "mynewt.apache.org/newtmgr/nmxact/nmble" "mynewt.apache.org/newtmgr/nmxact/nmp" "mynewt.apache.org/newtmgr/nmxact/nmxutil" + "mynewt.apache.org/newtmgr/nmxact/oic" "mynewt.apache.org/newtmgr/nmxact/omp" "mynewt.apache.org/newtmgr/nmxact/sesn" ) @@ -53,50 +55,50 @@ func NewBllOicSesn(cfg BllSesnCfg) *BllOicSesn { } } -func (bos *BllOicSesn) listenDisconnect() { +func (bls *BllOicSesn) listenDisconnect() { go func() { - <-bos.cln.Disconnected() + <-bls.cln.Disconnected() - bos.mtx.Lock() - bos.d.ErrorAll(fmt.Errorf("Disconnected")) - bos.d.Stop() - bos.mtx.Unlock() + bls.mtx.Lock() + bls.d.ErrorAll(fmt.Errorf("Disconnected")) + bls.d.Stop() + bls.mtx.Unlock() - bos.cln = nil + bls.cln = nil }() } -func (bos *BllOicSesn) connect() error { +func (bls *BllOicSesn) connect() error { log.Debugf("Connecting to peer") ctx := ble.WithSigHandler(context.WithTimeout(context.Background(), - bos.cfg.ConnTimeout)) + bls.cfg.ConnTimeout)) var err error - bos.cln, err = ble.Connect(ctx, bos.cfg.AdvFilter) + bls.cln, err = ble.Connect(ctx, bls.cfg.AdvFilter) if err != nil { if nmutil.ErrorCausedBy(err, context.DeadlineExceeded) { return fmt.Errorf("Failed to connect to peer after %s", - bos.cfg.ConnTimeout.String()) + bls.cfg.ConnTimeout.String()) } else { return err } } - bos.listenDisconnect() + bls.listenDisconnect() return nil } -func (bos *BllOicSesn) discoverAll() error { +func (bls *BllOicSesn) discoverAll() error { log.Debugf("Discovering profile") - p, err := bos.cln.DiscoverProfile(true) + p, err := bls.cln.DiscoverProfile(true) if err != nil { return err } - ompUnsecSvcUuid, _ := bledefs.ParseUuid(bledefs.OmpUnsecSvcUuid) - reqChrUuid, _ := bledefs.ParseUuid(bledefs.OmpUnsecReqChrUuid) - rspChrUuid, _ := bledefs.ParseUuid(bledefs.OmpUnsecRspChrUuid) + ompUnsecSvcUuid, _ := ParseUuid(bledefs.OmpUnsecSvcUuid) + reqChrUuid, _ := ParseUuid(bledefs.OmpUnsecReqChrUuid) + rspChrUuid, _ := ParseUuid(bledefs.OmpUnsecRspChrUuid) for _, s := range p.Services { uuid, err := UuidFromBllUuid(s.UUID) @@ -112,15 +114,15 @@ func (bos *BllOicSesn) discoverAll() error { } if bledefs.CompareUuids(uuid, reqChrUuid) == 0 { - bos.nmpReqChr = c + bls.nmpReqChr = c } else if bledefs.CompareUuids(uuid, rspChrUuid) == 0 { - bos.nmpRspChr = c + bls.nmpRspChr = c } } } } - if bos.nmpReqChr == nil || bos.nmpRspChr == nil { + if bls.nmpReqChr == nil || bls.nmpRspChr == nil { return fmt.Errorf( "Peer doesn't support a suitable service / characteristic") } @@ -129,31 +131,31 @@ func (bos *BllOicSesn) discoverAll() error { } // Subscribes to the peer's characteristic implementing NMP. -func (bos *BllOicSesn) subscribe() error { +func (bls *BllOicSesn) subscribe() error { log.Debugf("Subscribing to NMP response characteristic") onNotify := func(data []byte) { - bos.d.Dispatch(data) + bls.d.Dispatch(data) } - if err := bos.cln.Subscribe(bos.nmpRspChr, false, onNotify); err != nil { + if err := bls.cln.Subscribe(bls.nmpRspChr, false, onNotify); err != nil { return err } return nil } -func (bos *BllOicSesn) exchangeMtu() error { - mtu, err := exchangeMtu(bos.cln, bos.cfg.PreferredMtu) +func (bls *BllOicSesn) exchangeMtu() error { + mtu, err := exchangeMtu(bls.cln, bls.cfg.PreferredMtu) if err != nil { return err } - bos.attMtu = mtu + bls.attMtu = mtu return nil } -func (bos *BllOicSesn) Open() error { - if bos.IsOpen() { +func (bls *BllOicSesn) Open() error { + if bls.IsOpen() { return nmxutil.NewSesnAlreadyOpenError( "Attempt to open an already-open bll session") } @@ -162,64 +164,64 @@ func (bos *BllOicSesn) Open() error { if err != nil { return err } - bos.d = d + bls.d = d - if err := bos.connect(); err != nil { + if err := bls.connect(); err != nil { return err } - if err := bos.exchangeMtu(); err != nil { + if err := bls.exchangeMtu(); err != nil { return err } - if err := bos.discoverAll(); err != nil { + if err := bls.discoverAll(); err != nil { return err } - if err := bos.subscribe(); err != nil { + if err := bls.subscribe(); err != nil { return err } return nil } -func (bos *BllOicSesn) Close() error { - if !bos.IsOpen() { +func (bls *BllOicSesn) Close() error { + if !bls.IsOpen() { return nmxutil.NewSesnClosedError( "Attempt to close an unopened bll session") } - if err := bos.cln.CancelConnection(); err != nil { + if err := bls.cln.CancelConnection(); err != nil { return err } - bos.cln = nil + bls.cln = nil return nil } // Indicates whether the session is currently open. -func (bos *BllOicSesn) IsOpen() bool { - return bos.cln != nil +func (bls *BllOicSesn) IsOpen() bool { + return bls.cln != nil } // Retrieves the maximum data payload for outgoing NMP requests. -func (bos *BllOicSesn) MtuOut() int { - return bos.attMtu - nmble.NOTIFY_CMD_BASE_SZ - nmp.NMP_HDR_SIZE +func (bls *BllOicSesn) MtuOut() int { + return bls.attMtu - nmble.NOTIFY_CMD_BASE_SZ - nmp.NMP_HDR_SIZE } // Retrieves the maximum data payload for incoming NMP responses. -func (bos *BllOicSesn) MtuIn() int { - return bos.attMtu - nmble.NOTIFY_CMD_BASE_SZ - nmp.NMP_HDR_SIZE +func (bls *BllOicSesn) MtuIn() int { + return bls.attMtu - nmble.NOTIFY_CMD_BASE_SZ - nmp.NMP_HDR_SIZE } // Stops a receive operation in progress. This must be called from a // separate thread, as sesn receive operations are blocking. -func (bos *BllOicSesn) AbortRx(nmpSeq uint8) error { - return bos.d.ErrorOneNmp(nmpSeq, fmt.Errorf("Rx aborted")) +func (bls *BllOicSesn) AbortRx(nmpSeq uint8) error { + return bls.d.ErrorOneNmp(nmpSeq, fmt.Errorf("Rx aborted")) } -func (bos *BllOicSesn) EncodeNmpMsg(msg *nmp.NmpMsg) ([]byte, error) { +func (bls *BllOicSesn) EncodeNmpMsg(msg *nmp.NmpMsg) ([]byte, error) { return omp.EncodeOmpTcp(msg) } @@ -228,27 +230,27 @@ func (bos *BllOicSesn) EncodeNmpMsg(msg *nmp.NmpMsg) ([]byte, error) { // * nil: success. // * nmxutil.SesnClosedError: session not open. // * other error -func (bos *BllOicSesn) TxNmpOnce(msg *nmp.NmpMsg, opt sesn.TxOptions) ( +func (bls *BllOicSesn) TxNmpOnce(msg *nmp.NmpMsg, opt sesn.TxOptions) ( nmp.NmpRsp, error) { - if !bos.IsOpen() { + if !bls.IsOpen() { return nil, nmxutil.NewSesnClosedError( "Attempt to transmit over closed BLE session") } - b, err := bos.EncodeNmpMsg(msg) + b, err := bls.EncodeNmpMsg(msg) if err != nil { return nil, err } - nl, err := bos.d.AddNmpListener(msg.Hdr.Seq) + nl, err := bls.d.AddNmpListener(msg.Hdr.Seq) if err != nil { return nil, err } - defer bos.d.RemoveNmpListener(msg.Hdr.Seq) + defer bls.d.RemoveNmpListener(msg.Hdr.Seq) // Send request. - if err := bos.cln.WriteCharacteristic(bos.nmpReqChr, b, true); err != nil { + if err := bls.cln.WriteCharacteristic(bls.nmpReqChr, b, true); err != nil { return nil, err } @@ -269,8 +271,37 @@ func (bos *BllOicSesn) TxNmpOnce(msg *nmp.NmpMsg, opt sesn.TxOptions) ( } } -func (bos *BllOicSesn) GetResourceOnce(uri string, opt sesn.TxOptions) ( - []byte, error) { +func (bls *BllOicSesn) GetResourceOnce(uri string, opt sesn.TxOptions) ( + coap.COAPCode, []byte, error) { - return nil, fmt.Errorf("BllOicSesn.GetResourceOnce() unimplemented") + token := nmxutil.NextToken() + + ol, err := bls.d.AddOicListener(token) + if err != nil { + return 0, nil, err + } + defer bls.d.RemoveOicListener(token) + + req, err := oic.EncodeGet(uri, token) + if err != nil { + return 0, nil, err + } + + // Send request. + if err := bls.cln.WriteCharacteristic(bls.nmpReqChr, req, true); err != nil { + return 0, nil, err + } + + // Now wait for CoAP response. + for { + select { + case err := <-ol.ErrChan: + return 0, nil, err + case rsp := <-ol.RspChan: + return rsp.Code, rsp.Payload, nil + case <-ol.AfterTimeout(opt.Timeout): + msg := fmt.Sprintf("CoAP timeout; uri=%s", uri) + return 0, nil, nmxutil.NewRspTimeoutError(msg) + } + } } diff --git a/newtmgr/bll/bll_plain_sesn.go b/newtmgr/bll/bll_plain_sesn.go index d01ba51..0808bb4 100644 --- a/newtmgr/bll/bll_plain_sesn.go +++ b/newtmgr/bll/bll_plain_sesn.go @@ -24,6 +24,7 @@ import ( log "github.com/Sirupsen/logrus" "github.com/currantlabs/ble" + "github.com/runtimeco/go-coap" "golang.org/x/net/context" "mynewt.apache.org/newtmgr/newtmgr/nmutil" @@ -251,8 +252,8 @@ func (bps *BllPlainSesn) TxNmpOnce(msg *nmp.NmpMsg, opt sesn.TxOptions) ( } func (bps *BllPlainSesn) GetResourceOnce(uri string, opt sesn.TxOptions) ( - []byte, error) { + coap.COAPCode, []byte, error) { - return nil, + return 0, nil, fmt.Errorf("Resource API not supported by plain (non-OIC) session") } diff --git a/newtmgr/cli/commands.go b/newtmgr/cli/commands.go index 83347df..41a9120 100644 --- a/newtmgr/cli/commands.go +++ b/newtmgr/cli/commands.go @@ -81,6 +81,7 @@ func Commands() *cobra.Command { nmCmd.AddCommand(configCmd()) nmCmd.AddCommand(connProfileCmd()) nmCmd.AddCommand(echoCmd()) + nmCmd.AddCommand(getResCmd()) return nmCmd } diff --git a/newtmgr/cli/getres.go b/newtmgr/cli/getres.go new file mode 100644 index 0000000..a70b922 --- /dev/null +++ b/newtmgr/cli/getres.go @@ -0,0 +1,74 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +package cli + +import ( + "fmt" + + "github.com/spf13/cobra" + + "mynewt.apache.org/newt/util" + "mynewt.apache.org/newtmgr/newtmgr/nmutil" + "mynewt.apache.org/newtmgr/nmxact/xact" +) + +func getResRunCmd(cmd *cobra.Command, args []string) { + if len(args) != 2 { + nmUsage(cmd, nil) + } + + // XXX: Parse type. + + uri := args[1] + + s, err := GetSesn() + if err != nil { + nmUsage(nil, err) + } + + c := xact.NewGetResCmd() + c.SetTxOptions(nmutil.TxOptions()) + c.Uri = uri + + res, err := c.Run(s) + if err != nil { + nmUsage(nil, util.ChildNewtError(err)) + } + + sres := res.(*xact.GetResResult) + if sres.Status() != 0 { + fmt.Printf("Error: %d\n", sres.Status()) + } else { + fmt.Printf("%s: %+v\n", uri, sres.Value) + } +} + +func getResCmd() *cobra.Command { + getResEx := " newtmgr -c olimex getres public mynewt.value.0\n" + + getResCmd := &cobra.Command{ + Use: "getres <type> <uri>", + Short: "Read a CoAP resource on a device", + Example: getResEx, + Run: getResRunCmd, + } + + return getResCmd +} diff --git a/nmxact/nmble/ble_oic_sesn.go b/nmxact/nmble/ble_oic_sesn.go index 46d2f07..9d86e67 100644 --- a/nmxact/nmble/ble_oic_sesn.go +++ b/nmxact/nmble/ble_oic_sesn.go @@ -202,7 +202,7 @@ func (bos *BleOicSesn) ConnInfo() (BleConnDesc, error) { } func (bos *BleOicSesn) GetResourceOnce(uri string, opt sesn.TxOptions) ( - []byte, error) { + int, []byte, error) { token := nmxutil.NextToken() @@ -222,9 +222,5 @@ func (bos *BleOicSesn) GetResourceOnce(uri string, opt sesn.TxOptions) ( return nil, err } - if rsp.Code != coap.Content { - return nil, fmt.Errorf("UNEXPECTED OIC ACK: %#v", rsp) - } - - return rsp.Payload, nil + return rsp.Status, rsp.Payload, nil } diff --git a/nmxact/sesn/sesn.go b/nmxact/sesn/sesn.go index 3a064b5..4716413 100644 --- a/nmxact/sesn/sesn.go +++ b/nmxact/sesn/sesn.go @@ -25,6 +25,14 @@ import ( "mynewt.apache.org/newtmgr/nmxact/nmp" ) +type ResourceType int + +const ( + RES_TYPE_PUBLIC ResourceType = iota + RES_TYPE_GATEWAY + RES_TYPE_SECURE +) + type TxOptions struct { Timeout time.Duration Tries int diff --git a/nmxact/sesn/sesn_util.go b/nmxact/sesn/sesn_util.go index 9bcbd02..20db346 100644 --- a/nmxact/sesn/sesn_util.go +++ b/nmxact/sesn/sesn_util.go @@ -38,16 +38,16 @@ func TxNmp(s Sesn, m *nmp.NmpMsg, o TxOptions) (nmp.NmpRsp, error) { } } -func GetResource(s Sesn, uri string, o TxOptions) ([]byte, error) { +func GetResource(s Sesn, uri string, o TxOptions) (int, []byte, error) { retries := o.Tries - 1 for i := 0; ; i++ { - r, err := s.GetResourceOnce(uri, o) + status, r, err := s.GetResourceOnce(uri, o) if err == nil { - return r, nil + return status, r, nil } if !nmxutil.IsRspTimeout(err) || i >= retries { - return nil, err + return status, nil, err } } } diff --git a/nmxact/sesn/sesn_util.go b/nmxact/xact/getres.go similarity index 55% copy from nmxact/sesn/sesn_util.go copy to nmxact/xact/getres.go index 9bcbd02..609dadc 100644 --- a/nmxact/sesn/sesn_util.go +++ b/nmxact/xact/getres.go @@ -17,37 +17,47 @@ * under the License. */ -package sesn +package xact import ( - "mynewt.apache.org/newtmgr/nmxact/nmp" - "mynewt.apache.org/newtmgr/nmxact/nmxutil" + "github.com/runtimeco/go-coap" + + "mynewt.apache.org/newtmgr/nmxact/sesn" ) -func TxNmp(s Sesn, m *nmp.NmpMsg, o TxOptions) (nmp.NmpRsp, error) { - retries := o.Tries - 1 - for i := 0; ; i++ { - r, err := s.TxNmpOnce(m, o) - if err == nil { - return r, nil - } - - if !nmxutil.IsRspTimeout(err) || i >= retries { - return nil, err - } +type GetResCmd struct { + CmdBase + Uri string + Typ sesn.ResourceType +} + +func NewGetResCmd() *GetResCmd { + return &GetResCmd{ + CmdBase: NewCmdBase(), } } -func GetResource(s Sesn, uri string, o TxOptions) ([]byte, error) { - retries := o.Tries - 1 - for i := 0; ; i++ { - r, err := s.GetResourceOnce(uri, o) - if err == nil { - return r, nil - } - - if !nmxutil.IsRspTimeout(err) || i >= retries { - return nil, err - } +type GetResResult struct { + Code coap.COAPCode + Value []byte +} + +func newGetResResult() *GetResResult { + return &GetResResult{} +} + +func (r *GetResResult) Status() int { + return int(r.Code) +} + +func (c *GetResCmd) Run(s sesn.Sesn) (Result, error) { + status, val, err := sesn.GetResource(s, c.Uri, c.TxOptions()) + if err != nil { + return nil, err } + + res := newGetResResult() + res.Code = status + res.Value = val + return res, nil } -- To stop receiving notification emails like this one, please contact "commits@mynewt.apache.org" <commits@mynewt.apache.org>.