Получить строку из массива байт. Как?

Constx7
Offline
Зарегистрирован: 25.03.2018

Доброго времени суток, Дамы и Господа. Работаю с Shield SIM900 китайский на Али

Получаю СМС в массив байт так:

  if (sim900.available())     //Если порт готов
    while(sim900.available())
    {
      buffer[count++]=sim900.read();//Собираю массив байт
      Serial.println(count);//Слежу за заполнением массива
      if(count >= bufsize) { //Если больше 256
        Serial.println("##bufsize##");//Массив заполнен
        SMSString = String((char*)buffer);//Пишу в строку. Буду дальше работать со строкой
        Serial.println(SMSString);//Пишу в порт
        Serial.println("КОНЕЦ");
        clearBufferArray();//Очистим буфер
        count = 0;// Счетчик в 0
        break;// Вышли
      }
    }
  }

Получаю результат:

##bufsize##

КОНЕЦ

Вопрос: Где строка? Помогите найти, что не так? Спасибо.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

весь код где?

зачем два буфера buffer  SMSString?

clearBufferArray() - ?

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Код нужно давать рабочий, чтобы можно было запустить, а не огрызки.

СМС-то по-русски поди?

Constx7
Offline
Зарегистрирован: 25.03.2018

SMSString - это переменная типа String, buffer - массив байт. clearBufferArray - функция, которая в цикле присваивает элементам buffer значение null. Это, в общем-то, весь код и есть. Там еще есть много лирики к чтению СМС никак не относящаяся. Весь код завтра спрошу обязательно.

Constx7
Offline
Зарегистрирован: 25.03.2018

Завтра код спрошу. Но здесь почти все. СМС только на латинице. Да, еще - если пишу буфер через write, то строка пишется корректно. Serial.write(buffer, count); Но мне надо работать со строкой типа String.

Constx7
Offline
Зарегистрирован: 25.03.2018

Весь код:

#include <SoftwareSerial.h>
SoftwareSerial  sim900(9, 8);//Назначаем пины
const int bufsize=256;
byte buffer[bufsize];//Будем записывать побайтно
int count=0;//Счетчик
String SMSString; //Строка SMS-сообщения

void setup(void) {
  //starting sim900
  sim900.begin(9600);  
  delay(300);             
  sim900.print("AT+CMGF=1\r");//Текстовый режим
  delay(300);
  sim900.print("AT+IFC=1, 1\r");//программный контроль потока передачи данных
  delay(300);
  sim900.print("AT+CPBS=\"SM\"\r");//?
  delay(300);
  sim900.print("AT+CNMI=1,2,2,1,0\r");//Формат сообщения
  delay(500);
  Serial.begin(9600);

  powerUpOrDown();//Запустим SIM900
}

void get_buffer()
{
  if (sim900.available())         
  {
    while(sim900.available()) 
    {
      buffer[count++]=sim900.read();
      Serial.println(count);
      if(count >= bufsize) {
        Serial.println("##bufsize##");
        SMSString = String((char*)buffer);
        Serial.println(SMSString);
        //Serial.write(buffer, count);
        Serial.println("КОНЕЦ");
        //SMSString = String((char*)buffer);        
        //if (SMSString.indexOf("+CMT")>=0){
        //Serial.println(SMSString);          
        //}
        clearBufferArray();//Очистим буфер
        count = 0;
        break;
      }
    }
  }
}

void clearBufferArray()              // function to clear buffer array
{
  for (int i=0; i<count;i++)
    { buffer[i]=NULL;}                  // clear all index of array with command NULL
}

void loop(){
  get_buffer();//Читаем СМС с SIM900
}

//Включение SIM900
void powerUpOrDown()
{
 pinMode(4, OUTPUT);
 digitalWrite(4,LOW);
 delay(1000);
 digitalWrite(4,HIGH);
 delay(2000);
 digitalWrite(4,LOW);
 delay(3000);
}

 

Constx7
Offline
Зарегистрирован: 25.03.2018

Привел весь код

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

для очистки буфера достаточно в первый байт ноль записать

зачем двойное преобразование 35 и 36 строка для вывода в монитор? разве 37 строка не выводит информацию?

да и вообще работа со String рано или поздно выйдет вам боком - переполнением памяти, тут рядом тема была - зависал модуль при приеме СМС или USSD 

DenSyo
Offline
Зарегистрирован: 13.01.2017

buffer[count++]=sim900.read() - с учетом того, что count изначально равен 0 всегда порождает пустую строку, т.к. массив начинает заполняться только со второго символа оставляя первый нулевым (вообще принято считать, что это не точно)) инициализируйте count=-1, если конструкцию не менять...

5N62V
Offline
Зарегистрирован: 25.02.2016

Constx7 пишет:

Вопрос: Где строка? Помогите найти, что не так? Спасибо.

Я бы на Вашем месте для начала проконтролировал содержимое массива buffer. А был ли мальчик, так сказать :)

Constx7
Offline
Зарегистрирован: 25.03.2018

По буферу, спасибо за информацию.

37-я выводит. Не в выводе дело. Я хочу продолжить работу со строкой String и ее удобными функциями поиска по строке, конкатенации и замены и прочье.

Вообще у меня задача получить длинную СМС (до 160 символов латиницей) и разбить ее на значения, полученные значения некой настройки присвоить переменным Ардуино. Например, "v=123/v1=17/v2=45/v3=79175555555..." и так далее.

Constx7
Offline
Зарегистрирован: 25.03.2018

Спасибо за совет, попробую. Для меня, если честно, оказалось откровением, что массив заполняется со второго символа. Что же лежит тогда в первом? Просто нуль? Зачем? Где почитать?)

Constx7
Offline
Зарегистрирован: 25.03.2018

Проверял 37-ой строкой:

Serial.write(buffer, count);

Строка с сообщением есть.

DenSyo
Offline
Зарегистрирован: 13.01.2017

конечно оно есть. но первый элмент массива char имеет значение 0, при передаче такого массива в String получаем пустую строку

Constx7
Offline
Зарегистрирован: 25.03.2018

Понял. Спасибо. Буду проверять что у меня в первой ячейке массива.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

В конец буфера никто не пишет 0, а для операции в строке 35 он там нужен. Так что заполняйте буфер не до конца, а в конец ручками 0 приписывайте.

Надеюсь, Вы знаете, что делаете, требуя полного заполнения буфера. Хвост (не кратный 255) Вы обязательно потеряете, т.к. она будет ждать пока буфер не заполнится и ничего не делать.

Constx7
Offline
Зарегистрирован: 25.03.2018

ЕвгенийП пишет:

В конец буфера никто не пишет 0, а для операции в строке 35 он там нужен. Так что заполняйте буфер не до конца, а в конец ручками 0 приписывайте.

Надеюсь, Вы знаете, что делаете, требуя полного заполнения буфера. Хвост (не кратный 255) Вы обязательно потеряете, т.к. она будет ждать пока буфер не заполнится и ничего не делать.

Да, я понимаю, спасибо. Это тест. Мне сейчас важно строку получить или плюнуть и работать с байтами и символами.

Constx7
Offline
Зарегистрирован: 25.03.2018

DenSyo пишет:

buffer[count++]=sim900.read() - с учетом того, что count изначально равен 0 всегда порождает пустую строку, т.к. массив начинает заполняться только со второго символа оставляя первый нулевым (вообще принято считать, что это не точно)) инициализируйте count=-1, если конструкцию не менять...

Вот спасибо! Все в точку. У меня в первом байте был 0. Установил count в -1 и, вуаля, моя строка.) Счастлив без меры, а потратил на это 3 дня!))

##bufsize##
⸮⸮⸮⸮⸮
RDY
 
+CFUN: 1
 
+CPIN: READY
 
Call Ready
 
+CMT: "+79226684371","","18/04/24,13:21:43+12"
Proba SMS 1 
 
+CMT: "+79226684371","","18/04/24,13:21:56+12"
Proba SMS 2
 
+CMT: "+79226684371","","18/04/24,13:22:06+12"
Proba SMS 3
 
+CMT: "+79
КОНЕЦ
 
Господа, всем спасибо, всем пока. При встрече, с меня пиво.)
 
ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Чего-то я недопонял в этой жизни. Ну, да, ладно.

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

DenSyo пишет:

конечно оно есть. но первый элмент массива char имеет значение 0

глупость какая :(

это где написано?

ЗЫ. Впрочем можно не отвечать, главное что у ТС все работает.

DenSyo
Offline
Зарегистрирован: 13.01.2017

andycat пишет:

ЗЫ. Впрочем можно не отвечать, главное что у ТС все работает.

все-таки отвечу, что бы у наших читателей в будущем было меньше вопросов. как уже говорилось ранее, алгоритм формирования строки начинал заполнение масива char со второго символа. почему первый элемент получает значение 0? я говорил, что принято считать что это не точно, т.е. нельзя полагаться что после включения устройства в памяти будут содержаться одни нули, хотя современная память в силу технических особенностей имеет обнуленное состояние после включения, предполагается, что там хаос и прграмма должна сама инициализировать начальные состояния данных. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DenSyo пишет:
принято считать что это не точно, т.е. нельзя полагаться что после включения устройства в памяти будут содержаться одни нули

Почему не точно? Статическая инициализация прописана в стандарте языка. Так что никакого отношения к апппаратным особенностям работы памяти это не имеет.

DenSyo
Offline
Зарегистрирован: 13.01.2017

был уверен, что делает это именно компилятор, но обсуждение с коллегами на перекуре заставило меня изменить свое мнение) а память не тронутая компилятором будет иметь хаотичное состояние или все же какое-то определенное? 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Я не знаю, что за память нетронутая компилятором - куча, что ли? Про неё стандарт ничего не говорит. Там чётко прописано лишь то, что все статические переменные (включая глобальные) перед выполнением программы должны быть проинициализированы нулями.

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

DenSyo пишет:

buffer[count++]=sim900.read() - с учетом того, что count изначально равен 0 всегда порождает пустую строку, т.к. массив начинает заполняться только со второго символа оставляя первый нулевым (вообще принято считать, что это не точно)) инициализируйте count=-1, если конструкцию не менять...

Почему со второго начинает заполняться когда используется постфиксная операция? При count равном 0 массив начнет заполняться с нулевого элемента. Или я совсем уже ничего не понимаю и пора на пенсию.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Penni пишет:
Или я совсем уже ничего не понимаю и пора на пенсию.
См. мой пост #18 :))))

andycat
andycat аватар
Offline
Зарегистрирован: 07.09.2017

Я так понимаю    DenSyo сложно представляет как строка в памяти лежит и книжки не читает или вспомнил Pascal где первый байт размер строки хранит.

Хрень короче пишет, хотя может я и не прав, но почему я обнуляю строку записав в первый байт 0 и вообще строку с первого байта пишу - что я делаю не так ? 

DenSyo
Offline
Зарегистрирован: 13.01.2017

andycat, Penni, ЕвгенийП
ребята! вы слишком много курите! (с) вместо того, что бы проверить код, строчите на форуме...
какой порядок выполнения этого выражения: buffer[count++]= ? 
вы серьезно думаете, что вначале присвоение, а потом инкремент? это в каких книжках так?

andycat пишет:
- что я делаю не так ? 

хамите беспочвенно. совершенно непонимая о чем идет речь. остальные сами поймут, вам разжую. имеем массив buffer[256] изначально = {0,0,0,0,0,0,0....} все значения 0, так компилятор инициализирует объявленные переменные. есть счетчик текущей длины массива изначально заданный 0 и сбрасываемый до 0 перед чтением каждой новой строки. начинаем в цикле посимвольно запонять строку: buffer[0++]=, где 0++ == 1 в языке си который мы тут обсуждаем. элементу массива buffer[0] никогда не будет присваиваться значение пока не инициализируем счетчик как -1. вот и имеем всегда первым символом строки символ с кодом 0. т.е. пустую строку. 

andycat пишет:
Впрочем можно не отвечать, главное что у ТС все работает.

вот от этого мне особенно грустно((( озвучена проблема, предложено решение, выполнен тест который подтверждает правильность решения. а чё, почему, неважно. работает, да и ладно. пока не научитесь критически мыслить наши ракеты не полетят. 

Penni
Penni аватар
Offline
Зарегистрирован: 18.01.2015

DenSyo пишет:

andycat, Penni, ЕвгенийП
ребята! вы слишком много курите! (с) вместо того, что бы проверить код, строчите на форуме...
какой порядок выполнения этого выражения: buffer[count++]= ? 
вы серьезно думаете, что вначале присвоение, а потом инкремент? это в каких книжках так?

Проверяйте на здоровье, а ссылки на книжки где это написано кидали выше

const int bufsize=256;
byte buffer[bufsize];
int count=0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  for(byte j=10; j<20; j++)
    buffer[count++] = j;
  Serial.println(buffer[0]);
  Serial.println(buffer[1]);
  Serial.println(buffer[2]);
  Serial.println(buffer[3]);
  Serial.println(buffer[4]);
  Serial.println(buffer[5]);
  delay(10000);
}

 И вот совсем школьный пример

int count = 0;

void setup()
{
  Serial.begin(9600);
}

void loop()
{
  Serial.println(count++);
  delay(1000);
}

Что в первом лупе напечатает принтл?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DenSyo пишет:

какой порядок выполнения этого выражения: buffer[count++]= ? 
вы серьезно думаете, что вначале присвоение, а потом инкремент? 

Нет, конечно! Мы вообще не думаем об этом, мы это твёрдо знаем - сначала присваивание, а потом инкремент.

DenSyo пишет:

это в каких книжках так?

Во всех без исключения.

Вы, кстати, хоть одну прочитали? Нет? Так нафига ж: "в присутствии двух людей с университетским образованием позволяете себе с развязностью совершенно невыносимой подавать какие-то советы космического масштаба и космической же глупости"?

И вообще, по поводу Вашего поста, опять же из Булгакова:

"Вы, Шариков, чепуху говорите и возмутительнее всего то, что говорите её безапелляционно и уверенно."

Честно говоря, когда ребята начали подшучивать и я их поддержал, я ожидал Вашего вопроса: "что не так?" и даже подготовил ответ. Но Вы решили не задавать вопросов, а поучить нас расчитывать ракеты. ну, что ж, в добрый путь! Удачи :)

DenSyo
Offline
Зарегистрирован: 13.01.2017

да, лопухнулся((( 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

DenSyo пишет:

да, лопухнулся((( 

Очень рад, что признали - респект и уважуха!  Добро пожаловать к нам!

С подготовленным ответом, вечером, ладно, сейчас на работу пора.