nmxact - Generic adv predicate during scanning.

If the client doesn't know the address of the peer it wants to connect
to, it can supply a predicate which gets called for each incoming
advertisement.  If the callback returns true, nmxact will connect to the
sender of the corresponding advertisement.


Project: http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/repo
Commit: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/commit/06f33c03
Tree: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/tree/06f33c03
Diff: 
http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/diff/06f33c03

Branch: refs/heads/master
Commit: 06f33c03ececeac75b39fabea922d657958a6118
Parents: 4bcaec2
Author: Christopher Collins <[email protected]>
Authored: Tue Mar 28 11:11:51 2017 -0700
Committer: Christopher Collins <[email protected]>
Committed: Tue Mar 28 15:38:36 2017 -0700

----------------------------------------------------------------------
 nmxact/bledefs/bledefs.go      | 21 +++++++++----
 nmxact/nmble/ble_fsm.go        | 60 +++++++++++++++++++++++++++----------
 nmxact/nmble/ble_oic_sesn.go   |  2 +-
 nmxact/nmble/ble_plain_sesn.go |  2 +-
 nmxact/sesn/sesn_cfg.go        | 28 ++++++++++++++++-
 5 files changed, 90 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06f33c03/nmxact/bledefs/bledefs.go
----------------------------------------------------------------------
diff --git a/nmxact/bledefs/bledefs.go b/nmxact/bledefs/bledefs.go
index 5b12d0a..3bb2772 100644
--- a/nmxact/bledefs/bledefs.go
+++ b/nmxact/bledefs/bledefs.go
@@ -147,11 +147,6 @@ func (bd *BleDev) String() string {
                bd.Addr.String())
 }
 
-type BlePeerSpec struct {
-       Name string
-       Dev  BleDev // Only used if name not present.
-}
-
 type BleScanFilterPolicy int
 
 const (
@@ -257,3 +252,19 @@ func (a *BleAdvEventType) UnmarshalJSON(data []byte) error 
{
        *a, err = BleAdvEventTypeFromString(s)
        return err
 }
+
+type BleAdvReport struct {
+       // These fields are always present.
+       EventType BleAdvEventType
+       Sender    BleDev
+       Rssi      int8
+       Data      []byte
+
+       // These fields are only present if the sender included them in its
+       // advertisement.
+       Flags          uint8  // 0 if not present.
+       Name           string // "" if not present.
+       NameIsComplete bool   // false if not present.
+}
+
+type BleAdvPredicate func(adv BleAdvReport) bool

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06f33c03/nmxact/nmble/ble_fsm.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_fsm.go b/nmxact/nmble/ble_fsm.go
index 88ce90e..411ce59 100644
--- a/nmxact/nmble/ble_fsm.go
+++ b/nmxact/nmble/ble_fsm.go
@@ -11,6 +11,7 @@ import (
        . "mynewt.apache.org/newt/nmxact/bledefs"
        "mynewt.apache.org/newt/nmxact/nmp"
        "mynewt.apache.org/newt/nmxact/nmxutil"
+       "mynewt.apache.org/newt/nmxact/sesn"
 )
 
 type BleSesnState int32
@@ -38,7 +39,7 @@ type BleDisconnectFn func(err error)
 type BleFsmParams struct {
        Bx           *BleXport
        OwnAddrType  BleAddrType
-       PeerSpec     BlePeerSpec
+       PeerSpec     sesn.BlePeerSpec
        SvcUuid      BleUuid
        ReqChrUuid   BleUuid
        RspChrUuid   BleUuid
@@ -48,9 +49,9 @@ type BleFsmParams struct {
 
 type BleFsm struct {
        bx           *BleXport
-       peerSpec     BlePeerSpec
        ownAddrType  BleAddrType
-       peer         *BleDev
+       peerSpec     sesn.BlePeerSpec
+       peerDev      *BleDev
        svcUuid      BleUuid
        reqChrUuid   BleUuid
        rspChrUuid   BleUuid
@@ -87,8 +88,14 @@ func NewBleFsm(p BleFsmParams) *BleFsm {
                attMtu: DFLT_ATT_MTU,
        }
 
-       if bf.peerSpec.Name == "" {
-               bf.peer = &bf.peerSpec.Dev
+       // The peer spec contains one of:
+       //     * Peer address;
+       //     * Predicate function to call during scanning.
+       // If a peer address is specified, fill in the peer field now so the
+       // scanning step can be skipped.  Otherwise, the peer field gets 
populated
+       // during scanning.
+       if bf.peerSpec.ScanPred == nil {
+               bf.peerDev = &bf.peerSpec.Dev
        }
 
        return bf
@@ -97,7 +104,7 @@ func NewBleFsm(p BleFsmParams) *BleFsm {
 func (bf *BleFsm) disconnectError(reason int) error {
        str := fmt.Sprintf("BLE peer disconnected; "+
                "reason=\"%s\" (%d) peer=%s handle=%d",
-               ErrCodeToString(reason), reason, bf.peer.String(), 
bf.connHandle)
+               ErrCodeToString(reason), reason, bf.peerDev.String(), 
bf.connHandle)
        return nmxutil.NewBleSesnDisconnectError(reason, str)
 }
 
@@ -231,7 +238,7 @@ func (bf *BleFsm) connectListen(seq int) error {
                                                str := fmt.Sprintf("BLE 
connection attempt failed; "+
                                                        "status=%s (%d) 
peer=%s",
                                                        
ErrCodeToString(msg.Status), msg.Status,
-                                                       bf.peer.String())
+                                                       bf.peerDev.String())
                                                log.Debugf(str)
                                                bf.connChan <- 
nmxutil.NewBleHostError(msg.Status, str)
                                                return
@@ -241,7 +248,7 @@ func (bf *BleFsm) connectListen(seq int) error {
                                        if msg.Status == 0 {
                                                bl.Acked = true
                                                log.Debugf("BLE connection 
attempt succeeded; "+
-                                                       "peer=%d handle=%d", 
bf.peer.String(),
+                                                       "peer=%d handle=%d", 
bf.peerDev.String(),
                                                        msg.ConnHandle)
                                                bf.connHandle = msg.ConnHandle
                                                if err := bf.nmpRspListen(); 
err != nil {
@@ -253,7 +260,7 @@ func (bf *BleFsm) connectListen(seq int) error {
                                                str := fmt.Sprintf("BLE 
connection attempt failed; "+
                                                        "status=%s (%d) 
peer=%s",
                                                        
ErrCodeToString(msg.Status), msg.Status,
-                                                       bf.peer.String())
+                                                       bf.peerDev.String())
                                                log.Debugf(str)
                                                bf.connChan <- 
nmxutil.NewBleHostError(msg.Status, str)
                                                return
@@ -341,8 +348,8 @@ func (bf *BleFsm) nmpRspListen() error {
 func (bf *BleFsm) connect() error {
        r := NewBleConnectReq()
        r.OwnAddrType = bf.ownAddrType
-       r.PeerAddrType = bf.peer.AddrType
-       r.PeerAddr = bf.peer.Addr
+       r.PeerAddrType = bf.peerDev.AddrType
+       r.PeerAddr = bf.peerDev.Addr
 
        if err := bf.connectListen(r.Seq); err != nil {
                return err
@@ -372,15 +379,29 @@ func (bf *BleFsm) scan() error {
 
        abortChan := make(chan struct{}, 1)
 
+       // This function gets called for each incoming advertisement.
        scanCb := func(evt *BleScanEvt) {
-               if evt.DataName == bf.peerSpec.Name {
-                       bf.peer = &BleDev{
+               r := BleAdvReport{
+                       EventType: evt.EventType,
+                       Sender: BleDev{
                                AddrType: evt.AddrType,
                                Addr:     evt.Addr,
-                       }
+                       },
+                       Rssi: evt.Rssi,
+                       Data: evt.Data.Bytes,
+
+                       Flags:          evt.DataFlags,
+                       Name:           evt.DataName,
+                       NameIsComplete: evt.DataNameIsComplete,
+               }
+
+               // Ask client if we should connect to this advertiser.
+               if bf.peerSpec.ScanPred(r) {
+                       bf.peerDev = &r.Sender
                        abortChan <- struct{}{}
                }
        }
+
        if err := scan(bf.bx, bl, r, abortChan, scanCb); err != nil {
                return err
        }
@@ -596,7 +617,14 @@ func (bf *BleFsm) Start() error {
                switch state {
                case SESN_STATE_UNCONNECTED:
                        var err error
-                       if bf.peer == nil {
+
+                       // Determine if we can immediately initiate a 
connection, or if we
+                       // need to scan for a peer first.  If the client 
specified a peer
+                       // address, or if we have already successfully scanned, 
we initiate
+                       // a connection now.  Otherwise, we need to scan to 
determine which
+                       // peer meets the specified scan criteria.
+                       if bf.peerDev == nil {
+                               // Peer not inferred yet.  Initiate scan.
                                cb := func() error { return bf.scan() }
                                err = bf.action(
                                        SESN_STATE_UNCONNECTED,
@@ -604,6 +632,8 @@ func (bf *BleFsm) Start() error {
                                        SESN_STATE_UNCONNECTED,
                                        cb)
                        } else {
+                               // We already know the address we want to 
connect to.  Initiate
+                               // a connection.
                                cb := func() error { return bf.connect() }
                                err = bf.action(
                                        SESN_STATE_UNCONNECTED,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06f33c03/nmxact/nmble/ble_oic_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_oic_sesn.go b/nmxact/nmble/ble_oic_sesn.go
index f0dead2..98a30e9 100644
--- a/nmxact/nmble/ble_oic_sesn.go
+++ b/nmxact/nmble/ble_oic_sesn.go
@@ -49,7 +49,7 @@ func NewBleOicSesn(bx *BleXport, cfg sesn.SesnCfg) 
*BleOicSesn {
        bos.bf = NewBleFsm(BleFsmParams{
                Bx:           bx,
                OwnAddrType:  cfg.Ble.OwnAddrType,
-               PeerSpec:     cfg.Ble.Peer,
+               PeerSpec:     cfg.Ble.PeerSpec,
                SvcUuid:      svcUuid,
                ReqChrUuid:   reqChrUuid,
                RspChrUuid:   rspChrUuid,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06f33c03/nmxact/nmble/ble_plain_sesn.go
----------------------------------------------------------------------
diff --git a/nmxact/nmble/ble_plain_sesn.go b/nmxact/nmble/ble_plain_sesn.go
index c4b24c6..b4fda8e 100644
--- a/nmxact/nmble/ble_plain_sesn.go
+++ b/nmxact/nmble/ble_plain_sesn.go
@@ -43,7 +43,7 @@ func NewBlePlainSesn(bx *BleXport, cfg sesn.SesnCfg) 
*BlePlainSesn {
        bps.bf = NewBleFsm(BleFsmParams{
                Bx:           bx,
                OwnAddrType:  cfg.Ble.OwnAddrType,
-               PeerSpec:     cfg.Ble.Peer,
+               PeerSpec:     cfg.Ble.PeerSpec,
                SvcUuid:      svcUuid,
                ReqChrUuid:   chrUuid,
                RspChrUuid:   chrUuid,

http://git-wip-us.apache.org/repos/asf/incubator-mynewt-newtmgr/blob/06f33c03/nmxact/sesn/sesn_cfg.go
----------------------------------------------------------------------
diff --git a/nmxact/sesn/sesn_cfg.go b/nmxact/sesn/sesn_cfg.go
index cb6dce6..c511d10 100644
--- a/nmxact/sesn/sesn_cfg.go
+++ b/nmxact/sesn/sesn_cfg.go
@@ -15,9 +15,35 @@ const (
 
 type OnCloseFn func(s Sesn, err error)
 
+// Specifies the BLE peer to connect to.
+type BlePeerSpec struct {
+       // This is filled in if you know the address of the peer to connect to.
+       Dev bledefs.BleDev
+
+       // Otherwise, we must scan for a peer to connect to.  This points to a
+       // function that indicates whether we should connect to the sender of 
the
+       // specified advertisement.  This function gets called each time an
+       // incoming advertisement is received.  If it returns true, the session
+       // will connect to the sender of the corresponding advertisement.  Set 
this
+       // to nil if you populate the Dev field.
+       ScanPred bledefs.BleAdvPredicate
+}
+
+func BlePeerSpecDev(dev bledefs.BleDev) BlePeerSpec {
+       return BlePeerSpec{Dev: dev}
+}
+
+func BlePeerSpecName(name string) BlePeerSpec {
+       return BlePeerSpec{
+               ScanPred: func(r bledefs.BleAdvReport) bool {
+                       return r.Name == name
+               },
+       }
+}
+
 type SesnCfgBle struct {
        OwnAddrType  bledefs.BleAddrType
-       Peer         bledefs.BlePeerSpec
+       PeerSpec     BlePeerSpec
        CloseTimeout time.Duration
 }
 

Reply via email to