Как можно красивее офрмить эти if'ы

alexbmd
Offline
Зарегистрирован: 15.01.2016

как можно красивее(взрослее) сделать эту логику ?
c while красивее но не хочу т.к. может зависнуть ожидая какогото ответа
обработчик ошибок еще не дописал

bool isModemRegistered(){
	if (isModemAlive()){
		Serial1.print("ATH\r");
		if (Serial1.find("OK")){
			Serial1.print("AT+CPAS\r");
			if (Serial1.find("0")){
				Serial1.print("AT+CREG?\r");
				if (Serial1.find("0,1")) return true: return false;
			} else return false;
		} else return false;
	} else return false;
}
bool isModemBootup(){
	if (!isModemAlive()){
		if (!(PINC & (1 << 6))) delay(5000);  //delay if shutdown routine is initiated
		//(PINC & (1 << 6)) >> 6
		PORTC &= ~(1 << 6);  //boot pin low
		delay(300);  //time by datasheet
		PORTC |= (1 << 6);  //boot pin high
		delay(5000);  //delay if it actually is a reset
		if (Serial1.find("+PBREADY")) return true: return false;
	} else return true;
}
bool isModemAlive(){
	Serial1.print("AT\r");
	if (Serial1.find("OK")) return true: return false;
}
void modemOn(){
	if (isModemBootup()){
		if (isModemRegistered()) error no error yes;
	} else error yes;
}

т.к. на самом деле мы не знаем физического состояния внешнего устройства то попытался максимально (на сколько хватило мне соображалки) сделать защиту от дурака/случайного выключения/зависания. т.к. нет while и код после обработки ошибки, побежит по второму/третьему кругу и даже несмотряна то что мы пытаемся только включить внешнее устройство, фактически мы можем его и ресетнуть  и если с подключением /питанием все ок, то в конце концов должно заработать.

sadman41
Offline
Зарегистрирован: 19.10.2016

Красивее оформить - инвертировать условие и сразу сделать return false. А вот как умнее сделать - надобно мозг наморщить.

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

В строчке 8 - дичь написана, там нет тернарного оператора, компилироваться не должно. В строчке 21 - також. Или это - просто псевдокод?

По поводу красивости: всё субъективно. Красиво - это когда код форматирован по одному из стандартов. Как правильно замечено выше - инверсия условия сильно сократит кол-во ненужных else.

Функции типа 

bool isModemAlive(){
	Serial1.print("AT\r");
	if (Serial1.find("OK")) return true: return false;
}

можно переписать короче:

bool isModemAlive(){
	Serial1.print("AT\r");
	return !Serial1.find("OK");
}

В целом же, исходя из опыта: блокирующая работа с GSM-модемом в реальном более-менее серьёзном проекте - неприемлема, от слова "совсем": ответ на некоторые команды по даташиту может занимать до 80 секунд. Что в это время делать остальному функционалу прошивки - курить бамбук? Единственное верное пмсм решение - это неблокирующий конечный автомат с состояниями, вещь не самая тривиальная к реализации, в своё время убил на отладку этого дела больше месяца.

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

А что, прежде, чем задавать вопрос о красоте, просто добиться успешной компиляции ... не судьба?

Нет, не зря я Вас в соседней теме медалью наградил! Вы достойны! :)))

alexbmd
Offline
Зарегистрирован: 15.01.2016

DIYMan так вроде у меня не блокирующая я поэтому и убрал while(!serial.find()); ?
а почему return (!)Serial1.find("OK"); когда вроде надо return Serial1.find("OK"); ?

"инвертировать условие и сразу сделать return false" 

	if (!isModemAlive()) return false;
	else {
		Serial1.print("ATH\r");
		if (Serial1.find("OK")){
			Serial1.print("AT+CPAS\r");
			if (Serial1.find("0")){
				Serial1.print("AT+CREG?\r");
				return Serial1.find("0,1")
			} else return false;
		} else return false;
	}

вы это имели ввиду?

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

alexbmd пишет:

DIYMan так вроде у меня не блокирующая я поэтому и убрал while(!serial.find()); ?
а почему return (!)Serial1.find("OK"); когда вроде надо return Serial1.find("OK"); ?

"инвертировать условие и сразу сделать return false" 

	if (!isModemAlive()) return false;
	else {
		Serial1.print("ATH\r");
		if (Serial1.find("OK")){
			Serial1.print("AT+CPAS\r");
			if (Serial1.find("0")){
				Serial1.print("AT+CREG?\r");
				return Serial1.find("0,1")
			} else return false;
		} else return false;
	}

вы это имели ввиду?

У вас - именно блокирующая, потому что Serial.find не сразу возвращает управление, а по таймауту. К тому же - такой подход не обеспечит правильного реагирования на многие команды: как я писал выше - ответ на некоторые команды может занимать много секунд.

Почему !Serial.find - описка, если имелась в виду функция isModemAlive. В целом же, повторюсь ещё раз: ваш подход - не очень, на простом примере: вы послали команду AT, а в этот момент в порт упала SMS, до прихода ответа OK. С вашим кодом - СМС будет пропущена.

Инвертирование условия - это:

1. Ваш пример:

if(condition) return true;
else return false;

2. Инвертирование условия:

if(!condition) return false;

Второй вариант - короче и читабельней.

По поводу синтаксиса и пр.: очень советую почитать учебник по С++ - многие вопросы отпадут сами собой.

alexbmd
Offline
Зарегистрирован: 15.01.2016
bool isModemRegistered() {
  if (isModemAlive()) {
    Serial1.print("ATH\r");
    if (Serial1.find("OK")) {
      Serial1.print("AT+CPAS\r");
      if (Serial1.find("0")) {
        Serial1.print("AT+CREG?\r");
        return (Serial1.find("0,1")) ? true : false;
      } else return false;
    } else return false;
  } else return false;
}
bool isModemBootup() {
  if (!isModemAlive()) {
    if (!(PINC & (1 << 6))) delay(5000);  //delay if shutdown routine is initiated
    //(PINC & (1 << 6)) >> 6
    PORTC &= ~(1 << 6);  //boot pin low
    delay(300);  //time by datasheet
    PORTC |= (1 << 6);  //boot pin high
    delay(5000);  //delay if it actually is a reset
    return (Serial1.find("+PBREADY")) ? true : false;
  } else return true;
}
bool isModemAlive() {
  Serial1.print("AT\r");
  return (Serial1.find("OK")) ? true : false;
}
void modemOn() {
  if (isModemBootup()) {
    error = (isModemRegistered()) ? 0 : 1;
  } else error = 1;
}

Евгений теперь компилируется

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

DIYMan пишет:

Инвертирование условия - это:

1. Ваш пример:

if(condition) return true;
else return false;

2. Инвертирование условия:

if(!condition) return false;

Второй вариант - короче и читабельней.

исходный пример:

return condition;

не?

если инвертировать:

return !condition;

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

andriano пишет:

DIYMan пишет:

Инвертирование условия - это:

1. Ваш пример:

if(condition) return true;
else return false;

2. Инвертирование условия:

if(!condition) return false;

Второй вариант - короче и читабельней.

исходный пример:

return condition;

не?

если инвертировать:

return !condition;

Зависит от задачи и условий. В моём случае можно добавить дополнительные операторы:

if(!condition) {
error("HALT!");
return false;
}

В случае простого возврата return !condition - так не выйдет. К тому же - ТС нужен условный возврат, а не безусловный - это видно из логики кода. Поэтому именно if.

alexbmd
Offline
Зарегистрирован: 15.01.2016

DIYMan  да я заметил что ответ иногда вообще не приходит, ну или ему надо было много больше время. я послал другую команду и ответ пришел сразу на вторую а на первую получилось так и не пришел. да find он таймаут меня это как раз избавляет от while.

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

с инвертированием кажется понял, уже завтра попробую. спасибо

kolyn
Offline
Зарегистрирован: 18.01.2019

DIYMan пишет:

В целом же, исходя из опыта: блокирующая работа с GSM-модемом в реальном более-менее серьёзном проекте - неприемлема, от слова "совсем": ответ на некоторые команды по даташиту может занимать до 80 секунд. Что в это время делать остальному функционалу прошивки - курить бамбук? Единственное верное пмсм решение - это неблокирующий конечный автомат с состояниями, вещь не самая тривиальная к реализации, в своё время убил на отладку этого дела больше месяца.

Вы абсолютно правы. Попытался сделать пасечные весы. Что-бы по звонку от меня и подачи определенных DTMF сигналов "озвучивался" привес за сутки либо за неделю (файлы озвучки в SIM800). Ну и плюс энергосберегающий режим и периодическая проверка регистрации в сети (сеть теряется часто в предполагаемом месте установки устройства), нет сети - отключи радиомоодуль, минут через несколько снова проверь... Это штоба батарейку поберечь. Ну и плюс экранчик с кнопочкой, на месте привес проверить. Ну и RTC с микросхемой памяти, - эти привесы хранить и долгими зимними вечерами анализировать.

Код блокирующий : АТ команда - ждем овет - что-то делаем. Вроде и работает все, но криво как-то. То на звонок не отвечает, то ДТМФ не распознает, то еще какая хрень...

НО! Представив сложность написания конЧЕного автомата (с кучей незапрашиваемых уведомлений, вариантами ответов от SIM) - решил НИАСИЛЮ ;)) Жил же я раньше без умных весов, может и дальше проживу...

sadman41
Offline
Зарегистрирован: 19.10.2016

kolyn, при таком раскладе нужно было идти в обратную сторону - не по запросу отдавать данные, а пушить куда-нить. Сейчас, как я понимаю, модно на MQTT-сервер выкидывать данные, потом со смартфона клиентом смотреть. А если 3310 в качестве клиентского устройства, то ежедневный смс-репорт - сколько прибавилось за сутки, сколько с начала недели. Заодно будет уверенность, что система не висит.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kolyn пишет:
НО! Представив сложность написания конЧЕного автомата (с кучей незапрашиваемых уведомлений, вариантами ответов от SIM) - решил НИАСИЛЮ ;)) Жил же я раньше без умных весов, может и дальше проживу...
А еще нехорошие люди придумали матыматыку. А раньше все было просто один носок тры рубля, другой чотыры, итого платы десят. А пришли матыматыки и уважаемые люди понесли убытки. Хорошую вешь матыматыкой не назвали бы.

kolyn
Offline
Зарегистрирован: 18.01.2019

sadman41 пишет:

не по запросу отдавать данные, а пушить куда-нить. 

В месте, где хотел пользовать устройство мобильного интернета нет. От слова совсем. Даже EDGE нет! Это первое. Второе - вохдящие бесплатны. Т.е я пополнил карту раз в год и звоню на устройство, не заморачиваясь с проверкой счета, пополнением и т.д. - считаю жирным плюсом при эксплуатации.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Насколько я понял - хотели звонить с бесплатными входящими и пр. пирогами, но не смогли обуздать систему. Так что - или смс или ничего. Выбор Ваш, конечно  - мотаться на пасеку чтобы смотреть на экранчик или иногда пополнять баланс.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kolyn пишет:
В месте, где хотел пользовать устройство мобильного интернета нет. От слова совсем. Даже EDGE нет! Это первое. Второе - вохдящие бесплатны. Т.е я пополнил карту раз в год и звоню на устройство, не заморачиваясь с проверкой счета, пополнением и т.д. - считаю жирным плюсом при эксплуатации.
Без обратной связи ничего путного не выйдет. Как вы поймете что удаленое устройство приняло ваше сообщение и сделало то что вы ей передали. Может оно давно отвалилось и вы отправляете смс в никуда.

kolyn
Offline
Зарегистрирован: 18.01.2019

sadman41 пишет:

 Выбор Ваш, конечно  - мотаться на пасеку чтобы смотреть на экранчик 

Летом живу там практически все время - это основное занятие для денг. Ардуина - хобби, тренировка для мозгов, черствеют с годами, знаете ли. Проект пытался замутить не для себя, хотел выложить в свободный доступ. "Умные пчеловодные весы" как коммерчесский проект есть и в Украине и в России, и за далеким бугром, но цена!!! Любителю не по карману, профессионалу по сути не нужны - он и так все видит...

То,что сгородил я, в принципе работает, но... Глюки, такое предлагать для повторения - дурной тон. Может следующей зимой... или никогда...

kolyn
Offline
Зарегистрирован: 18.01.2019

qwone, писал ранее про логику:

Что-бы по звонку от меня и подачи определенных DTMF сигналов "озвучивался" привес за сутки либо за неделю (файлы озвучки в SIM800).

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

kolyn пишет:
Что-бы по звонку от меня и подачи определенных DTMF сигналов "озвучивался" привес за сутки либо за неделю (файлы озвучки в SIM800).
А теперь представим ситуацию. Вы находитесь хер-знаете-где. Хотите узнать прирост. Отправляете СМС . И улий озвучивает прирост +5 кг. Замечательно. Но вы из местности хер-знаете-где услышите озвучку находящую на улике,а значит далеко от вас. Вот и выходит, что нужно отправить прирост уже к вам на мобилу, который это и озвучит . 

sadman41
Offline
Зарегистрирован: 19.10.2016

Квон опять неправильного мёда хлебнул...

kolyn
Offline
Зарегистрирован: 18.01.2019

qwone пишет:

А теперь представим ситуацию. Вы находитесь хер-знаете-где. Хотите узнать прирост. Отправляете СМС . И улий озвучивает прирост +5 кг. Замечательно. Но вы из местности хер-знаете-где услышите озвучку находящую на улике,а значит далеко от вас. Вот и выходит, что нужно отправить прирост уже к вам на мобилу, который это и озвучит . 

Одно из двух - либо я тупо пояснил, либо до Вас тупо не дошло ;)

Я звоню весам. Они снимают трубу, и говорят мне (человечьим голосом на чистом русском языке): "Хотите узнать привес за сутки - нажмите 1, привес за неделю - нажмите два, хотите послушать свежий анекдот - нажмите 666".  Я на своем телефоне нажимаю кнопку 1, весам передается ДТМФ-сигнал и они говорят человечьим языком: "Привес за сутки составил 16 кг. 850 гр." Я переключаюсь с телефона на калькулятор, умножаю на количество семей, на цену меда в долларах и довольный потираю руки.

Позже выясняется, что это был глюк и в реале вместо привеса была убыль...

DetSimen
DetSimen аватар
Онлайн
Зарегистрирован: 25.01.2017

Значить, Пух приходил, покопаца

alexbmd
Offline
Зарегистрирован: 15.01.2016

DIYMan пишет:

В целом же, повторюсь ещё раз: ваш подход - не очень, на простом примере: вы послали команду AT, а в этот момент в порт упала SMS, до прихода ответа OK. С вашим кодом - СМС будет пропущена.

вчера во время эксперементов с модем добавил прерывание для отладки и заметил следующее:

- если прерывания нет, то все что уходит в сериал от модема успешно получается ардуиной. без пропусков.

- если я добавляю короткое и быстрое прерывание, просто зажечь 13 лед, когда чтото пришло в сериал. причем зажигаем через запись в порт а не через digitalWrite(); который в 20 раза медленее, то первые 5 символов пропадают из эфира.  как можно словить все символы ?

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

alexbmd пишет:

весь код показывайте.

И вообще непонятно, зачем прерывание для отладки если все что валится из модема вы все равно выводите в монитор.

Уже многократно обсуждалось здесь, максимально отказываться от вских выводов информации во время приема данных, т.е. или делаете большой буфер, в него все кидаете а потом обрабатываете или обрабатывать online но тогда код должен быть максимально коротким

alexbmd
Offline
Зарегистрирован: 15.01.2016
леонардо соеденен с модемом и отправляет на комп все что посылает модем

volatile byte flag = 0;

void setup(){
pinMode(13, OUTPUT);
pinMode(3, INPUT); //в модем
  while(!Serial); // for leonardo
  Serial.begin(115200);
  Serial1.begin(115200);
  attachInterrupt(0, blink, LOW);

  }

void loop(){
  // Копируем Serial1 --> Serial
  if(Serial1.available()) Serial.write(Serial1.read());
  // Копируем Serial --> Serial1
  if(Serial.available()) Serial1.write(Serial.read());
  if (flag) {
	  PORTC |= (1 << 7);
	  flag = 0;
  }

}

void blink() {
	flag = 1;
}

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

ну и как сказал уж без прерывания все ок а так первые 5 символов пропадают

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

alexbmd пишет:


ну вопрос то остался: зачем моргать светодиодом со скоростью 115200 при приеме данных?

 

alexbmd
Offline
Зарегистрирован: 15.01.2016

не, он моргает один раз. согласно низкому уровню на ноге 10 модема.

в кратце. на ноге 10 модема. появляется низкий уровень  когда приходит смс. в этоже время одновременно когда приходит смс модем отправляет текст RING в сериал. т.е. одновременно ринг в сериал и ноль на 10 ноге. по этому нулю я зажигаю лед. но не вижу надписб RING в сериал. если закоментить прерывание то RING я вижу.