SMS информирование отключения внешнего питания на модеме IOT-GA6
- Войдите на сайт для отправки комментариев
- отправка SMS через две минуты (изменяется в скетче) после отключения/включения внешнего питания AC220 V.
- отправка SMS при сработке концевика (пин на землю замкнуть) на секунду (изменяется в скетче). Следующее сообщение отправиться не ранее чем через 10 минут (меняется в скетче).
- административный телефон можно поменять позвонив на железку в первые 30 секунд после окончания инициализации модема.
- используется два светодиода: первый - короткие вспышки раз в 3 секунды - нормальный рабочий режим, вспышка раз в секунду - инициализация модема, частое мецание - ошибка ответа от модема - перезагрузка; второй светодиод - несколько вспышек за 3 секунды = номеру выполняемой команды/шага в данный момент - можно диагностировать на какой команде модем капризничает.
- в каждой отправляемой SMS прописывается uptime железки и температура внешнего датчика DS18B20.
#include <avr/wdt.h> #include <avr\pgmspace.h> #include <EEPROM.h> char phoneMain[] = "7920*******"; // admin phone const char at21cmd[] PROGMEM = "AT+CUSD=1,*100#,15\r\n"; // USSD string get balance #define DOOR_CONTROL #define EXT_POW_CONTROL #define USE_DS18B20 #ifdef EXT_POW_CONTROL #define ext_pow_pin (byte)5 // 2 <--> 5 test #define READEXTPOW digitalRead(ext_pow_pin) #define delaySMSpowerOFF 120000UL // задержка 2 минут отправки СМС при отключении питания #define delaySMSpowerON 120000UL // задержка 2 минут отправки СМС при включении питания unsigned long timer_power_on_off; byte startPowerTimer; byte lastPower220; #endif #ifdef DOOR_CONTROL byte deviceMode = 1; // 1 = сигнализация включена - контроль сработки датчика #define key_pin (byte)2 // 5 <--> 2 test #define READKEY !digitalRead(key_pin) #define delay_alarm_door 600000UL unsigned long timer_alarm_door = 0; byte flsend_alarm_door; #define period_deb_key 1000UL unsigned long timer_deb_key = 0; #endif #ifdef USE_DS18B20 #include <OneWire.h> #include <DallasTemperature.h> #define TEMPERATURE_PRECISION 9 // точность получения значения темературы #define ds18_pin A0 // pin DS18B20 OneWire oneWire(ds18_pin); // объект 1Ware DallasTemperature sensors(&oneWire); // объект датчика температуты byte dsCount; // количество датчиков температуры #define max_ds_count 5 // максимальное количество датчиков DeviceAddress massTherm[max_ds_count]; // массив адресов датчиков ds18b20 #define period_get_temp 780137UL // получение температуры каждые 13 min unsigned long timer_get_temp; // таймер получения температуры word massTemper[max_ds_count]; //массив температур byte requestTemp = 1; // запрос температуры #endif #define bLedOn LOW #define led1_pin (byte)9 // status led #define LED1ON digitalWrite(led1_pin,bLedOn) #define LED1OFF digitalWrite(led1_pin,!bLedOn) #define led2_pin (byte)4 // error led #define LED2ON digitalWrite(led2_pin,bLedOn) #define LED2OFF digitalWrite(led2_pin,!bLedOn) #define reset_A6_pin (byte)7 #define power_A6_pin (byte)8 #define count_ext_commands 4 // count external commands from incoming sms byte flGetBalance; byte FirstStart; #define period_wait_phone 30000UL // ждем 30 секунд после инициализации модема звонка чтоб записать админский номер unsigned long timer_wait_phone; byte flag_wait_phone; #define pos_eeprom_flag_saved_admin_phone 48 // value 139 - exist phone #define pos_eeprom_admin_phone 76 unsigned long timer_reg_modem; // timer registration modem in net #define max_size_pgm_buf 128 char pgm_buf[max_size_pgm_buf]; #define period_read_sms 29971UL // read sms every ~30 sec unsigned long timer_read_sms = 0; // timer read sms #define period_send_sms 8937UL // send sms every ~9 sec unsigned long timer_send_sms = 0; // timer read sms #define max_size_fixed_resp 16 // in work save 3 response from buf commands char resp1[max_size_fixed_resp]; char resp2[max_size_fixed_resp]; char resp3[max_size_fixed_resp]; // 3 parts response byte flresp1, flresp2, flresp3; // found parts of response #define max_size_sms_buf 110 // max size sms with stop byte and text uptime char sms_buf[max_size_sms_buf]; // sms buf char sender[13]; // phone number for send sms. +7 and 10 digits + stop byte = always 13 digits!!! #define max_size_resp_buf 254 // max size response buf from modem, then more than goodest char resp_buf[max_size_resp_buf]; // response buf from modem byte pos_buf; // current pos response buf byte ledStatus, ledError, flLedSt, flLedEr; // ledError // 0 - normal work, modem status 101, 1 flash per 3 sec // 1 - init modem status 100, 1 flash per 1 sec // 2 - problem modem, no response, flash everu 20 milli sec,reset modem and new start // ledStatus // number flash per 3 sec = number modem step < 100 unsigned long timer_led_status, timer_led_error; byte modem_step; // current work mode mode in table of command // static steps: // 100 - delay for registration modem in net // 101 - not wait response, wait incomming call or other commands byte wait_response; // 0-no wait response, wait ring or other command // 1-wait fixed response, if time more - reset modem #define period_fixed_wait 15000UL // max time for type 1 wait response // 2-wait response data or wait action user, if time more - clear command #define period_data_wait 15000UL // max time for type 2 wait response unsigned long current_millis; uint8_t mcusr_mirror __attribute__ ((section (".noinit"))); void get_mcusr(void) \ __attribute__((naked)) \ __attribute__((used)) \ __attribute__((section(".init3"))); void get_mcusr(void) { mcusr_mirror = MCUSR; MCUSR = 0; wdt_disable(); } void setup() { MCUSR = 0; wdt_disable(); Serial.begin(9600); // modem speed // read mainPhone from EEPROM if ((EEPROM.read(pos_eeprom_flag_saved_admin_phone) == 139)) { for (byte i = 0; i < 11; ++i) phoneMain[i] = EEPROM.read(pos_eeprom_admin_phone + i); phoneMain[11] = 0; } #ifdef USE_DS18B20 sensors.begin(); // инициировать датчики температуры dsCount = sensors.getDeviceCount(); // получить количество датчиков if (dsCount > max_ds_count) dsCount = max_ds_count; // если датчиков больше чем максимальное - уменьшаем oneWire.reset_search(); // сброс шины поиска датчиков byte i = 0; while (i < dsCount) { // цикл по всем датчикам if (sensors.getAddress(massTherm[i], i)) sensors.setResolution(massTherm[i], TEMPERATURE_PRECISION); ++i; } #endif // put your setup code here, to run once: initAll(); wdt_enable(WDTO_8S); } void loop() { wdt_reset(); //delay(9000); // test WDT current_millis = millis(); // put your main code here, to run repeatedly: flashLed(); // read sms if (((current_millis - timer_read_sms) >= period_read_sms) && (wait_response == 0) && (modem_step == 101)) { timer_read_sms = current_millis; // reset timer read sms // set mode read sms modem_step = 9; } // send sms if (((current_millis - timer_send_sms) >= period_send_sms) && (wait_response == 0) && (modem_step == 101) && (sender[0] > 0) && (sms_buf[0] > 0)) { timer_send_sms = current_millis; // reset timer send sms // send sms modem_step = 11; } // door control #ifdef DOOR_CONTROL if (READKEY) { if (((current_millis - timer_deb_key) >= period_deb_key) && (deviceMode)) { if ((!flsend_alarm_door) && (modem_step != 100)) { flsend_alarm_door = 1; sendSMS(phoneMain, (char*) "Alarm! Door opened! "); timer_alarm_door = current_millis; } } } else { timer_deb_key = current_millis; } if (flsend_alarm_door) if ((current_millis - timer_alarm_door) >= delay_alarm_door) flsend_alarm_door = 0; #endif // external power control #ifdef EXT_POW_CONTROL // power 220V control if (startPowerTimer) { byte currentPower = READEXTPOW; if (lastPower220) { if (!currentPower) { startPowerTimer = 0; lastPower220 = currentPower; } else { if ((current_millis - timer_power_on_off) >= delaySMSpowerON) { startPowerTimer = 0; sendSMS(phoneMain, (char *) "Power AC220 ON "); } } } else { if (currentPower) { startPowerTimer = 0; lastPower220 = currentPower; } else { if ((current_millis - timer_power_on_off) >= delaySMSpowerOFF) { startPowerTimer = 0; sendSMS(phoneMain, (char *) "Alarm! Power AC220 OFF "); } } } } else { if (READEXTPOW != lastPower220) { startPowerTimer = 1; timer_power_on_off = current_millis; lastPower220 = READEXTPOW; } } #endif // get balance if ((wait_response == 0) && (modem_step == 101) && (flGetBalance)) { flGetBalance = 0; modem_step = 21; } #ifdef USE_DS18B20 if (((current_millis - timer_get_temp) >= period_get_temp) && (wait_response == 0) && (modem_step == 101)) { if (requestTemp) { sensors.requestTemperatures(); requestTemp = 0; } else if ((current_millis - timer_get_temp) >= (period_get_temp + 200UL)) { // for 9 bit PRECISION timer_get_temp = current_millis; requestTemp = 1; byte i = 0; while (i < dsCount) { float tct = sensors.getTempC(massTherm[i]); if (tct < 0) massTemper[i] = ((-tct) * 10) + 2000; else massTemper[i] = (tct * 10); ++i; } } } #endif // modem work loadDataFromModem(); // load data mainLoopModem(); // main actions on modem } void initAll() { #ifdef DOOR_CONTROL pinMode(key_pin, INPUT_PULLUP); flsend_alarm_door = 0; deviceMode = 1; #endif #ifdef EXT_POW_CONTROL pinMode(ext_pow_pin, INPUT); lastPower220 = READEXTPOW; startPowerTimer = 0; #endif pinMode(led1_pin, OUTPUT); LED1OFF; pinMode(led2_pin, OUTPUT); LED2OFF; pinMode(reset_A6_pin, OUTPUT); pinMode(power_A6_pin, OUTPUT); initModem(); ledError = 1; // 1 = modem status 100 } void initModem() { digitalWrite(reset_A6_pin, LOW); digitalWrite(power_A6_pin, HIGH); while ((millis() - current_millis) <= 3200UL) { Serial.print("AT\r\n"); delay(100); } modem_step = 100; // first step = wait modem for registration on net wait_response = 0; // no wait response sms_buf[0] = 0; // clear sms sender[0] = 0; // clear sender timer_reg_modem = millis(); pos_buf = 0; resp_buf[pos_buf] = 0; ledStatus = 0; flGetBalance = 0; flag_wait_phone = 0; FirstStart = 1; } void resetModem() { ledError = 2; digitalWrite(reset_A6_pin, HIGH); delay(500); initModem(); } void flashLed() { // led1 - led status if ((ledStatus > 0) && (ledStatus <= 15)) { if ((current_millis - timer_led_status) >= (3000UL + (250UL * flLedSt))) { if (flLedSt >= (ledStatus * 2)) { LED1OFF; flLedSt = 0; timer_led_status = current_millis; } else { if (bitRead(flLedSt, 0)) LED1OFF; else LED1ON; ++flLedSt; } } } else { LED1OFF; } // led2 - led error switch (ledError) { case 1: { if ((current_millis - timer_led_error) >= 1000UL) { if (flLedEr) { if ((current_millis - timer_led_error) >= 1050UL) { timer_led_error = current_millis; LED2OFF; flLedEr = 0; } } else { LED2ON; flLedEr = 1; } } break; } case 2: { if ((current_millis - timer_led_error) >= 50UL) { if (flLedEr) { if ((current_millis - timer_led_error) >= 100UL) { timer_led_error = current_millis; LED2OFF; flLedEr = 0; } } else { LED2ON; flLedEr = 1; } } break; } default: { if ((current_millis - timer_led_error) >= 3000UL) { if (flLedEr) { if ((current_millis - timer_led_error) >= 3050UL) { timer_led_error = current_millis; LED2OFF; flLedEr = 0; } } else { LED2ON; flLedEr = 1; } } } } } const char at0cmd[] PROGMEM = "AT\r\n"; // 0 const char at1cmd[] PROGMEM = "AT+DDET=1\r\n"; const char at2cmd[] PROGMEM = "ATE0\r\n"; // 1 const char at3cmd[] PROGMEM = "AT+CLIP=1\r\n"; // 3 const char at4cmd[] PROGMEM = "ATS0=5\r\n"; // 4 const char at5cmd[] PROGMEM = "ATV1\r\n"; // 2 const char at6cmd[] PROGMEM = "AT+CMEE=2\r\n"; const char at7cmd[] PROGMEM = "AT+CMGF=1\r\n"; // 6 const char at8cmd[] PROGMEM = "AT+CREG?\r\n"; const char at8resp1[] PROGMEM = "+CREG:"; const char at8resp2[] PROGMEM = ",1"; // 5 const char at9cmd[] PROGMEM = "AT+CMGL=\"ALL\"\r\n"; const char at10cmd[] PROGMEM = "AT+CMGD=1,4\r\n"; // 7 const char at11cmd[] PROGMEM = "AT+CMGS=\""; const char at12cmd[] PROGMEM = "~sender~"; const char at13cmd[] PROGMEM = "\r\n"; const char at13resp1[] PROGMEM = ">"; const char at14cmd[] PROGMEM = "~textsms~"; const char at15cmd[] PROGMEM = "~ctrlz~"; const char at15resp1[] PROGMEM = "+CMGS:"; const char at16cmd[] PROGMEM = "ATA\r\n"; const char at16resp2[] PROGMEM = "NO CARRIER"; const char at17cmd[] PROGMEM = "ATH\r\n"; const char at18cmd[] PROGMEM = "\""; const char at19cmd[] PROGMEM = "AT+CSQ\r\n"; const char at19resp1[] PROGMEM = "+CSQ:"; const char at19resp2[] PROGMEM = ","; const char at20cmd[] PROGMEM = "AT+GSN\r\n"; // get imei const char atOKcmd[] PROGMEM = "OK"; const char atOKRNcmd[] PROGMEM = "OK\r\n"; const char atNULLcmd[] PROGMEM = ""; const char at1status[] PROGMEM = "1"; const char at2status[] PROGMEM = "2"; const char at1step[] PROGMEM = "1"; const char at2step[] PROGMEM = "2"; const char at3step[] PROGMEM = "3"; const char at4step[] PROGMEM = "4"; const char at5step[] PROGMEM = "5"; const char at6step[] PROGMEM = "6"; const char at7step[] PROGMEM = "7"; const char at8step[] PROGMEM = "8"; const char at9step[] PROGMEM = "9"; const char at10step[] PROGMEM = "10"; const char at11step[] PROGMEM = "11"; const char at12step[] PROGMEM = "12"; const char at13step[] PROGMEM = "13"; const char at14step[] PROGMEM = "14"; const char at15step[] PROGMEM = "15"; const char at16step[] PROGMEM = "16"; const char at17step[] PROGMEM = "17"; const char at18step[] PROGMEM = "18"; const char at19step[] PROGMEM = "19"; const char at101step[] PROGMEM = "101"; const char at20step[] PROGMEM = "20"; const char at21resp1[] PROGMEM = "+CUSD: 2,"; const char at21resp2[] PROGMEM = ",72\r\n"; const char * const str_at[] PROGMEM = { // record of AT commands at0cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at2step, at1cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at2step, at2cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at3step, at3cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at4step, at4cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at5step, at5cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at7step, at6cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at7step, at7cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at8step, at8cmd, at8resp1, at8resp2, atOKcmd, at1status, at20step, at9cmd, atOKRNcmd, atNULLcmd, atNULLcmd, at1status, at101step, at10cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at101step, at11cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at12step, at12cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at18step, at13cmd, at13resp1, atNULLcmd, atNULLcmd, at1status, at14step, at14cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at15step, at15cmd, at15resp1, atOKcmd, atNULLcmd, at1status, at101step, at16cmd, atOKRNcmd, at16resp2, atNULLcmd, at2status, at101step, at17cmd, atOKRNcmd, atNULLcmd, atNULLcmd, at1status, at101step, at18cmd, atNULLcmd, atNULLcmd, atNULLcmd, at1status, at13step, at19cmd, at19resp1, at19resp2, atOKcmd, at1status, at101step, at20cmd, atOKcmd, atNULLcmd, atNULLcmd, at1status, at10step, // get imei and go to 10 cmd - last cmd for init - delete sms at21cmd, atOKRNcmd, at21resp1, at21resp2, at1status, at101step }; void getPgmBuf(byte idxPgmBuf) { const char * addrStroki = pgm_read_word_near((int)(str_at + idxPgmBuf)); strcpy_P(pgm_buf, addrStroki); } void loadDataFromModem() { // load data from modem to buf - only one line (string) if (Serial.available()) { byte br; while (Serial.available()) { br = Serial.read(); if (br) { if (pos_buf >= (max_size_resp_buf - 1)) pos_buf = 0; resp_buf[pos_buf] = br; ++pos_buf; if (br == '\n') if ((pos_buf > 1) && (resp_buf[pos_buf - 2] == '\r')) break; // new string*/ } } resp_buf[pos_buf] = 0; // stop byte of string } } void mainLoopModem() { // main action modem switch (modem_step) { case 100: { if ((current_millis - timer_reg_modem) >= 20000UL) { // wait 20sec registration modem wait_response = 0; // do not response modem_step = 0; // go to init modem mode - first command } break; } case 101: { ledError = 0; ledStatus = 0; if (FirstStart) { FirstStart = 0; flag_wait_phone = 1; timer_wait_phone = current_millis; } if (pos_buf == 0) break; // no response // find ring and other commands and execute if (flag_wait_phone) { if ((current_millis - timer_wait_phone) < period_wait_phone) { byte pb1 = posSubStrFromPos(resp_buf, pos_buf, (char *) "+CLIP:", 0); if (pb1) { byte pb2 = posSubStrFromPos(resp_buf, pos_buf, (char *) "79", 0); //-- if ((pb1) && (pb2 > (pb1 + 5)) && (pos_buf > (pb2 + 12))) { // save to EEPROM EEPROM.write(pos_eeprom_flag_saved_admin_phone, 139); for (byte i = 0; i < 11; ++i) { byte bc = resp_buf[i + pb2 - 1]; phoneMain[i] = bc; EEPROM.write(pos_eeprom_admin_phone + i, bc); } phoneMain[11] = 0; EEPROM.write(pos_eeprom_admin_phone + 11, 0); flag_wait_phone = 0; wait_response = 0; modem_step = 17; // answer on ring 16 or break ring 17 break; } //-- } } else { flag_wait_phone = 0; } } // other find break; } default: { switch (wait_response) { case 0: { sendAtCommand(modem_step); // send command to modem break; } case 1: { if ((current_millis - timer_reg_modem) >= period_fixed_wait) { // if end timer wait response resetModem(); // we have problem - no correct response from modem } else { if (pos_buf == 0) break; // no response // action before find response, example long ussd if (findRespParts() == 1) { // need fixed response // good response from modem // other action on one item command switch (modem_step) { case 15: { // end send sms sender[0] = 0; sms_buf[0] = 0; // clear sms buf // go to next step wait_response = 0; // do not wait response getPgmBuf(6 * modem_step + 5); modem_step = strToByte(pgm_buf); // to next at command or mode break; } case 9: { // read all sms // find command from sms if (posSubStrFromPos(resp_buf, pos_buf, (char*) "+CMGL: ", 0) > 0) { // we have sms int sbeg = 0; int spos; lsms1: if (sbeg < pos_buf) { spos = posSubStrFromPos(resp_buf, pos_buf, (char*) "+CMGL: ", sbeg); if (spos > 0) { spos += 7; if (spos < pos_buf) { spos = posSubStrFromPos(resp_buf, pos_buf, phoneMain, spos); if (spos > 0) { spos += 7; spos = posSubStrFromPos(resp_buf, pos_buf, (char*) "\r\n", spos); if (spos > 0) { ++spos; // begin text sms byte ends = posSubStrFromPos(resp_buf, pos_buf, (char*) "\r\n", spos); // end text sms if (ends > 0) { for (byte i = 0; i < count_ext_commands; ++i) { getExtBuf(i); if (posSubStrFromPos(resp_buf, ends, pgm_buf, spos) > 0) { execExtCmd(i); break; } } sbeg = ends; goto lsms1; } } } } } } // go to step delete SMS wait_response = 0; // do not wait response modem_step = 10; // step 10 } else { // go to next step wait_response = 0; // do not wait response getPgmBuf(6 * modem_step + 5); modem_step = strToByte(pgm_buf); // to next at command or mode } break; } default: { // go to next step wait_response = 0; // do not wait response getPgmBuf(6 * modem_step + 5); modem_step = strToByte(pgm_buf); // to next at command or mode } } } } break; } case 2: { if ((current_millis - timer_reg_modem) >= period_data_wait) { // if end timer wait response // no data or no user action // exit from command // go to next step wait_response = 0; // do not wait response getPgmBuf(6 * modem_step + 5); modem_step = strToByte(pgm_buf); // to next at command or mode } else { if (pos_buf == 0) break; // no response // read parts of sms or other commands or DTMF // go to next step after actions wait_response = 0; // do not wait response getPgmBuf(6 * modem_step + 5); modem_step = strToByte(pgm_buf); // to next at command or mode } break; } default: { // go to next step after actions wait_response = 0; // do not wait response getPgmBuf(6 * modem_step + 5); modem_step = strToByte(pgm_buf); // to next at command or mode } } } } } int strPos(char *str11, char *str22) { // find position substring in string char*p = LastPos(str11, str22); int n = p - str11; return n; } char* LastPos(char *str1, char *str2) { // find substring in string int L1 = strlen(str1); int L2 = strlen(str2); for (int i = L1 - L2; i >= 0; i--) { int j = 0; for (; j < L2; j++) if ((str1[i + j] != str2[j])) break; if (j == L2) return str1 + i; } return 0; } void sendAtCommand(byte numcmd) { // send at command if modem not busy // find key worlds getPgmBuf(6 * numcmd); if (posSubStrFromPos(pgm_buf, strlen(pgm_buf), (char *) "~sender~", 0) > 0) { Serial.print(sender); } else if (posSubStrFromPos(pgm_buf, strlen(pgm_buf), (char *) "~textsms~", 0) > 0) { Serial.print(sms_buf); } else if (posSubStrFromPos(pgm_buf, strlen(pgm_buf), (char *) "~ctrlz~", 0) > 0) { Serial.print(char(26)); } else { Serial.print(pgm_buf); // send cmd from cmd buf by number cmd } timer_reg_modem = current_millis; // reset wait response timer // load response from command to buf getPgmBuf(6 * numcmd + 1); if (pgm_buf[0] == 0) { // no response resp1[0] = 0; resp2[0] = 0; resp3[0] = 0; // no response wait_response = 0; getPgmBuf(6 * numcmd + 5); modem_step = strToByte(pgm_buf); // go to next step or mode pos_buf = 0; // clear response buf return; // next loop } else { getPgmBuf(6 * numcmd + 1); byte i = 0; while ((resp1[i] = pgm_buf[i]) > 0) ++i; resp1[i] = 0; // save first response from buf at cmd getPgmBuf(6 * numcmd + 2); if (pgm_buf[0] == 0) { // no second response resp2[0] = 0; resp3[0] = 0; // no response 2 and 3 } else { byte i = 0; while ((resp2[i] = pgm_buf[i]) > 0) ++i; resp2[i] = 0; // save secont response from buf at cmd getPgmBuf(6 * numcmd + 3); if (pgm_buf[0] == 0) { // no thr response resp3[0] = 0; // no response 3 } else { byte i = 0; while ((resp3[i] = pgm_buf[i]) > 0) ++i; resp3[i] = 0; // save thr response from buf at cmd } } } getPgmBuf(6 * numcmd + 4); wait_response = strToByte(pgm_buf); // set wait resp from command buf flresp1 = 0; flresp2 = 0; flresp3 = 0; // clear result response pos_buf = 0; resp_buf[pos_buf] = 0; // clear response buf ledStatus = numcmd + 1; ledError = 0; } byte strToByte(char *instr) { byte sl = strlen(instr); if (sl < 1) return 0; byte res = 0, i = 0; while (instr[i] > 0) { res += ((instr[i] - '0') * pow(10, (sl - i - 1))); ++i; } if (sl > 2) ++res; return res; } byte posSubStrFromPos(char *inBuf, byte maxPosBuf, char *subStr, byte resPos) { if (resPos >= maxPosBuf) return 0; while ((resPos < maxPosBuf) && (inBuf[resPos] > 0)) { byte isub = 0; if (inBuf[resPos] == subStr[isub]) { byte sslen = strlen(subStr); while (((resPos + isub) < maxPosBuf) && (inBuf[resPos + isub] > 0) && (isub < sslen)) { if (subStr[isub] != inBuf[resPos + isub]) break; ++isub; } if (isub >= sslen) { ++resPos; return resPos; } } ++resPos; } return 0; } byte findRespParts() { // find response parts in response buf byte countresp = 0, countgood = 0; if (resp1[0] > 0) { // exist response 1 ++countresp; if (strPos(resp_buf, resp1) >= 0) { flresp1 = 1; // found response 1 } if (resp2[0] > 0) { // exist response 2 ++countresp; if (strPos(resp_buf, resp2 ) >= 0) { flresp2 = 1; // found response 2 } if (resp3[0] > 0) { // exist response 3 ++countresp; if (strPos(resp_buf, resp3) >= 0) { flresp3 = 1; // found response 3 } } } } if (flresp1 == 1) { ++countgood; } if (flresp2 == 1) { ++countgood; } if (flresp3 == 1) { ++countgood; // calculate good response } if ((countresp > 0) && (countresp == countgood)) return 1; else return 0; } const char ex0cmd[] PROGMEM = "getstatus"; const char ex1cmd[] PROGMEM = "poweroff"; const char ex2cmd[] PROGMEM = "poweron"; const char ex3cmd[] PROGMEM = "getbalance"; const char * const ext_pgm_cmd[] PROGMEM = { ex0cmd, ex1cmd, ex2cmd, ex3cmd }; void getExtBuf(byte idxPgmBuf) { const char * addrStroki = pgm_read_word_near((int)(ext_pgm_cmd + idxPgmBuf)); strcpy_P(pgm_buf, addrStroki); } void execExtCmd(byte numCmd) { switch (numCmd) { case 0: { #ifdef DOOR_CONTROL if (deviceMode) sendSMS(phoneMain, (char*) "Power ON "); else sendSMS(phoneMain, (char*) "Power OFF "); #endif break; } case 1: { #ifdef DOOR_CONTROL deviceMode = 0; #endif break; } case 2: { #ifdef DOOR_CONTROL deviceMode = 1; #endif break; } case 3: { flGetBalance = 1; break; } default: {} } } void sendSMS(char *phnum, char *txtsms) { // prepare sender phone number and text for sms sender[0] = 0; sms_buf[0] = 0; strcpy(sender, "+"); strcat(sender, phnum); strcpy(sms_buf, txtsms); byte i = strlen(sms_buf); i = addTextUptime(sms_buf, i , max_size_sms_buf); // add uptime text to sms buf sms_buf[i] = 0; #ifdef USE_DS18B20 if (dsCount) { i = addTextTemp0(sms_buf, i , max_size_sms_buf); // add DS18B20 temp idx 0 to sms buf sms_buf[i] = 0; } #endif timer_send_sms = current_millis; // reset timer send sms timer_read_sms = current_millis; // reset timer read sms } byte addTextUptime(char *text, byte firstpos, byte maxsize) { // add uptime text to input text byte days = current_millis / 86400000UL; byte hours = (current_millis % 86400000UL) / 3600000UL; byte mins = ((current_millis % 86400000UL) % 3600000UL) / 60000UL; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = 'u'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; if (days > 9) { text[firstpos] = (days / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; } text[firstpos] = (days % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = 'd'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; if (hours > 9) { text[firstpos] = (hours / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; } text[firstpos] = (hours % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = 'h'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; if (mins > 9) { text[firstpos] = (mins / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; } text[firstpos] = (mins % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = 'm'; ++firstpos; return firstpos; } byte addTextTemp0(char *text, byte firstpos, byte maxsize) { // add uptime text to input text if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = ' '; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; word ttt = massTemper[0]; if (ttt >= 2000) { text[firstpos] = '-'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; ttt -= 2000; } word bbb = ttt / 10; if (bbb > 9) { text[firstpos] = (bbb / 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; } text[firstpos] = (bbb % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = '.'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = (ttt % 10) + '0'; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = ' '; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = '\''; ++firstpos; if (firstpos >= (maxsize - 1)) return firstpos; text[firstpos] = 'C'; ++firstpos; return firstpos; }
за пайку - жырную два.
за пайку - жырную два.
а где там наверху видно какая пайка? ;) - максимум расположение элементов.
ну а так да......стыдно. Ну не серийное же устройство делаю.
ну а так да......стыдно.
Да я пашутил же, намайная пайка, просто я ненавижу хитросплетения торчащих какпапало проводов.
Посоветуй лучше, где брал держатели для 18650? Где не находил, выходят 145р с пересылкой, а у мня на такие деньжищщи - амфибиотропная асфиксия.
https://ru.aliexpress.com/item/32841386302.html
аналогично дорого :( доставка
да еще и долго - 1.5 месяца
лана. будем копить. :)
бутылки хоть сдам, в канцеканцов.