Skip to content

A little bit more flexible support for battery level indication #560

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

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -319,6 +319,16 @@ Disable or enable support for device network-time requests (LoRaWAN MAC request

If disabled, stub routines are provided that will return failure (so you don't need conditional compiles in client code).

### Battery level report

To support battery level indication in the MAC `DevStatusAns` messages you can either use an `int LMIC_registerBattLevelCb(lmic_battlevel_cb_t *pBattLevelCb, void *pUserData)` call to register a callback function of the form `typedef u1_t lmic_battlevel_cb_t(void *pUserData);`, if you have `LMIC_ENABLE_user_events` enabled, or call `LMIC_setBattLevel(u1_t battLevel)` periodically.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you have LMIC_ENABLE_user_events enabled

The default in lmic is to support user events. So the above text maybe better should read "if you don not have disabaled ..."

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite possibly. I am using this library in a custom-built platform specific setup, so I am not that aware of the standard defaults :)


By default, the value supplied in the `DevStatusAns` messages will be `MCMD_DEVS_BATT_NOINFO`, but you can change this behaviour for the externally powered devices by adding to your project config file the following line:

```
#define LMIC_MCMD_DEVS_BATT_DEFAULT MCMD_DEVS_EXT_POWER
```

### Rarely changed variables

The remaining variables are rarely used, but we list them here for completeness.
Expand Down
5 changes: 5 additions & 0 deletions src/lmic/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,11 @@
// DEPRECATED([email protected]); replaced by LMIC.noRXIQinversion (dynamic). Don't define this.
//#define DISABLE_INVERT_IQ_ON_RX

// Use MCMD_DEVS_EXT_POWER value here for externally powered devices
#if !defined(LMIC_MCMD_DEVS_BATT_DEFAULT)
# define LMIC_MCMD_DEVS_BATT_DEFAULT MCMD_DEVS_BATT_NOINFO
#endif

// This allows choosing between multiple included AES implementations.
// Make sure exactly one of these is uncommented.
//
Expand Down
31 changes: 29 additions & 2 deletions src/lmic/lmic.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,11 @@ void os_wmsbf4 (xref2u1_t buf, u4_t v) {

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

Expand Down Expand Up @@ -564,6 +568,16 @@ int LMIC_registerEventCb(lmic_event_cb_t *pEventCb, void *pUserData) {
#endif // ! LMIC_ENABLE_user_events
}

int LMIC_registerBattLevelCb(lmic_battlevel_cb_t *pBattLevelCb, void *pUserData) {
#if LMIC_ENABLE_user_events
LMIC.client.battLevelCb = pBattLevelCb;
LMIC.client.battLevelUserData = pUserData;
return 1;
#else // ! LMIC_ENABLE_user_events
return 0;
#endif // ! LMIC_ENABLE_user_events
}

static void runReset (xref2osjob_t osjob) {
LMIC_API_PARAMETER(osjob);

Expand Down Expand Up @@ -929,7 +943,7 @@ scan_mac_cmds(
// LMIC.snr is SNR times 4, convert to real SNR; rounding towards zero.
const int snr = (LMIC.snr + 2) / 4;
// per [1.02] 5.5. the margin is the SNR.
LMIC.devAnsMargin = (u1_t)(0b00111111 & (snr <= -32 ? -32 : snr >= 31 ? 31 : snr));
LMIC.devAnsMargin = (u1_t)(0x3F & (snr <= -32 ? -32 : snr >= 31 ? 31 : snr));

response_fit = put_mac_uplink_byte3(MCMD_DevStatusAns, os_getBattLevel(), LMIC.devAnsMargin);
break;
Expand Down Expand Up @@ -2785,6 +2799,7 @@ void LMIC_reset (void) {
LMIC.ping.dr = DR_PING; // ditto
LMIC.ping.intvExp = 0xFF;
#endif // !DISABLE_PING
LMIC.batteryLevel = LMIC_MCMD_DEVS_BATT_DEFAULT;

LMICbandplan_resetDefaultChannels();
DO_DEVDB(LMIC.devaddr, devaddr);
Expand Down Expand Up @@ -3024,6 +3039,18 @@ void LMIC_setClockError(u2_t error) {
LMIC.client.clockError = error;
}

// Sets the battery level returned in MAC Command DevStatusAns.
// Available defines in lorabase.h:
// MCMD_DEVS_EXT_POWER = 0x00, // external power supply
// MCMD_DEVS_BATT_MIN = 0x01, // min battery value
// MCMD_DEVS_BATT_MAX = 0xFE, // max battery value
// MCMD_DEVS_BATT_NOINFO = 0xFF, // unknown battery level
// When setting the battery level calculate the applicable
// value from MCMD_DEVS_BATT_MIN to MCMD_DEVS_BATT_MAX.
void LMIC_setBattLevel(u1_t battLevel) {
LMIC.batteryLevel = battLevel;
}

// \brief return the uplink sequence number for the next transmission.
// This simple getter returns the uplink sequence number maintained by the LMIC engine.
// The caller should store the value and restore it (see LMIC_setSeqnoUp) on
Expand Down
6 changes: 6 additions & 0 deletions src/lmic/lmic.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,7 @@ enum {
typedef void LMIC_ABI_STD lmic_rxmessage_cb_t(void *pUserData, uint8_t port, const uint8_t *pMessage, size_t nMessage);
typedef void LMIC_ABI_STD lmic_txmessage_cb_t(void *pUserData, int fSuccess);
typedef void LMIC_ABI_STD lmic_event_cb_t(void *pUserData, ev_t e);
typedef u1_t LMIC_ABI_STD lmic_battlevel_cb_t(void *pUserData);

// network time request callback function
// defined unconditionally, because APIs and types can't change based on config.
Expand Down Expand Up @@ -425,6 +426,8 @@ struct lmic_client_data_s {
void *rxMessageUserData; //! data for rxMessageCb
lmic_txmessage_cb_t *txMessageCb; //! transmit-complete message handler; reset on each tx complete.
void *txMessageUserData; //! data for txMessageCb.
lmic_battlevel_cb_t *battLevelCb; //! user-supplied callback function to get battery level for Dev
void *battLevelUserData; //! data for battLevelCb.
#endif // LMIC_ENABLE_user_events

/* next we have things that are (u)int32_t */
Expand Down Expand Up @@ -600,6 +603,7 @@ struct lmic_t {

u1_t margin;
s1_t devAnsMargin; // SNR value between -32 and 31 (inclusive) for the last successfully received DevStatusReq command
u1_t batteryLevel; // Battery level returned in devStatusAns messages
u1_t adrEnabled;
u1_t moreData; // NWK has more data pending
#if LMIC_ENABLE_TxParamSetupReq
Expand Down Expand Up @@ -694,6 +698,7 @@ void LMIC_setPingable (u1_t intvExp);
void LMIC_setSession (u4_t netid, devaddr_t devaddr, xref2u1_t nwkKey, xref2u1_t artKey);
void LMIC_setLinkCheckMode (bit_t enabled);
void LMIC_setClockError(u2_t error);
void LMIC_setBattLevel(u1_t battLevel);

u4_t LMIC_getSeqnoUp (void);
u4_t LMIC_setSeqnoUp (u4_t);
Expand All @@ -704,6 +709,7 @@ int LMIC_getNetworkTimeReference(lmic_time_reference_t *pReference);

int LMIC_registerRxMessageCb(lmic_rxmessage_cb_t *pRxMessageCb, void *pUserData);
int LMIC_registerEventCb(lmic_event_cb_t *pEventCb, void *pUserData);
int LMIC_registerBattLevelCb(lmic_battlevel_cb_t *pBattLevelCb, void *pUserData);

// APIs for client half of compliance.
typedef u1_t lmic_compliance_rx_action_t;
Expand Down