@ -1,6 +1,7 @@
# include <Arduino.h>
# include "target.h"
# include <helpers/ArduinoHelpers.h>
# include <helpers/sensors/MicroNMEALocationProvider.h>
RAK4631Board board ;
@ -10,7 +11,8 @@ WRAPPER_CLASS radio_driver(radio, board);
VolatileRTCClock fallback_clock ;
AutoDiscoverRTCClock rtc_clock ( fallback_clock ) ;
SensorManager sensors ;
MicroNMEALocationProvider nmea = MicroNMEALocationProvider ( Wire ) ;
RAK4631SensorManager sensors = RAK4631SensorManager ( nmea ) ;
# ifdef DISPLAY_CLASS
DISPLAY_CLASS display ;
@ -20,6 +22,68 @@ SensorManager sensors;
# define LORA_CR 5
# endif
# ifdef MESH_DEBUG
uint32_t deviceOnline = 0x00 ;
void scanDevices ( TwoWire * w )
{
uint8_t err , addr ;
int nDevices = 0 ;
uint32_t start = 0 ;
Serial . println ( " Scanning I2C for Devices " ) ;
for ( addr = 1 ; addr < 127 ; addr + + ) {
start = millis ( ) ;
w - > beginTransmission ( addr ) ; delay ( 2 ) ;
err = w - > endTransmission ( ) ;
if ( err = = 0 ) {
nDevices + + ;
switch ( addr ) {
case 0x42 :
Serial . println ( " \t Found RAK12500 GPS Sensor " ) ;
deviceOnline | = RAK12500_ONLINE ;
break ;
default :
Serial . print ( " \t I2C device found at address 0x " ) ;
if ( addr < 16 ) {
Serial . print ( " 0 " ) ;
}
Serial . print ( addr , HEX ) ;
Serial . println ( " ! " ) ;
break ;
}
} else if ( err = = 4 ) {
Serial . print ( " Unknow error at address 0x " ) ;
if ( addr < 16 ) {
Serial . print ( " 0 " ) ;
}
Serial . println ( addr , HEX ) ;
}
}
if ( nDevices = = 0 )
Serial . println ( " No I2C devices found \n " ) ;
Serial . println ( " Scan for devices is complete. " ) ;
Serial . println ( " \n " ) ;
}
# endif
static bool readStringUntil ( Stream & s , char dest [ ] , size_t max_len , char term , unsigned int timeout_millis ) {
unsigned long timeout = millis ( ) + timeout_millis ;
char * dp = dest ;
while ( millis ( ) < timeout & & dp - dest < max_len - 1 ) {
if ( s . available ( ) ) {
char c = s . read ( ) ;
if ( c = = term ) break ;
* dp + + = c ; // append to dest[]
} else {
delay ( 1 ) ;
}
}
* dp = 0 ; // null terminator
return millis ( ) < timeout ; // false, if timed out
}
bool radio_init ( ) {
rtc_clock . begin ( Wire ) ;
@ -68,6 +132,136 @@ void radio_set_tx_power(uint8_t dbm) {
radio . setOutputPower ( dbm ) ;
}
void RAK4631SensorManager : : start_gps ( )
{
//function currently not used
gps_active = true ;
pinMode ( disStandbyPin , OUTPUT ) ;
digitalWrite ( disStandbyPin , 1 ) ;
MESH_DEBUG_PRINTLN ( " GPS should be on now " ) ;
}
void RAK4631SensorManager : : stop_gps ( )
{
//function currently not used
gps_active = false ;
pinMode ( disStandbyPin , OUTPUT ) ;
digitalWrite ( disStandbyPin , 0 ) ;
MESH_DEBUG_PRINTLN ( " GPS should be off now " ) ;
}
void RAK4631SensorManager : : sleep_gps ( ) {
gps_active = false ;
ublox_GNSS . powerSaveMode ( ) ;
MESH_DEBUG_PRINTLN ( " GPS should be sleeping now " ) ;
}
void RAK4631SensorManager : : wake_gps ( ) {
gps_active = true ;
ublox_GNSS . powerSaveMode ( false ) ;
MESH_DEBUG_PRINTLN ( " GPS should be waking now " ) ;
}
bool RAK4631SensorManager : : gpsIsAwake ( uint32_t ioPin ) {
int pinInitialState = 0 ;
//set initial waking state
pinMode ( ioPin , OUTPUT ) ;
digitalWrite ( ioPin , 0 ) ;
delay ( 1000 ) ;
digitalWrite ( ioPin , 1 ) ;
delay ( 1000 ) ;
if ( ublox_GNSS . begin ( Wire ) = = true ) {
MESH_DEBUG_PRINTLN ( " GPS init correctly and GPS is turned on " ) ;
ublox_GNSS . setI2COutput ( COM_TYPE_NMEA ) ;
ublox_GNSS . saveConfigSelective ( VAL_CFG_SUBSEC_IOPORT ) ;
disStandbyPin = ioPin ;
gps_active = true ;
gps_present = true ;
return true ;
}
else
MESH_DEBUG_PRINTLN ( " GPS failed to init on this IO pin... try the next " ) ;
//digitalWrite(ioPin,pinInitialState); //reset the IO pin to initial state
return false ;
}
bool RAK4631SensorManager : : begin ( ) {
# ifdef MESH_DEBUG
scanDevices ( & Wire ) ;
# endif
//search for the correct IO standby pin depending on socket used
if ( gpsIsAwake ( P_GPS_STANDBY_A ) ) {
MESH_DEBUG_PRINTLN ( " GPS is on socket A " ) ;
}
else if ( gpsIsAwake ( P_GPS_STANDBY_C ) ) {
MESH_DEBUG_PRINTLN ( " GPS is on socket C " ) ;
}
else if ( gpsIsAwake ( P_GPS_STANDBY_F ) ) {
MESH_DEBUG_PRINTLN ( " GPS is on socket F " ) ;
}
else {
MESH_DEBUG_PRINTLN ( " Error: No GPS found on sockets A, C or F " ) ;
gps_active = false ;
gps_present = false ;
return false ;
}
//Now that GPS is found and set up, set to sleep for initial state
stop_gps ( ) ;
}
bool RAK4631SensorManager : : querySensors ( uint8_t requester_permissions , CayenneLPP & telemetry ) {
if ( requester_permissions & TELEM_PERM_LOCATION & & gps_active ) { // does requester have permission?
telemetry . addGPS ( TELEM_CHANNEL_SELF , node_lat , node_lon , node_altitude ) ;
}
return true ;
}
void RAK4631SensorManager : : loop ( ) {
static long next_update = 0 ;
_nmea - > loop ( ) ;
if ( millis ( ) > next_update & & gps_active ) {
node_lat = ( double ) ublox_GNSS . getLatitude ( ) / 10000000. ;
node_lon = ( double ) ublox_GNSS . getLongitude ( ) / 10000000. ;
node_altitude = ( double ) ublox_GNSS . getAltitude ( ) / 1000. ;
MESH_DEBUG_PRINT ( " lat %f lon %f alt %f \r \n " , node_lat , node_lon , node_altitude ) ;
next_update = millis ( ) + 1000 ;
}
}
int RAK4631SensorManager : : getNumSettings ( ) const { return 1 ; } // just one supported: "gps" (power switch)
const char * RAK4631SensorManager : : getSettingName ( int i ) const {
return i = = 0 ? " gps " : NULL ;
}
const char * RAK4631SensorManager : : getSettingValue ( int i ) const {
if ( i = = 0 ) {
return gps_active ? " 1 " : " 0 " ;
}
return NULL ;
}
bool RAK4631SensorManager : : setSettingValue ( const char * name , const char * value ) {
if ( strcmp ( name , " gps " ) = = 0 ) {
if ( strcmp ( value , " 0 " ) = = 0 ) {
stop_gps ( ) ;
} else {
start_gps ( ) ;
}
return true ;
}
return false ; // not supported
}
mesh : : LocalIdentity radio_new_identity ( ) {
RadioNoiseListener rng ( radio ) ;
return mesh : : LocalIdentity ( & rng ) ; // create new random identity