toInt превращает любую букву в ноль :(

puhloschiok

✩✩✩✩✩✩✩
8 Окт 2018
22
0
Всем привет!
Есть необходимость превращать String в целое число, и в зависимости от значения числа выполнять определённую функцию.
Делаю так:

C++:
void myFunction (String result) {
    if (result.length() == 1) {
        int command = ((String)result).toInt();
        if (command == 0 || command == 1 || command == 2) {
          switch (command) {
            case 0:
              Serial.println("0");
              break;
            case 1:
             Serial.println("1");
             break;
            case 2:
              Serial.println("2");
              break;
            default:
              Serial.println("Error!");
          }
          correct = true;
        }
    } else {
        Serial.println("Error!");
    }
}

При этом, если result равен, допустим, «W», то при конвертации в целое число получаю command равный нулю.
Как мне получать только цифры из этой строки?
Заранее благодарю за помощь!

P.S.: хотел ещё добавить, что такое происходит лишь с латинскими буквами. Если result равен «Ё», то будет сообщение об ошибке.
 
Изменено:

puhloschiok

✩✩✩✩✩✩✩
8 Окт 2018
22
0
а какое число вы ожидали получить из w?
В том то и дело, что никакого. Может подскажете, как мне реальные цифры взять из этой строки?
Я думаю всё немного упрощается тем, что длина строки не должна превышать 1.
Если символов несколько, то она уже не проходит проверку. Но вот как «вычленить», так сказать, число из неё я не знаю :(
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@puhloschiok, пришлите полный код, нужно понимать какого вида строка может поступать в функцию
 

puhloschiok

✩✩✩✩✩✩✩
8 Окт 2018
22
0
@IamNikolay хорошо! Код ниже.
Прошу вас рассмотреть именно момент с этой переменной, а не код в целом. Код мой очень далёк от идела, хоть я и очень старался.
Делаю проект простой GSM-сигнализации для друга. Хотел после успешного тестирования выложить схему и код в комьюнити.
Весь код, отвечающий за отправку SMS я брал с сайта codius.ru и немного модифицировал под свои нужды. Остальное писал сам.

C++:
#include <avr/eeprom.h>
#include <SoftwareSerial.h>
const byte relay_pin = 2; // реле
const byte alert_pin = 3; // клеммы
const byte btn_pin = 4; // кнопка
const byte led_pin = 5; // светодиод
SoftwareSerial SIM800(8, 9); // RX и TX

// кнопка
bool bounce = 0;
bool btn = 1, oldBtn;
unsigned long past;
const uint32_t time = 1000;
bool flag = 0;
uint32_t past_flag = 0;

// клеммы
bool c_bounce = 0;
bool cmm = 1, oldCmm;
unsigned long c_past;
const uint32_t c_time = 1000;
bool c_flag = 0;
uint32_t c_past_flag = 0;

// сигнализация
bool mode = 0;
bool bttn_state = 0;
bool clemm_state = 0;
bool led_state = LOW;
bool signalizuha = 0;
bool mssg = 0;
bool mssg1 = 0;
bool remssg = 0;
long last_led_time = 0;
const uint32_t led_time = 1000;

// SMS texts
String mssg_ready = "Alarm state: Ready";
String mssg_on = "Alarm state: ON";
String mssg_off = "Alarm state: OFF";
String mssg_alarm = "ALERT!";
String mssg_dooropen = "Door state: Opened";
String mssg_already_done = "Already done!";
String mssg_incorrect =  "I don't understand :(";
String report_mssg = "";

// codius
String _response    = "";
long lastUpdate = millis();
long updatePeriod   = 60000;
String my_phone = "+7XXXXXXXXXX;

//--------------------------------- S E T U P ---------------------------------//

void setup() {
  SIM800.begin(9600);  
  sendATCommand("AT", true);
  sendATCommand("AT+CMGDA=\"DEL ALL\"", true);

  pinMode(relay_pin, OUTPUT);
  pinMode(alert_pin, INPUT_PULLUP);
  pinMode(btn_pin, INPUT_PULLUP);
  pinMode(led_pin, OUTPUT);

  lastUpdate = millis();

  // проверяем последнее состояние
  mode = eeprom_read_byte(0);
  signalizuha = eeprom_read_byte(1);
  mssg = eeprom_read_byte(2);
  mssg1 = eeprom_read_byte(3);
  bttn_state = eeprom_read_byte(5);
  digitalWrite(relay_pin, signalizuha);
}

//---------------------------------- SIM800 -----------------------------------//

String sendATCommand(String cmd, bool waiting) {
  String _resp = "";
  SIM800.println(cmd);
  if (waiting) {
    _resp = waitResponse();
  }
  return _resp;
}

String waitResponse() {
  String _resp = "";
  long _timeout = millis() + 10000;
  while (!SIM800.available() && millis() < _timeout)  {};
  if (SIM800.available()) {
    _resp = SIM800.readString();
  }
  return _resp;
}

bool hasmsg = false;

//---------------------------------- L O O P ----------------------------------//

void loop() {
  // режим ожидания (мигаем светодиодом)
  if (mode == 0) {
    if(millis() - last_led_time > led_time) {
      last_led_time = millis(); 
      if (led_state == LOW)
        led_state = HIGH;
      else
        led_state = LOW;
      digitalWrite(led_pin, led_state);
    }
  // режим готовности (светодиод не мигает)
  } else if (mode == 1) {
      digitalWrite(led_pin, HIGH);
  }

  // нажатие кнопки
  bool newBtn = digitalRead(btn_pin);
  if (!bounce && newBtn != btn) { bounce = 1; past = millis(); }
  if (bounce && millis() - past >= 10) {
    bounce = 0 ; oldBtn = btn; btn = newBtn;
    if (!btn && oldBtn) { flag = 1; past_flag = millis(); }
    // переходим в режим готовности (нажатие кнопки)
    if (!oldBtn && btn && flag && millis() - past_flag < time) {
      bttn_state = 1;
      eeprom_write_byte(5, 1);
      flag = 0;
      activate();
    }
  }
  
  // выключаем сигнализацию (удержание кнопки)
  if (flag && millis() - past_flag >= time) {
    flag = 0;
    deactivate();
  }

  // замыкание клемм
  bool newCmm = digitalRead(alert_pin);
  if (!c_bounce && newCmm != cmm) { c_bounce = 1; c_past = millis(); }
  if (c_bounce && millis() - c_past >= 1000) {
    c_bounce = 0 ; oldCmm = cmm; cmm = newCmm;
    if (!cmm && oldCmm) {
      c_flag = 1; c_past_flag = millis();
      // активируем сигнализацию
      clemm_state = 1;
      activate();
    } else if (cmm && !oldCmm) {
      clemm_state = 0;
      alarm();
    }
  }

  // Codius.ru
  if (lastUpdate + updatePeriod < millis() ) {
    do {
      _response = sendATCommand("AT+CMGL=\"REC UNREAD\",1", true);
      if (_response.indexOf("+CMGL: ") > -1) {
        int msgIndex = _response.substring(_response.indexOf("+CMGL: ") + 7, _response.indexOf("\"REC UNREAD\"", _response.indexOf("+CMGL: ")) - 1).toInt();
        char i = 0;
        do {
          i++;
          _response = sendATCommand("AT+CMGR=" + (String)msgIndex + ",1", true);
          _response.trim();
          if (_response.endsWith("OK")) {
            if (!hasmsg) hasmsg = true;
            sendATCommand("AT+CMGR=" + (String)msgIndex, true);
            sendATCommand("\n", true);
            parseSMS(_response);
            break;
          }
          else {
            sendATCommand("\n", true);
          }
        } while (i < 10);
        break;
      }
      else {
        lastUpdate = millis();
        if (hasmsg) {
          sendATCommand("AT+CMGDA=\"DEL READ\"", true);
          hasmsg = false;
        }
        break;
      }
    } while (1);
  }
  
  if (SIM800.available())   {
    _response = waitResponse();
    _response.trim();
    if (_response.indexOf("+CMTI:")>-1) {
      lastUpdate = millis() - updatePeriod;
    }
  }
}

void parseSMS(String msg) {
  String msgheader  = "";
  String msgbody    = "";
  String msgphone   = "";

  msg = msg.substring(msg.indexOf("+CMGR: "));
  msgheader = msg.substring(0, msg.indexOf("\r"));
  msgbody = msg.substring(msgheader.length() + 2);
  msgbody = msgbody.substring(0, msgbody.lastIndexOf("OK"));
  msgbody.trim();

  int firstIndex = msgheader.indexOf("\",\"") + 3;
  int secondIndex = msgheader.indexOf("\",\"", firstIndex);
  msgphone = msgheader.substring(firstIndex, secondIndex);

  if (msgphone.length() > 6 && my_phone.indexOf(msgphone) > -1) {
    setAlertState(msgbody);
  }
}

void activate() {
  if (clemm_state == 1 && bttn_state == 1) {
    mode = 1;
    eeprom_write_byte(0, 1);
    if (mssg1 == 0) {
      mssg1 = 1;
      eeprom_write_byte(3, 1);
      sendSMS(my_phone, mssg_on);
    }
  } else if (clemm_state == 0 && bttn_state == 1) {
    mode = 1;
    eeprom_write_byte(0, 1);
  }
}

void deactivate() {
  if (mode == 1) {
      mode = 0;
      mssg = 0;
      mssg1 = 0;
      signalizuha = 0;
      bttn_state = 0;
      digitalWrite(relay_pin, 0);
      eeprom_write_byte(0, 0);
      eeprom_write_byte(1, 0);
      eeprom_write_byte(2, 0);
      eeprom_write_byte(3, 0);
      eeprom_write_byte(5, 0);
      sendSMS(my_phone, mssg_off);
    }
}

void alarm() {
  // врубаем сирену!
  if (mode == 1) {
    digitalWrite(relay_pin, 1);
    signalizuha = 1;
    eeprom_write_byte(1, 1);
    if (mssg == 0) {
      mssg = 1;
      eeprom_write_byte(2, 1);
      sendSMS(my_phone, mssg_alarm);
    }
  }
}

void report() {
  if (mode == 0 && clemm_state == 1) {
    report_mssg = "Alarm OFF, Door Closed";
  } else if (mode == 0 && clemm_state == 0) {
    report_mssg = "Alarm OFF, Door Opened";
  } else if (mode == 1 && clemm_state == 1) {
    report_mssg = "Alarm ON, Door Closed";
  } else if (mode == 1 && clemm_state == 0) {
    report_mssg = "ALERT! Alarm ON, Door Opened";
  }
  sendSMS(my_phone, report_mssg);
}

void setAlertState (String result) {
  bool correct = false;
  if (result.length() == 1) {
    int command = ((String)result).toInt();
    if (command == 0 || command == 1 || command == 2) {
      switch (command) {
        case 0:
          if (mode == 1) {
            deactivate();
          } else {
            sendSMS(my_phone, mssg_already_done);
          }
          break;
        case 1:
          if (clemm_state == 1 && mode == 0) {
            bttn_state = 1;
            eeprom_write_byte(5, 1);
            activate();
          } else if (clemm_state == 0 && mode == 0) {
            sendSMS(my_phone, mssg_dooropen);
          } else if (mode == 1) {
            sendSMS(my_phone, mssg_already_done);
          }
          break;
        case 2:
          report();
          break;
        default:
          sendSMS(my_phone, mssg_incorrect);
      }
      correct = true;
    }
  }
  if (!correct) {
    sendSMS(my_phone, mssg_incorrect);
  }
}

void sendSMS(String phone, String message)
{
  sendATCommand("AT+CMGS=\"" + phone + "\"", true);
  sendATCommand(message + "\r\n" + (String)((char)26), true);
}
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@puhloschiok, судя по коду - приходит смс, затем она урезается и отправляется в функцию. А что именно приходит в смс - не написали. Нужна именно строка с которой вы хотите получить число.
Например:
строка вида: kod5412
нужно получить: 5412
 

puhloschiok

✩✩✩✩✩✩✩
8 Окт 2018
22
0
@IamNikolay строка простая, всего три варианта рабочих команд: 0 (выключение), 1 (включение) или 2 (запрос статуса).
Если я отправляю «W», то команда выполняться не должна, а выполняется «0».
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@puhloschiok, тогда нужно проверять пришла цифра или нет, делается это функцией isDigit(). Или можно при нуле ничего неделать, а выключение перенести на 3.Смотрите сами, как вам проще будет
 
  • Лойс +1
Реакции: puhloschiok

puhloschiok

✩✩✩✩✩✩✩
8 Окт 2018
22
0
@IamNikolay ух-ты! Про isDigit() никогда не слышал. Спасибо! Попробую сейчас.

Так. К сожалению String нельзя обработать с помощью isDigit().

cannot convert 'String' to 'int' for argument '1' to 'boolean isDigit(int)'
 

IamNikolay

★★★✩✩✩✩
15 Янв 2020
820
175
@puhloschiok, функция не так работает, переменная, поступающая в функцию, должна быть типа char.
вот пример:
C++:
if (isDigit(переменная)) {
  Serial.println("переменная цифра");
    //тут добавляете переключатель по 0 1 2
}
else {
  Serial.println("переменная не цифра");
}
если же у вас преобразование нигде не делается, и хотите отправлять String, то преобразование можно сделать в самой функции, тогда будет выглядеть так:
C++:
if (isDigit(переменная.charAt(0))) {
  Serial.println("переменная цифра");
    //тут добавляете переключатель по 0 1 2
}
else {
  Serial.println("переменная не цифра");
}
 
Изменено:
  • Лойс +1
Реакции: puhloschiok

puhloschiok

✩✩✩✩✩✩✩
8 Окт 2018
22
0
@IamNikolay спасибо огромное! Теперь работает без сбоев :)
Протестирую какое-то продолжительное время и поделюсь проектом.