2021-06-27 10:56:28 -07:00
# include "configuration.h"
2022-02-27 00:18:35 -08:00
# include "AdminModule.h"
2021-02-26 15:34:00 +08:00
# include "Channels.h"
2021-02-21 14:03:44 +08:00
# include "MeshService.h"
# include "NodeDB.h"
# include "Router.h"
# include "main.h"
2021-03-18 19:09:31 +08:00
# ifdef PORTDUINO
# include "unistd.h"
# endif
2022-02-27 02:21:02 -08:00
AdminModule * adminModule ;
2021-02-21 14:03:44 +08:00
2021-08-01 11:21:36 -07:00
/// A special reserved string to indicate strings we can not share with external nodes. We will use this 'reserved' word instead.
/// Also, to make setting work correctly, if someone tries to set a string to this reserved value we assume they don't really want a change.
static const char * secretReserved = " sekrit " ;
/// If buf is !empty, change it to secret
static void hideSecret ( char * buf ) {
if ( * buf ) {
strcpy ( buf , secretReserved ) ;
}
}
/// If buf is the reserved secret word, replace the buffer with currentVal
static void writeSecret ( char * buf , const char * currentVal ) {
if ( strcmp ( buf , secretReserved ) = = 0 ) {
strcpy ( buf , currentVal ) ;
}
}
2022-02-27 02:21:02 -08:00
void AdminModule : : handleGetChannel ( const MeshPacket & req , uint32_t channelIndex )
2021-03-11 10:01:57 +08:00
{
if ( req . decoded . want_response ) {
2021-02-26 15:34:00 +08:00
// We create the reply here
AdminMessage r = AdminMessage_init_default ;
r . get_channel_response = channels . getByIndex ( channelIndex ) ;
2021-02-26 20:10:41 +08:00
r . which_variant = AdminMessage_get_channel_response_tag ;
2021-04-06 10:34:23 +08:00
myReply = allocDataProtobuf ( r ) ;
2021-02-26 15:34:00 +08:00
}
}
2022-02-27 02:21:02 -08:00
void AdminModule : : handleGetRadio ( const MeshPacket & req )
2021-02-26 15:34:00 +08:00
{
if ( req . decoded . want_response ) {
// We create the reply here
AdminMessage r = AdminMessage_init_default ;
2021-03-11 13:02:00 +08:00
r . get_radio_response = radioConfig ;
2021-03-07 09:51:17 +08:00
2021-05-03 14:46:30 +08:00
// NOTE: The phone app needs to know the ls_secs & phone_timeout value so it can properly expect sleep behavior.
2021-03-07 09:51:17 +08:00
// So even if we internally use 0 to represent 'use default' we still need to send the value we are
// using to the app (so that even old phone apps work with new device loads).
r . get_radio_response . preferences . ls_secs = getPref_ls_secs ( ) ;
2021-05-03 14:46:30 +08:00
r . get_radio_response . preferences . phone_timeout_secs = getPref_phone_timeout_secs ( ) ;
2021-08-01 11:21:36 -07:00
// hideSecret(r.get_radio_response.preferences.wifi_ssid); // hmm - leave public for now, because only minimally private and useful for users to know current provisioning)
hideSecret ( r . get_radio_response . preferences . wifi_password ) ;
2021-03-07 09:51:17 +08:00
2021-02-26 20:10:41 +08:00
r . which_variant = AdminMessage_get_radio_response_tag ;
2021-04-06 10:34:23 +08:00
myReply = allocDataProtobuf ( r ) ;
2021-02-26 15:34:00 +08:00
}
}
2022-02-27 02:21:02 -08:00
bool AdminModule : : handleReceivedProtobuf ( const MeshPacket & mp , AdminMessage * r )
2021-02-21 14:03:44 +08:00
{
2022-02-21 06:29:15 +01:00
// if handled == false, then let others look at this message also if they want
bool handled = false ;
2021-02-21 14:03:44 +08:00
assert ( r ) ;
2021-02-26 15:34:00 +08:00
switch ( r - > which_variant ) {
case AdminMessage_set_owner_tag :
DEBUG_MSG ( " Client is setting owner \n " ) ;
handleSetOwner ( r - > set_owner ) ;
break ;
case AdminMessage_set_radio_tag :
DEBUG_MSG ( " Client is setting radio \n " ) ;
handleSetRadio ( r - > set_radio ) ;
break ;
case AdminMessage_set_channel_tag :
2021-03-19 23:40:41 +08:00
DEBUG_MSG ( " Client is setting channel %d \n " , r - > set_channel . index ) ;
2021-04-03 14:56:46 +08:00
if ( r - > set_channel . index < 0 | | r - > set_channel . index > = ( int ) MAX_NUM_CHANNELS )
2021-04-06 10:34:23 +08:00
myReply = allocErrorResponse ( Routing_Error_BAD_REQUEST , & mp ) ;
2021-03-23 11:44:51 +08:00
else
handleSetChannel ( r - > set_channel ) ;
2021-02-26 15:34:00 +08:00
break ;
2021-03-23 11:44:51 +08:00
case AdminMessage_get_channel_request_tag : {
uint32_t i = r - > get_channel_request - 1 ;
2021-03-23 11:54:53 +08:00
DEBUG_MSG ( " Client is getting channel %u \n " , i ) ;
2021-03-23 11:44:51 +08:00
if ( i > = MAX_NUM_CHANNELS )
2021-04-06 10:34:23 +08:00
myReply = allocErrorResponse ( Routing_Error_BAD_REQUEST , & mp ) ;
2021-03-23 11:44:51 +08:00
else
handleGetChannel ( mp , i ) ;
2021-02-26 15:34:00 +08:00
break ;
2021-03-23 11:44:51 +08:00
}
2021-02-26 15:34:00 +08:00
case AdminMessage_get_radio_request_tag :
DEBUG_MSG ( " Client is getting radio \n " ) ;
handleGetRadio ( mp ) ;
break ;
2021-03-27 10:19:59 +08:00
case AdminMessage_reboot_seconds_tag : {
int32_t s = r - > reboot_seconds ;
DEBUG_MSG ( " Rebooting in %d seconds \n " , s ) ;
rebootAtMsec = ( s < 0 ) ? 0 : ( millis ( ) + s * 1000 ) ;
break ;
}
2022-01-21 15:03:26 -06:00
case AdminMessage_shutdown_seconds_tag : {
int32_t s = r - > shutdown_seconds ;
DEBUG_MSG ( " Shutdown in %d seconds \n " , s ) ;
shutdownAtMsec = ( s < 0 ) ? 0 : ( millis ( ) + s * 1000 ) ;
break ;
}
2021-03-27 10:19:59 +08:00
2021-03-18 19:09:31 +08:00
# ifdef PORTDUINO
case AdminMessage_exit_simulator_tag :
2021-03-18 19:40:00 +08:00
DEBUG_MSG ( " Exiting simulator \n " ) ;
2021-03-18 19:09:31 +08:00
_exit ( 0 ) ;
break ;
# endif
2021-02-26 15:34:00 +08:00
default :
2022-02-21 06:29:15 +01:00
AdminMessage response = AdminMessage_init_default ;
2022-03-09 19:01:43 +11:00
AdminMessageHandleResult handleResult = MeshModule : : handleAdminMessageForAllPlugins ( mp , r , & response ) ;
2022-02-21 06:29:15 +01:00
if ( handleResult = = AdminMessageHandleResult : : HANDLED_WITH_RESPONSE )
{
myReply = allocDataProtobuf ( response ) ;
}
else if ( mp . decoded . want_response )
{
DEBUG_MSG ( " We did not responded to a request that wanted a respond. req.variant=%d \n " , r - > which_variant ) ;
}
else if ( handleResult ! = AdminMessageHandleResult : : HANDLED )
{
// Probably a message sent by us or sent to our local node. FIXME, we should avoid scanning these messages
DEBUG_MSG ( " Ignoring nonrelevant admin %d \n " , r - > which_variant ) ;
}
2021-02-26 15:34:00 +08:00
break ;
2021-02-21 14:03:44 +08:00
}
2022-02-21 06:29:15 +01:00
return handled ;
2021-02-21 14:03:44 +08:00
}
2022-02-27 02:21:02 -08:00
void AdminModule : : handleSetOwner ( const User & o )
2021-02-21 14:03:44 +08:00
{
int changed = 0 ;
if ( * o . long_name ) {
changed | = strcmp ( owner . long_name , o . long_name ) ;
strcpy ( owner . long_name , o . long_name ) ;
}
if ( * o . short_name ) {
changed | = strcmp ( owner . short_name , o . short_name ) ;
strcpy ( owner . short_name , o . short_name ) ;
}
if ( * o . id ) {
changed | = strcmp ( owner . id , o . id ) ;
strcpy ( owner . id , o . id ) ;
}
2021-04-10 11:39:13 +08:00
if ( owner . is_licensed ! = o . is_licensed ) {
2021-11-02 13:27:56 +00:00
changed = 1 ;
2021-04-10 11:39:13 +08:00
owner . is_licensed = o . is_licensed ;
}
2021-02-21 14:03:44 +08:00
2021-11-02 13:27:56 +00:00
if ( ( ! changed | | o . team ) & & ( owner . team ! = o . team ) ) {
changed = 1 ;
owner . team = o . team ;
}
2021-02-21 14:03:44 +08:00
if ( changed ) // If nothing really changed, don't broadcast on the network or write to flash
service . reloadOwner ( ) ;
}
2022-02-27 02:21:02 -08:00
void AdminModule : : handleSetChannel ( const Channel & cc )
2021-02-21 14:03:44 +08:00
{
channels . setChannel ( cc ) ;
2021-03-11 18:29:47 +08:00
// Just update and save the channels - no need to update the radio for ! primary channel changes
if ( cc . index = = 0 ) {
// FIXME, this updates the user preferences also, which isn't needed - we really just want to notify on configChanged
service . reloadConfig ( ) ;
2021-03-19 15:24:24 +08:00
} else {
2021-03-11 18:29:47 +08:00
channels . onConfigChanged ( ) ; // tell the radios about this change
nodeDB . saveChannelsToDisk ( ) ;
}
2021-02-21 14:03:44 +08:00
}
2022-02-27 02:21:02 -08:00
void AdminModule : : handleSetRadio ( RadioConfig & r )
2021-02-21 14:03:44 +08:00
{
2021-08-01 11:21:36 -07:00
writeSecret ( r . preferences . wifi_password , radioConfig . preferences . wifi_password ) ;
2021-02-21 14:03:44 +08:00
radioConfig = r ;
2021-03-11 18:29:47 +08:00
service . reloadConfig ( ) ;
2021-02-21 14:03:44 +08:00
}
2022-03-09 19:01:43 +11:00
AdminModule : : AdminModule ( ) : ProtobufModule ( " Admin " , PortNum_ADMIN_APP , AdminMessage_fields )
2021-02-26 15:34:00 +08:00
{
2021-03-11 10:01:57 +08:00
// restrict to the admin channel for rx
2021-03-13 13:14:27 +08:00
boundChannel = Channels : : adminChannel ;
2021-02-21 14:03:44 +08:00
}