Skip to content
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

*_GET-message types confuse parseUBXPayload #5

Open
thasti opened this issue Oct 19, 2018 · 1 comment
Open

*_GET-message types confuse parseUBXPayload #5

thasti opened this issue Oct 19, 2018 · 1 comment
Assignees
Labels

Comments

@thasti
Copy link

thasti commented Oct 19, 2018

I wrote a simple script trying to query some settings of a receiver. However, after sending (for example) a UBX.CFG.PRT_GET message, the UBXManager fails to parse the response correctly.

I traced this error down already to some extent:
The root cause is that both UBX.CFG.PRT_GET and UBX.CFG.PRT have the same _id. When initMessageClass initially fills the _lookup-dictionary of UBX.CFG, duplicate keys are partially discarded, only the last key-value is stored, leaving only UBX.CFG.PRT_GET in there.

When parseUBXPayload then tries to look up the subclass from the _lookup-dictionary with .get(msgid), only UBX.CFG.PRT_GET is present.

The issue can be worked around by changing the order of PRT and PRT_GET in the source code (same applies for TP5 and TP5_GET, but explicitly excluding _GET-messages from the list of parseable messages might be a better idea.

Interesting side effect: The Exception message wrongly states "Message not fully consumed while parsing a UBX.CFG.TP5_GET!", even though this should read UBX.CFG.PRT_GET. I did not track down what causes this, but it threw me off first while looking for the root cause of the problem.

Test code:

import serial
import time
import UBX
from UBXManager import UBXManager

ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=None)
manager = UBXManager(ser, debug=True)
manager.start()

# query port settings - response triggers bug
time.sleep(1)
prt = UBX.CFG.PRT_GET(b'\x01')
manager.send(prt.serialize())
@oscarmezyk
Copy link

oscarmezyk commented Oct 29, 2018

@thasti If I understand correctly the "addGet" decorator creates a "Get" version of UBXMessage with given _class and _id, so the best way is to pass payload to the UBXMessage init. I managed to do it with:

  1. extended version of addGet decorator, that inits Get class with payload
def addGetExt(cls):
    """Decorator that adds a Get function to the subclass."""
    class Get(UBXMessage):
        def __init__(self,payload=b''):
            # this only works because class and module have the same name!
            _class = eval(cls.__module__)._class
            UBXMessage.__init__(self, _class, cls._id, payload)
    setattr(cls, "Get", Get)
    return cls

#usage
msg = UBX.CFG.PRT.Get(payload=b'\x03')

  1. modified decorator to accept payload - this is rather static solution, but works for specific configuration
def addGetPayload(payload):
    def addGet(cls):
        """Decorator that adds a Get function to the subclass."""
        class Get(UBXMessage):
            def __init__(self):
                # this only works because class and module have the same name!
                _class = eval(cls.__module__)._class
                UBXMessage.__init__(self, _class, cls._id, payload)
        setattr(cls, "Get", Get)
        return cls
    return addGet

this decorator then is used:

@addGetPayload(payload=b'\x03')
class PRT:

In both cases you'd need to modify decorators for classes in UBX, remove _GET subclasses and import new decorator functions in UBX/CFG (see import lines). Please see if it works for you.

@mayeranalytics mayeranalytics self-assigned this Feb 28, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants