micropython / micropython-lib

Core Python libraries ported to MicroPython
Other
2.39k stars 994 forks source link

Why are these pairing parameters in aioble.security module private? #800

Open brianreinhold opened 8 months ago

brianreinhold commented 8 months ago

The aioble security module defines several very important constants needed for pairing such as

_IRQ_ENCRYPTION_UPDATE = const(28)
_IRQ_GET_SECRET = const(29)
_IRQ_SET_SECRET = const(30)
_IRQ_PASSKEY_ACTION = const(31)

_IO_CAPABILITY_DISPLAY_ONLY = const(0)
_IO_CAPABILITY_DISPLAY_YESNO = const(1)
_IO_CAPABILITY_KEYBOARD_ONLY = const(2)
_IO_CAPABILITY_NO_INPUT_OUTPUT = const(3)
_IO_CAPABILITY_KEYBOARD_DISPLAY = const(4)

_PASSKEY_ACTION_INPUT = const(2)
_PASSKEY_ACTION_DISP = const(3)
_PASSKEY_ACTION_NUMCMP = const(4)

I don't understand why they are private. These same constants are needed in any pairing request invoked by the application which means the application must redefine them. I think I can still use them though linters will complain and that would violate policy. Can't they be made public or did I miss something (my search did not find any public set of such constants).

projectgus commented 7 months ago

Hi @brianreinhold,

You're right this is a somewhat confusing pattern, especially compared to CPython code.

In fact, you can't use these from your application at all. There's a MicroPython optimisation where a variable that starts with _ and is assigned to a const() is evaluated at compile time. This is to save memory and code size (each constant otherwise needs to store the name for lookup, which adds up across hundreds or thousands of stored names.)

The recommended approach is to copy the constants you need into your program using the same optimisation trick. You can see this pattern in the aioble l2cap examples (for different constants). It isn't particularly elegant, but it saves a lot of size in the long run.

As far as I can see this pattern isn't explicitly documented for aioble. Suggest we keep this issue open until it's documented, or someone points out where I missed the existing documentation...

brianreinhold commented 7 months ago

@projectgus Thanks for the heads up. I did add them to my source (as I had no choice) but I will check out that optimization. I figured anything labeled 'const' would be placed in ROM and read from ROM with some optimized reference scheme.

projectgus commented 7 months ago

It is indeed (mostly) added to flash (ROM) storage, but the size in flash can still add up hence the additional optimisation on top of the first one which makes the variable "vanish" entirely.

brianreinhold commented 7 months ago

@projectgus Can these _constants only be called from a given file or a given package? I have a bunch of these Bluetooth constants that need to be called by several classes each in their own file.

projectgus commented 7 months ago

@brianreinhold That's correct, the only options are:

  1. Copy the same _NAME = const(n) constants into each source file. This has the smallest resource footprint (the constants effectively don't exist after the Python code is compiled.)
  2. Remove either the leading underscore or the const(). The constants are now "normal" and can be imported from other Python files, but they use up some additional resources (mostly size in flash).