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 }
