semuconsulting / pyubx2

Python library for parsing and generating UBX GPS/GNSS protocol messages.
BSD 3-Clause "New" or "Revised" License
165 stars 65 forks source link

Getting ACK/NAK response from command #94

Closed n8ur closed 1 year ago

n8ur commented 1 year ago

This may be a bug, or it may be my lack of knowledge. I want to send a command to the receiver and find out whether it was ACK'd or NAK'd. The application is getting HPPOSLLH where the receiver supports it, or POSLLH where it doesn't. I can't find a straightforward way to do this.

Here is an example trying to set HPPOSLLH on a neo-m8t receiver that doesn't support it, then setting POSLLH where that succeeded:

<UBX(ACK-NAK, clsID=CFG, msgID=CFG-MSG)> {'_immutable': True, '_mode': 0, '_payload': b'\x06\x01', '_length': b'\x02\x00', '_checksum': b'\x0e3', '_parsebf': 1, '_scaling': 1, '_ubxClass': b'\x05', '_ubxID': b'\x00', 'clsID': 6, 'msgID': 1}

<UBX(ACK-ACK, clsID=CFG, msgID=CFG-MSG)> {'_immutable': True, '_mode': 0, '_payload': b'\x06\x01', '_length': b'\x02\x00', '_checksum': b'\x0f8', '_parsebf': 1, '_scaling': 1, '_ubxClass': b'\x05', '_ubxID': b'\x01', 'clsID': 6, 'msgID': 1}

Note that the ubxID value changes but the clsID value does not. And both the clsID and msgID values are 1 higher than their _ubx equivalents -- a picket-fence error, or am I misunderstanding the intention?

Is there a bug in the values of clsID and msgID in this case? And is there a more elegant way of telling whether a command was ACK'd or NAK'd than looking for the object attributes?

The environment is Linux Mint 21 and Python 3.10, with pyuxb2 installed via pip3 today.

Thanks!

semuadmin commented 1 year ago

Hi @n8ur ,

The messages look correct to me.

The public clsID and msgID attributes in the ACK-ACK or ACK-NAK responses represent the message class they're acknowledging, which in both cases is a CFG-MSG message (clsID 0x06, msgID 0x01). The private _ubxClass and _ubxID attributes represent the class and id of the acknowledgement itself, which is 0x05,0x01 for ACK-ACK and 0x05,0x00 for ACK-NAK.

The UBX protocol does not provide for explicit synchronous responses to input commands (e.g., via a unique transaction ID). Monitoring the ACK response is not an absolutely foolproof way of assessing whether a given command worked or not but it is the only option available, so your approach is valid - send a CFG-MSG to set NAV-HPPOSLLH; if you get an ACK-NAK, send a further CFG-MSG to set NAV-POSLLH instead.

As an aside, it should never be necessary to view both private and public attributes in a UBXMessage object. The public attributes contain all the data you need, and pyubx's __str__ method renders these in a human-readable format.

Hope this helps.

n8ur commented 1 year ago

Thanks for getting back to me so quickly! I understand now about the expected behavior.

In my application the only thing I need to check (so far) is the attempt to set HPPOS, and I can do that at a stage in the config before there's much other data coming back from the receiver, so hopefully that will be reliable enough.

Thanks again!

semuadmin commented 1 year ago

Entirely your choice, but you can just as easily check for an ACK-NAK response to a CFG-MSG command using:

if parsed_data.identity == "ACK-NAK":
    if parsed_data.clsID == 0x06 and parsed_data.msgID == 0x01:  # CFG-MSG
      ...

This should work fine as long as you're not sending other CFG-MSG commands in quick succession.

Are you happy for me to close this issue?

n8ur commented 1 year ago

Thanks for the tip to parsed_data.identity attribute. I'm a novice with python objects and I just discovered the dir() function to list all the attributes. The vars() function did not include the identity attribute, and that's where I was looking before. Problem solved, issue can be closed, and thanks again.