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 месяца
лана. будем копить. :)
бутылки хоть сдам, в канцеканцов.