-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prepare to move specific ZDO requests out of Adapter #1187
base: master
Are you sure you want to change the base?
Conversation
@kirovilya Could you test out zboss? Lots of moving parts, need to confirm nothing broke. If you can report back issues. |
This comment was marked as resolved.
This comment was marked as resolved.
// `authentication`: TC significance always 1 (zb specs) | ||
const zdoPayload = Zdo.Buffalo.buildRequest(this.hasZdoMessageOverhead, clusterId, seconds, 1, []); | ||
|
||
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
there is a special feature for the ZBOSS - you need to send 2 commands: to the coordinator and the broadcast.
await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, true);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So proper logic is like this?
if (networkAddress) {
// device-only when network > 0
await this.sendZdo(ZSpec.BLANK_EUI64, networkAddress, clusterId, zdoPayload, true);
} else {
// coordinator-only when networkAddress === 0 or undefined (all)
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.COORDINATOR_ADDRESS, clusterId, zdoPayload, true);
if (networkAddress === undefined) {
// all
await this.sendZdo(ZSpec.BLANK_EUI64, ZSpec.BroadcastAddress.DEFAULT, clusterId, zdoPayload, true);
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes. or combine in one block with 2 commands sendZdo - always send a broadcast, even if we connect it to some router
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not separating it would break what Z2M expects (from the dropdown in frontend).
123
=> device-only0
=> coordinator-onlyundefined
=> all (coordinator+broadcast)
So I'll push like that, let me know if that doesn't work out in zboss.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to join to the coordinator, I have to send 2 commands: one with the coordinator's address (0), and the second with the broadcast. only in this case, the joining of devices begins.
to join to the router, I sent only one command (without broadcast), but the device did not connect to it (the concentrator did not give permission to connect) and I haven't been able to beat it yet. maybe we should send another broadcast team, but I haven't checked yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm seeing a zb_nlme_permit_joining_request(duration)
in espressif zboss library. Could it be similar to emberznet, where there's a special function to open the network on the coordinator-only without going through a ZDO?
@@ -221,14 +214,25 @@ class ZStackAdapter extends Adapter { | |||
} | |||
|
|||
public async permitJoin(seconds: number, networkAddress?: number): Promise<void> { | |||
const addrmode = networkAddress === undefined ? 0x0f : 0x02; | |||
const dstaddr = networkAddress || 0xfffc; | |||
const clusterId = Zdo.ClusterId.PERMIT_JOINING_REQUEST; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self: check if this doesn't break https://github.com/Koenkk/Z-Stack-firmware/blob/7398d834eb3a790876c280293c4181da96cc7114/coordinator/Z-Stack_3.x.0/firmware.patch#L274 and https://github.com/Koenkk/Z-Stack-firmware/blob/7398d834eb3a790876c280293c4181da96cc7114/coordinator/Z-Stack_3.x.0/firmware.patch#L579
return result; | ||
} catch (error) { | ||
logger.debug(`Node descriptor request for '${networkAddress}' failed (${error}), retry`, NS); | ||
// Doing a route discovery after simple descriptor request fails makes it succeed sometimes. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This logic is lost now, I guess we need to move the logic up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The discovery bit? I made a note of that.
I'm thinking maybe adding a function to Adapter
for failed requests, something like this: onFailedRequest(ieeeAddress, networkAddress, profileId, clusterId)
, which might also allow to make the other various retry logic more generic in the future (upstream in Controller/Device instead of Adapter).
Thoughts?
I guess we could also have a discoverRoute
function in Adapter (which may not do anything if not needed). This is quite stack-specific, emberznet does this automatically for any frame via APS option for example.
I guess we could temporarily add it back in sendZdo
, I expect this would more or less do the same?
if (clusterId === Zdo.ClusterId.NODE_DESCRIPTOR_REQUEST) {
await this.discoverRoute(networkAddress);
}
await this.znp.requestZdo(clusterId, payload, waiter?.ID);
case Zdo.ClusterId.PERMIT_JOINING_REQUEST: { | ||
const finalPayload = Buffer.alloc(payload.length + 3); | ||
finalPayload.writeUInt8(ZSpec.BroadcastAddress[networkAddress] ? AddressMode.ADDR_BROADCAST : AddressMode.ADDR_16BIT, 0); | ||
// TODO: confirm zstack uses AddressMode.ADDR_16BIT + ZSpec.BroadcastAddress.DEFAULT to signal "coordinator-only" (assumed from previous code) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note to self; check this
@@ -308,6 +312,30 @@ class Znp extends events.EventEmitter { | |||
}); | |||
} | |||
|
|||
public requestZdo(clusterId: ZdoClusterId, payload: Buffer, waiterID?: number): Promise<void> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My expectation was that we don't use the ZNP specific ZDO commands but just AF_DATA_REQUEST
, wouldn't it be easier to use that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't know if the ZDO rsp payloads will match the same? Responses would still come in as AREQ/ZDO?
Probably have to rework the req payloads (looks like the network address would no longer be prefixing at least?).
Does it work for NETWORK_ADDRESS_REQUEST
too (just wondering since it has to use the ieee from the zdo payload and not dstaddr from data req)?
Something like this would work out-of-the-box?
// await this.znp.requestZdo(clusterId, payload, waiter?.ID);
await this.dataRequest(networkAddress, Zdo.ZDO_ENDPOINT, Zdo.ZDO_ENDPOINT, clusterId, Constants.AF.DEFAULT_RADIUS, payload, 15000);
Final goal is to remove the following functions from
Adapter
in favor of a genericsendZdo
with requests built and sent directly fromController
/Device
/Endpoint
:changeChannel
permitJoin
lqi
routingTable
nodeDescriptor
activeEndpoints
simpleDescriptor
bind
unbind
removeDevice
This should make the API far more robust against changes (by not requiring updates in every adapter) and offer full payloads to the upstream code (instead of the current limited set of properties), which could lead to a few new features.
Due to the sizeable overhaul required in some stacks, this PR will focus first on introducing the
sendZdo
function while keeping above functions in place until they can safely be removed (all adapters are required to have support before that can happen).A working example (albeit using an older implementation) of the full update for
ember
(as well as some tentative partial implementations in other stacks) can be found in this branch.TODO:
sendZdo
ember
zstack
(done, need testing)deconz
(done, need testing)zigate
(need testing)zboss
(need testing)ezsp
Zdo.Buffalo.readResponse
for ZDO framesember
zstack
deconz
(done, need testing)zigate
(need testing)zboss
(need testing)ezsp
TODO separate PR:
deviceAnnounce
andnetworkAddress
event fromAdapter
Adapter
& impl.Controller
ember
zstack
CC: @kirovilya @ChrisHae @G1K @devbis contributions/ideas on specific stacks welcome!