The high-level analyzer feature and measurements is a fantastic feature, absolute game changer and very easy to get started with.
With that in mind, I would like to suggest making the API a bit more structured by using classes and enums rather than dicts and strings (of course, if you guys intend to stick with the dictionaries, it would not be too hard for someone in the community to make a wrapper library to provide this kind of functionality).
What I mean is that get_capabilities
returns a Capabilities
object rather than a dict, set_settings
receives a UserSettings
object rather than a dict, and so on.
Furthermore, strings that can only have a fixed set of values (such as the “type” field for I2C frames) are represented by some sort of enumerated type.
Benefits:
- IDEs like PyCharm will show warnings if there is a typo or if the wrong types are used
- IDEs like PyCharm will provide autocomplete
- You can look up the source code to see what kind of data types are expected
- Class docstrings can be extracted by e.g. Sphinx and used to generate up-to-date documentation
Downsides:
- Increased code size in some cases (probably mostly the example cases)
- Examples might look a bit more intimidating to some users
Below is an example of how a HLA implementation might look with such an API (names are just made up of course).
import saleae_logic_high_level_analyzers as hla
class MyAnalyzer(object):
def get_capabilities(self) -> hla.Capabilities:
return hla.Capabilities(
settings=[
hla.UserInput(
label="First setting label",
type=hla.String()
),
hla.UserInput(
label="Another setting",
type=hla.Number(minimum=1e-6, maximum=1e4)
),
hla.UserInput(
label="Pick one of the following",
type=hla.Choices(["Option A", "Option B"])
),
]
)
def set_settings(self, settings: hla.UserSettings) -> hla.AnalyzerSettings:
self.setting_1 = settings.get("First setting label", default="")
self.setting_2 = settings.get("Another setting", default=1)
self.setting_3 = settings.get("Pick one of the following", default="Option A")
return hla.AnalyzerSettings(
result_types=[
hla.ResultType(
type="error",
format="Error!"
),
hla.ResultType(
type="my_type",
format="Field 1: {{data.field_1}}, Field 2: {{data.field_2}}"
),
]
)
def decode(self, input_data: hla.I2CFrame):
if input_data.type == hla.I2CStart:
self.handle_start(input_data)
elif input_data.type == hla.I2CStop:
self.handle_stop(input_data)
elif input_data.type == hla.I2CAddress:
self.handle_address(input_data)
elif input_data.type == hla.I2CData:
self.handle_data(input_data)
return self.get_frames()
# ... definitions for handle_start, handle_stop, handle_address, handle_data, get_frames etc