// SERVER <serverip> <serverpassword> <paranoidmode>
BOOL net_sms_handle_server(char *caller, char *command, char *arguments)
{
    BOOL serverq_result;

    par_set(PARAM_SERVERIP, arguments);
    arguments = net_sms_nextarg(arguments);
    if (arguments != NULL)
    {
        par_set(PARAM_SERVERPASS, arguments);
        arguments = net_sms_nextarg(arguments);
        if (arguments != NULL)
        {
            par_set(PARAM_PARANOID, arguments);
        }
    }
    serverq_result = net_sms_handle_serverq(caller, command, arguments);

    if (net_state != NET_STATE_DIAGMODE)
    {
        net_state_vint = NET_GPRS_RETRIES;
        net_state_enter(NET_STATE_NETINITP);
    }

    return serverq_result;
}
// GPRS <APN> <username> <password>
BOOL net_sms_handle_gprs(char *caller, char *command, char *arguments)
{
    BOOL gprsq_result;

    par_set(PARAM_GPRSAPN, arguments);
    arguments = net_sms_nextarg(arguments);
    if (arguments != NULL)
    {
        if ((arguments[0]=='-')&&(arguments[1]==0))
            par_set(PARAM_GPRSUSER, arguments+1);
        else
            par_set(PARAM_GPRSUSER, arguments);
        arguments = net_sms_nextarg(arguments);
        if (arguments != NULL)
        {
            if ((arguments[0]=='-')&&(arguments[1]==0))
                par_set(PARAM_GPRSPASS, arguments+1);
            else
                par_set(PARAM_GPRSPASS, arguments);
        }
    }
    gprsq_result = net_sms_handle_gprsq(caller, command, arguments);

    if (net_state != NET_STATE_DIAGMODE)
    {
        net_state_vint = NET_GPRS_RETRIES;
        net_state_enter(NET_STATE_NETINITP);
    }

    return gprsq_result;
}
// MODULE <vehicleid> <units> <notifications>
BOOL net_sms_handle_module(char *caller, char *command, char *arguments)
{
    BOOL moduleq_result;

    par_set(PARAM_VEHICLEID, arguments);
    arguments = net_sms_nextarg(arguments);
    if (arguments != NULL)
    {
        par_set(PARAM_MILESKM, arguments);
        arguments = net_sms_nextarg(arguments);
        if (arguments != NULL)
        {
            par_set(PARAM_NOTIFIES, arguments);
            arguments = net_sms_nextarg(arguments);
            if (arguments != NULL)
            {
                par_set(PARAM_VEHICLETYPE, arguments);
            }
        }
    }
    moduleq_result = net_sms_handle_moduleq(caller, command, arguments);
    vehicle_initialise();

    if (net_state != NET_STATE_DIAGMODE)
    {
        net_state_vint = NET_GPRS_RETRIES;
        net_state_enter(NET_STATE_NETINITP);
    }

    return moduleq_result;
}
// net_sms_checkauth: check SMS caller & first argument
//   according to auth mode
BOOL net_sms_checkauth(char authmode, char *caller, char **arguments)
{
    switch (authmode)
    {
    case '1':
        //   1:     the first argument must be the module password
        if (net_sms_checkpassarg(caller, *arguments) == 0)
            return FALSE;
        *arguments = net_sms_nextarg(*arguments); // Skip over the password
        break;
    case '2':
        //   2:     the caller must be the registered telephone
        if (net_sms_checkcaller(caller) == 0)
            return FALSE;
        break;
    case '3':
        //   3:     the caller must be the registered telephone, or first argument the module password
        if (net_sms_checkcaller(caller) == 0)
        {
            if (net_sms_checkpassarg(caller, *arguments)==0)
                return FALSE;
            *arguments = net_sms_nextarg(*arguments);
        }
        break;
    }

    return TRUE;
}
BOOL net_sms_handle_ap(char *caller, char *command, char *arguments)
{
    unsigned char d = 0;
    char *p = par_get(PARAM_MODULEPASS);

    while ((d < PARAM_MAX)&&(arguments != NULL))
    {
        if ((arguments[0]=='-')&&(arguments[1]==0))
            par_set(d++, arguments+1);
        else
            par_set(d++, arguments);
        arguments = net_sms_nextarg(arguments);
    }

    if (net_state != NET_STATE_DIAGMODE)
        net_state_enter(NET_STATE_FIRSTRUN);

    return FALSE;
}
BOOL net_sms_handle_feature(char *caller, char *command, char *arguments)
{
    unsigned char f;

    if (arguments == NULL) return FALSE;

    f = atoi(arguments);
    arguments = net_sms_nextarg(arguments);
    if ((f>=0)&&(f<FEATURES_MAX)&&(arguments != NULL))
    {
        sys_features[f] = atoi(arguments);
        if (f>=FEATURES_MAP_PARAM) // Top N features are persistent
            par_set(PARAM_FEATURE_S+(f-FEATURES_MAP_PARAM), arguments);
        if (f == FEATURE_CANWRITE) vehicle_initialise();
        net_send_sms_start(caller);
        net_puts_rom(NET_MSG_FEATURE);
        return TRUE;
    }
    return FALSE;
}
// Set charge mode (params: 0=standard, 1=storage,3=range,4=performance) and optional current limit
BOOL net_sms_handle_chargemode(char *caller, char *command, char *arguments)
{
    char mode[2];
    if (arguments == NULL) return FALSE;

    strupr(arguments);
    if (vehicle_fn_commandhandler != NULL)
    {
        mode[0] = '0' + string_to_mode(arguments);
        mode[1] = 0;
        vehicle_fn_commandhandler(FALSE, 10, mode);

        arguments = net_sms_nextarg(arguments);
        if (arguments != NULL)
            vehicle_fn_commandhandler(FALSE, 15, arguments);
    }

    net_send_sms_start(caller);
    net_puts_rom(NET_MSG_CHARGEMODE);
    return TRUE;
}
BOOL net_sms_handle_params(char *caller, char *command, char *arguments)
{
    unsigned char d = PARAM_MILESKM;

    while ((d < PARAM_MAX)&&(arguments != NULL))
    {
        if ((arguments[0]=='-')&&(arguments[1]==0))
            par_set(d++, arguments+1);
        else
            par_set(d++, arguments);
        arguments = net_sms_nextarg(arguments);
    }

    net_send_sms_start(caller);
    net_puts_rom(NET_MSG_PARAMS);
    net_send_sms_finish();

    vehicle_initialise();

    if (net_state != NET_STATE_DIAGMODE)
        net_state_enter(NET_STATE_DONETINIT);

    return FALSE;
}
char *net_prep_ctp(char *s, char *argument)
{
  int imStart = car_idealrange;
  int imTarget = 0;
  int pctTarget = 0;
  int cac100 = car_cac100;
  int volts = car_linevoltage;
  int amps = car_chargelimit;
  int degAmbient = car_ambient_temp;
  int chargemode = car_chargemode;
  int watts = 0;
  int imExpect;
  int minRemain;
  
  if (vehicle_fn_minutestocharge == NULL)
  {
    return stp_rom(s, "CTP not available");
  }
  
  // CTP 90s 150e 70% 16800w 160a 24d [S|R|P]
  while (argument != NULL)
  {
    int cch = strlen(argument);
    strupr(argument); // Convert argument to upper case
    if (cch > 0)
      {
      int val;
      char chType = argument[cch-1];
      argument[cch-1] = 0;
      if (cch > 1)
        {
        val = atoi(argument);
        switch (chType)
          {
          case 'S':
            imStart = val;
            break;
          case 'E':
            imTarget = val;
           break;
          case '%':
            pctTarget = val;
            break;
          case 'W':
            watts = val;
            break;
          case 'V':
            volts = val;
            break;
          case 'A':
            amps = val;
            break;
          case 'C':
            cac100 = val*100;
            break;
          case 'D':
            degAmbient = val;
            break;
          }
        }
      else
        {
        switch (chType)
          {
          case 'S':
            chargemode = 0;
            break;
          case 'R':
            chargemode = 3;
            break;
          case 'P':
            chargemode = 4;
            break;
          }
        }
      argument[cch-1] = chType;
      }
    argument = net_sms_nextarg(argument);
  }
  
  if (volts > 0 && amps > 0)
    watts = volts * amps;

  if (watts < 1000)
    {
    s = stp_rom(s, "no power level specified");
    return s;
    }
  
  minRemain = vehicle_fn_minutestocharge(chargemode, watts, imStart, imTarget, pctTarget, cac100, degAmbient, &imExpect);

  s = stp_i(s, NULL, imStart);
  s = stp_i(s, " to ", imExpect);
  s = stp_rom(s, " ideal mi\r");
  if (minRemain >= 0)
    {
    s = stp_i(s, NULL, minRemain/60);
    s = stp_ulp(s, ":", minRemain % 60, 2, '0');
    }
  else if (minRemain == -3)
    {
    s = stp_rom(s, "target reached");
    }
  else
    {
    s = stp_i(s, "error: ", minRemain);
    }

  return s;
}