Skip to content

Commit

Permalink
further seperate ZCL events by functional and foundation
Browse files Browse the repository at this point in the history
  • Loading branch information
splitice committed Sep 19, 2023
1 parent 875f33d commit ed76766
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 16 deletions.
44 changes: 29 additions & 15 deletions lib/Af.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ class Af extends EventEmitter {
- _indirect_send
*/
this._controller = controller
this._seq = 0

// 0..250 random number to start seq with
this._seq = Math.floor(Math.random() * 250)

this.indirectTimeout = 70000
this.resendTimeout = 8100
this.maxTransactions = 250
Expand All @@ -64,7 +67,7 @@ class Af extends EventEmitter {
}

nextZclSeqNum() {
seqNumber += 1; // seqNumber is a private var on the top of this module
seqNumber ++; // seqNumber is a private var on the top of this module
if (seqNumber >= 253 || seqNumber < 0)
seqNumber = 0;

Expand Down Expand Up @@ -112,11 +115,12 @@ class Af extends EventEmitter {

if(msg.zclMsg.frameCntl.direction === 1) {
// for broadcast responses only
this.emit('ZCL:incomingMsg:' + msg.dstendpoint + ':' + msg.zclMsg.seqNum, msg);
const prefix = 'ZCL:'+(frameType ? 'functional' : 'foundation')+':'
this.emit(prefix + msg.dstendpoint + ':' + msg.zclMsg.seqNum, msg);

// { groupid, clusterid, srcaddr, srcendpoint, dstendpoint, wasbroadcast, linkquality, securityuse, timestamp, transseqnumber, zclMsg }
this.emit('ZCL:incomingMsg:' + msg.srcaddr.toString(16) + ':' + msg.srcendpoint + ':' + msg.dstendpoint + ':' + msg.zclMsg.seqNum, msg);
this.emit('ZCL:incomingMsg:' + msg.srcaddr.toString(16) + ':' + msg.srcendpoint + ':' + msg.zclMsg.seqNum, msg);
this.emit(prefix + msg.srcaddr.toString(16) + ':' + msg.srcendpoint + ':' + msg.dstendpoint + ':' + msg.zclMsg.seqNum, msg);
this.emit(prefix + msg.srcaddr.toString(16) + ':' + msg.srcendpoint + ':' + msg.zclMsg.seqNum, msg);
}

// Necessary, some IAS devices don't respect endpoints
Expand All @@ -137,7 +141,7 @@ class Af extends EventEmitter {
}
}

if (typeof dispatchTo == "function") {
if (dispatchTo) {
dispatchTo.call(targetEp, msg, remoteEp);
}

Expand Down Expand Up @@ -281,7 +285,7 @@ class Af extends EventEmitter {
try {
let areqCancelable = areqC()

const startAreq = async () => {
const startAreq = async (attempt) => {
let cnf

do {
Expand All @@ -292,6 +296,13 @@ class Af extends EventEmitter {
if (cnf.status === 0 || cnf.status === 'SUCCESS') { // success
this.emit('ind:dataConfirm', { dstEp, afParams });
return cnf
} else if(cnf.status == 205) { // ZNwkNoRoute
await controller.request('NWK', 'rtg', { nwkaddr: dstAddr })
await Q.delay(((Math.random()/4) + 0.75) * 16000)
await controller.request('NWK', 'rtg', { nwkaddr: dstAddr })
if(attempt > 1) {
shouldResend = false
}
}

if (shouldResend) {
Expand Down Expand Up @@ -367,9 +378,8 @@ class Af extends EventEmitter {
areqCancelable._cancels.delete(wf)
await Q.delay((Math.random() + 0.5) * 16000)
continue
} else {
throw ex
}
throw ex
}
wf.then(areqCancelable.resolve, areqCancelable.reject)
break
Expand All @@ -379,10 +389,10 @@ class Af extends EventEmitter {
isResend = true
}

const indirectSendFn = async () => {
const indirectSendFn = async (attempt) => {
try {
await afSend()
return await startAreq()
return await startAreq(attempt)
} catch (ex) {
areqCancelable.cancel()
throw ex
Expand Down Expand Up @@ -436,6 +446,8 @@ class Af extends EventEmitter {

// .frame(frameCntl, manufCode, seqNum, cmd, zclPayload[, clusterId])
seqNum = cfg.seqNum !== undefined ? cfg.seqNum : this.nextZclSeqNum();

if(dstEp._logger) dstEp._logger(`zclFoundation(${cmd}:${seqNum}) ${JSON.stringify(zclData)}`)

zclBuffer = zcl.frame(frameCntl, manufCode, seqNum, cmd, zclData);

Expand All @@ -444,9 +456,9 @@ class Af extends EventEmitter {
const nwkAddr = dstEp.nwkAddr
assert(typeof nwkAddr === 'number')
if (srcEp === dstEp) // from remote to remote itself
mandatoryEvent = 'ZCL:incomingMsg:' + nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + seqNum;
mandatoryEvent = 'ZCL:foundation:' + nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + seqNum;
else // from local ep to remote ep
mandatoryEvent = 'ZCL:incomingMsg:' + nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + srcEp.getEpId() + ':' + seqNum;
mandatoryEvent = 'ZCL:foundation:' + nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + srcEp.getEpId() + ':' + seqNum;

areq = this.waitFor(mandatoryEvent, AreqTimeout)
}
Expand Down Expand Up @@ -526,15 +538,17 @@ class Af extends EventEmitter {

// .frame(frameCntl, manufCode, seqNum, cmd, zclPayload[, clusterId])
seqNum = cfg.seqNum !== undefined ? cfg.seqNum : this.nextZclSeqNum();

if(dstEp._logger) dstEp._logger(`zclFunctional(${cmd}:${seqNum}) ${JSON.stringify(zclData)}`)

zclBuffer = zcl.frame(frameCntl, manufCode, seqNum, cmd, zclData, cId);

if (frameCntl.direction === 0 && !cfg.response) { // client-to-server, thus require getting the feedback response

if (srcEp === dstEp) // from remote to remote itself
mandatoryEvent = 'ZCL:incomingMsg:' + dstEp.nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + seqNum;
mandatoryEvent = 'ZCL:functional:' + dstEp.nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + seqNum;
else // from local ep to remote ep
mandatoryEvent = 'ZCL:incomingMsg:' + dstEp.nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + srcEp.getEpId() + ':' + seqNum;
mandatoryEvent = 'ZCL:functional:' + dstEp.nwkAddr.toString(16) + ':' + dstEp.getEpId() + ':' + srcEp.getEpId() + ':' + seqNum;


areq = this.waitFor(mandatoryEvent, AreqTimeout)
Expand Down
3 changes: 2 additions & 1 deletion lib/AfController.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ class AfController extends EventEmitter {
debug(`Doing indirect send attempt ${i}/${retries}`)
}

workPromise = sendFn()
workPromise = sendFn(i)

// It's a race for who can return first
const promises = [Q.delay(cfg.indirectTimeout), workPromise]
Expand All @@ -100,6 +100,7 @@ class AfController extends EventEmitter {
await Q.cancelledRace([Q.delay(5000), workPromise]) // Wait at-least 5 seconds after a module error
}
else if(typeof result === 'number') {
// network status code
if(result != 6 && i != retries) {
const waitTime = 3500 - (Date.now() - attemptStart)
if(waitTime > 0) await await Q.cancelledRace([Q.delay(waitTime), workPromise])
Expand Down

0 comments on commit ed76766

Please sign in to comment.