Skip to content

Conversation

@InovelliUSA
Copy link
Contributor

This PR covers two issues. The first is @Nerivec

We noticed that the some changes in this commit: #9867

msg.data[c] changed to msg.data[Number.parseInt(c, 10)]

Caused some problems with the configuration value parsing for our devices.

The second is when the value of the attribute of an UINT8 is 255, it seems to reach the converter as NaN (or null?). There is a workaround in this PR for that issue as well, but I think this issue is new and am curious what might have caused it.

[2025-09-22 12:08:06] debug: zh:zstack:znp: <-- AREQ: AF - incomingMsg - {"groupid":0,"clusterid":64561,"srcaddr":27383,"srcendpoint":1,"dstendpoint":1,"wasbroadcast":0,"linkquality":116,"securityuse":0,"timestamp":5253037,"transseqnumber":0,"len":10,"data":{"type":"Buffer","data":[28,47,18,11,1,14,0,0,32,255]}}
[2025-09-22 12:08:06] debug: zh:controller: Received payload: clusterID=64561, address=27383, groupID=0, endpoint=1, destinationEndpoint=1, wasBroadcast=false, linkQuality=116, frame={"header":{"frameControl":{"frameType":0,"manufacturerSpecific":true,"direction":1,"disableDefaultResponse":true,"reservedBits":0},"manufacturerCode":4655,"transactionSequenceNumber":11,"commandIdentifier":1},"payload":[{"attrId":14,"status":0,"dataType":32,"attrData":null}],"command":{"ID":1,"name":"readRsp","parameters":[{"name":"attrId","type":33},{"name":"status","type":32},{"name":"dataType","type":32,"conditions":[{"type":"fieldEquals","field":"status","value":0}]},{"name":"attrData","type":1000,"conditions":[{"type":"fieldEquals","field":"status","value":0}]}]}}
[2025-09-22 12:08:06] debug: zh:zstack:unpi:parser: --- parseNext []
[2025-09-22 12:08:06] debug: z2m: Received Zigbee message from '0x94deb8fffef4cf5e', type 'readResponse', cluster 'manuSpecificInovelli', data '{"defaultLevelRemote":null}' from endpoint 1 with groupID 0

@Nerivec
Copy link
Collaborator

Nerivec commented Sep 22, 2025

About the Number.parse, these were added after the new typing was added (previously was not typed -any-, so values passed all checks even if wrong). Your changes appear to bypass the typing again (type-asserting as unknown).
I saw when I did that PR that Inovelli converters use a lot of dynamically-generated code, that clashes with Typescript a lot, makes it very hard to properly type everything.

See Koenkk/zigbee-herdsman#1503 about the ZCL non-values.
Meantime we'll add a temp fix (revert 0xff always returning NaN for UINT8) in ZH in next release (big PR won't be ready/tested). Should not include a fix here. CC: @Koenkk
Note: custom clusters will need to be updated after aforementioned PR to fit new enhancements.

@Koenkk
Copy link
Owner

Koenkk commented Sep 22, 2025

Will be fixed by Koenkk/zigbee-herdsman#1510

@Koenkk Koenkk closed this Sep 22, 2025
@rohankapoorcom
Copy link
Contributor

rohankapoorcom commented Sep 22, 2025

Doesn't the zigbee-hersman change only fix one issue?

This still needs fixing:

msg.data[c] changed to msg.data[Number.parseInt(c, 10)]

Caused some problems with the configuration value parsing for our devices.

This literally breaks all of the configuration values on these devices (and there's a huge number of them).

Rewriting the converter to be more type safe and less dynamic seems like a pretty big ask to fix this functionality.

@Koenkk Koenkk reopened this Sep 22, 2025
@Koenkk
Copy link
Owner

Koenkk commented Sep 22, 2025

@rohankapoorcom you are right, @InovelliUSA could you update the PR?

@InovelliUSA
Copy link
Contributor Author

I updated the PR to remove the code that was converting NaN to 255.

@Nerivec
Copy link
Collaborator

Nerivec commented Sep 22, 2025

Rewriting the converter to be more type safe and less dynamic seems like a pretty big ask to fix this functionality.

Agreed, not to fix this specifically, but overall, it would be better for the future. The new converters typing should allow pretty decent compile-time checks, avoid issues slipping through due to any-like typing (which is basically like writing plain JavaScript since it disables compile checks).
I remember having to type quite a few spots as any in the last two big typing refactors in Inovelli due to dynamic gen, but I also did not want to spend too much time on specific spots for things that could be improved later on. Let me know if you want some help, some pretty involved types are possible to fit more dynamic needs if necessary, though for smaller code chunks, it usually is faster to refactor the base a bit. Can find me on Discord like before.

@Koenkk we might want to check if other occurrences of this got through in the typing PR (cases where reduce or some other fn is dynamically parsing msg.data keys, and Number.parse should not have been used). I don't remember seeing much of this outside inovelli.ts during the PR, but just in case. Should be just the last few commits of the PR (post-typing fixes).

if (msg.type === "readResponse") {
return Object.keys(msg.data).reduce((p, c) => {
const key = splitValuesByEndpoint ? `${c}_${msg.endpoint.ID}` : c;
const obj = typeof msg.data === "string" ? JSON.parse(msg.data) : msg.data;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this alone should work:

const raw = (msg.data as Record<string | number, unknown>)[c];

(msg.data is either Record or Buffer)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I made that change.

@rohankapoorcom
Copy link
Contributor

Rewriting the converter to be more type safe and less dynamic seems like a pretty big ask to fix this functionality.

Agreed, not to fix this specifically, but overall, it would be better for the future. The new converters typing should allow pretty decent compile-time checks, avoid issues slipping through due to any-like typing (which is basically like writing plain JavaScript since it disables compile checks). I remember having to type quite a few spots as any in the last two big typing refactors in Inovelli due to dynamic gen, but I also did not want to spend too much time on specific spots for things that could be improved later on. Let me know if you want some help, some pretty involved types are possible to fit more dynamic needs if necessary, though for smaller code chunks, it usually is faster to refactor the base a bit. Can find me on Discord like before.

Sure, I think that's a good improvement to work towards. I am not a typescript expert though, do you maybe have a suggestion for where to start with this?

@Nerivec
Copy link
Collaborator

Nerivec commented Sep 23, 2025

@rohankapoorcom replied on Discord to avoid crowding here.

@Koenkk
Copy link
Owner

Koenkk commented Sep 23, 2025

@Nerivec I checked other occurrences of Object.keys(msg.data) but they look good to me.

Thanks @InovelliUSA !

@Koenkk Koenkk merged commit 8580fd5 into Koenkk:master Sep 23, 2025
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants