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

Device status - Battery % #501

Open
KE6MTO opened this issue Dec 18, 2019 · 11 comments
Open

Device status - Battery % #501

KE6MTO opened this issue Dec 18, 2019 · 11 comments
Assignees

Comments

@KE6MTO
Copy link

KE6MTO commented Dec 18, 2019

Are Device Status requests supported? Looking for support for the back-end server to request the node status, in particular the battery %. So far haven't been able to identify if that is support and if so how to feed it the battery %. It would be great to get that function as base of this code base.

@terrillmoore
Copy link
Member

The MAC command is supported in v3.0.99; but there's no API yet for feeding battery %. Generally if you look in the LoRaWAN 1.0.3 spec, grab a name and search for it (using VS Code, at least), you'll find. The name in LoRaWAN 1.0.3 is DevStatusReq. Visual Studio Code is the way to deal with this code: CTRL+SHIFT+f => then fill in DevStatusReq: bingo, line 915 (in my sandbox) of lmic.c.

There is a routine os_getBattLevel() which is supposed to be overridable, but in practice cannot be overridden without editing code. (None of the os_xxx routines are easily replaced; this is a mismatch between library architecture and Arduino use case.) Of course, you have the source, and you can edit locally while waiting for this to be fixed in a better way.

@terrillmoore terrillmoore self-assigned this Dec 21, 2019
@cyberman54
Copy link

I would also be interested in a way / API to override os_getBattLevel(), since i am already set with my own gettBattLevel().

@cyberman54
Copy link

@terrillmoore But why does the override work with other functions used in lmic.c, like os_getDevEui ?

@terrillmoore
Copy link
Member

@cyberman54 Because os_getDevEui() doesn't have any definition at all in the base library. The code just calls it and you must provide the function.

If we did that with os_getBattLevel() (by removing the definition from the core library), we would break backward compatibility. In addition, as we found with the fixed names for onEvent(), this is not a very convenient approach as systems grow.

There are non-portable ways of letting you override the hal functions using GNU weak definitions. But that won't work with other compilers. (Also, the STM32 BSP does exactly this with many of its functions, and it's kind of ugly in practice.)

Some possible portable approaches:

  1. We could add an API to register a callback for the battery (so the LMIC calls out to your code when it needs data).
  2. We could add a byte (LMIC.batteryLevel) that (if zero) is transmitted as the "unknown battery value" (0xFF, I believe); and then add an API LMIC_setBatteryLevel() that stuffs your current value into the byte. (People very low on code space could stuff the byte directly.)
  3. We could add a virtual method in HalConfiguration_t -- then you could override it. (But this is kind of awkward and a lot of typing for a simple concept.)

Number 2 seems the best to me at the moment. Apps often check the battery level anyway, occasionally, in order to know whether to flash lights, etc. But I don't have a strong opinion.

@cyberman54
Copy link

Yes, option 2 sounds most reasonable for this.

@nielskoot
Copy link

I needed support for the battery level and implemented option 2, also added a define so devices on external power can just set that special value without a need to call a function. Tested it on 2 different devices, one on external power and one on batteries. Will send a pull request.

@cyberman54
Copy link

@nielskoot i will by happe to test it as soon as the PR is ready.

@altishchenko
Copy link

Good for loops, but what do you think about a callback? It does sound a bit more complicated from a simple app perspective, but I think it is more natural to make one call to register a callback, then feeding battery level values into LMIC constantly.

@altishchenko
Copy link

On the second thought you can even combine the whole story in one, where callback gets priority:

#if !defined(os_getBattLevel)
u1_t os_getBattLevel (void) {
 #if LMIC_ENABLE_user_events
    if (LMIC.client.battLevelCb != NULL)
        return LMIC.client.battLevelCb(LMIC.client.battLevelUserData);
 #endif
    return LMIC.batteryLevel;
}
#endif

@nielskoot
Copy link

@altishchenko that is good way to support callback too. I can include it, however don't use the user events myself. Anyone who could test this?

@altishchenko
Copy link

I use it myself in our code. My variant is completely event driven, published PR #560 here.

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

No branches or pull requests

5 participants