17 Commits
v1.1 ... v1.2

Author SHA1 Message Date
UA1ZBE
7e978fcc9c update docs: relay3/4 pins, inverted logic, all relays independent 2026-07-22 15:51:39 +03:00
UA1ZBE
9ca5530c73 add relay3 (pin5), relay4 (pin6); invert logic: ON=HIGH, OFF=LOW 2026-07-22 15:49:23 +03:00
UA1ZBE
1430bba3f4 relay1 independent from ohrana, both relays saved 2026-07-22 14:09:15 +03:00
UA1ZBE
e68a762e88 docs: add TZ+3 mention, remove stale line ref 2026-07-22 14:03:44 +03:00
UA1ZBE
9b1c8f3497 Revert "add name set, beacon commands"
This reverts commit acc36cf3ad.
2026-07-22 14:00:37 +03:00
UA1ZBE
0b01526a39 Revert "docs: add name, name set, beacon"
This reverts commit 62cf8fc3f4.
2026-07-22 14:00:37 +03:00
UA1ZBE
fb30065edd Revert "fix beacon: init Ed25519 identity for valid advert signature"
This reverts commit d487b84926.
2026-07-22 14:00:37 +03:00
UA1ZBE
87ac515063 Revert "fix beacon: add onAdvertRecv to display received beacons"
This reverts commit 8b21bccac2.
2026-07-22 14:00:37 +03:00
UA1ZBE
9deb046ae3 Revert "auto beacon every hour + on startup via AdvertDataBuilder"
This reverts commit d49443f66c.
2026-07-22 14:00:37 +03:00
UA1ZBE
d49443f66c auto beacon every hour + on startup via AdvertDataBuilder 2026-07-22 13:55:05 +03:00
UA1ZBE
8b21bccac2 fix beacon: add onAdvertRecv to display received beacons 2026-07-22 13:44:50 +03:00
UA1ZBE
d487b84926 fix beacon: init Ed25519 identity for valid advert signature 2026-07-22 13:39:33 +03:00
UA1ZBE
62cf8fc3f4 docs: add name, name set, beacon 2026-07-22 13:32:59 +03:00
UA1ZBE
acc36cf3ad add name set, beacon commands 2026-07-22 13:32:35 +03:00
UA1ZBE
d3990516b5 add TZ offset +3h (MSK) for time display/set 2026-07-22 13:00:55 +03:00
UA1ZBE
dfdd6ab343 update README: add snr, remove canal 2026-07-22 12:56:42 +03:00
UA1ZBE
cb2a33c97e add snr command, update docs 2026-07-22 12:54:44 +03:00
6 changed files with 140 additions and 64 deletions

View File

@@ -106,21 +106,26 @@ All commands are processed in `onGroupDataRecv()`:
| Command | Action | Response |
|---------|--------|----------|
| `help` | list commands | `help:...` |
| `ohrana on` | arm, relay1 ON | `ohrana on ok` |
| `ohrana off` | disarm, relay1 OFF | `ohrana off ok` |
| `relay1 on` | relay1 ON (direct) | `relay1 on ok` |
| `relay1 off` | relay1 OFF (direct) | `relay1 off ok` |
| `relay2 on` | relay2 ON | `relay2 on ok` |
| `relay2 off` | relay2 OFF | `relay2 off ok` |
| `relay` | state of both relays | `relay:1on 2off` |
| `ohrana on` | arm | `ohrana on ok` |
| `ohrana off` | disarm | `ohrana off ok` |
| `relay1 on` | relay1 ON (HIGH) | `relay1 on ok` |
| `relay1 off` | relay1 OFF (LOW) | `relay1 off ok` |
| `relay2 on` | relay2 ON (HIGH) | `relay2 on ok` |
| `relay2 off` | relay2 OFF (LOW) | `relay2 off ok` |
| `relay3 on` | relay3 ON (HIGH) | `relay3 on ok` |
| `relay3 off` | relay3 OFF (LOW) | `relay3 off ok` |
| `relay4 on` | relay4 ON (HIGH) | `relay4 on ok` |
| `relay4 off` | relay4 OFF (LOW) | `relay4 off ok` |
| `relay` | state of all relays | `relay:1on 2off 3on 4off` |
| `status` | report state | `status:armed/off temp:±X.XC hall:trig/ok motion:trig/ok bat:X.XXV/USB` |
| `ver` | build date | `build:Mon DD YYYY HH:MM:SS` |
| `scan` | noise floor | `noise:-XXXdBm` |
| `snr` | RSSI и SNR последнего пакета | `rssi:-78dBm snr:+6.5dB` |
| `uptime` | device uptime | `uptime:1d 3h 15m` |
| `kontrol <min>` | auto-status every N min | `kontrol 60 min ok` |
| `kontrol off` | disable auto-status | `kontrol off` |
| `reboot` | reboot device | `rebooting` |
| `time` | show RTC date/time | `time:22.07.2026 11:00` |
| `time` | show RTC date/time (MSK, UTC+3) | `time:22.07.2026 11:00` |
| `time s DD.MM.YYYY HH.MM` | set RTC date/time | `time set 22.07.2026 11.00` |
### Response Delay
@@ -131,6 +136,8 @@ Alerts (`alert:hall`, `alert:motion`) and startup (`poweron`) are sent immediate
### Special Commands
- **`snr`** — returns `rssi:-78dBm snr:+6.5dB` based on the last received packet. Uses `radio_driver.getLastRSSI()` and `pkt->getSNR()`. Stored in `last_rssi` / `last_snr` fields, updated on every `onGroupDataRecv`.
- **`reboot`** — sends `rebooting` immediately (not deferred), blinks LED 5 times, then `NVIC_SystemReset()`.
- **`uptime`** — calculates uptime from `g_boot_time` (set at boot). Format: `uptime:1d 3h 15m` (days/hours/minutes).
- **`kontrol <min>`** — sets `g_auto_status_interval = min * 60000`. In `loop()`, when `millis() - g_last_auto_status >= interval`, sends status. Range: 11440 minutes.
@@ -198,7 +205,7 @@ pio run -e promicro_security -t upload
pio device monitor -b 115200
```
Current resource usage: RAM 8%, Flash 36.5%.
Current resource usage: RAM 8.1%, Flash 36.8%.
---
@@ -220,14 +227,14 @@ The LED blink (3 fast flashes) is the first thing in `onGroupDataRecv`. If LED d
- `rtc_clock.getCurrentTime()` returning bogus data (VolatileRTCClock starts from 0, fine).
### Adding a new command
1. Add `else if` block in `onGroupDataRecv()` after line 168.
1. Add `else if` block in `onGroupDataRecv()`.
2. Use `strcmp(cmd, "command") == 0` for exact match.
3. Call `send_text("response")` to reply.
4. Update the `help` string.
### Config persistent storage
- `InternalFS` (LittleFS) on nRF52 internal flash.
- `SecurityConfig`: armed + relay2 state saved as binary struct.
- `SecurityConfig`: armed + relay1/2/3/4 state saved as binary struct.
- File: `/security.cfg`, magic `0x53454355`.
---

View File

@@ -5,19 +5,19 @@ LoRa mesh-устройство охраны на базе nRF52840 (ProMicro) и
## Возможности
- Управление двумя реле (охрана + независимое)
- Управление четырьмя реле
- Датчик Холла (геркон) — оповещение об открытии двери/окна
- PIR датчик движения
- DS18B20 температура
- Светодиодная индикация состояния
- Сохранение конфигурации в энергонезависимую память
- Смена канала через mesh-команду
- SNR — RSSI и SNR последнего принятого пакета
## Аппарат
- **SoC:** nRF52840 (Adafruit ProMicro nRF52840)
- **Радио:** SX1262 (868 МГц, SF7, 62.5 кГц)
- **Память:** 256 КБ ОЗУ, 712 КБ Flash (занято 36%)
- **Память:** 256 КБ ОЗУ, 712 КБ Flash (занято 37%)
## Команды
@@ -27,10 +27,13 @@ LoRa mesh-устройство охраны на базе nRF52840 (ProMicro) и
| `ohrana off` | Выключить охрану |
| `relay1 on/off` | Управление реле 1 |
| `relay2 on/off` | Управление реле 2 |
| `relay` | Состояние обоих реле |
| `relay3 on/off` | Управление реле 3 |
| `relay4 on/off` | Управление реле 4 |
| `relay` | Состояние всех реле |
| `status` | Состояние устройства (включая bat) |
| `ver` | Версия прошивки |
| `scan` | Уровень шума в эфире |
| `snr` | RSSI и SNR последнего пакета |
| `uptime` | Время работы |
| `kontrol <min>` | Автоотправка статуса каждые N мин |
| `kontrol off` | Отключить автоотправку |

View File

@@ -24,16 +24,21 @@ Security Node — LoRa mesh-устройство, которое следит з
| Команда | Что делает | Пример ответа |
|---------|-----------|---------------|
| `help` | Список всех команд | `help:ohrana on,ohrana off,...` |
| `ohrana on` | **Включить охрану** — датчики активны, реле 1 замкнуто | `ohrana on ok` |
| `ohrana off` | **Выключить охрану** — датчики не активны, реле 1 разомкнуто | `ohrana off ok` |
| `relay1 on` | Включить реле 1 (независимо от охраны) | `relay1 on ok` |
| `ohrana on` | **Включить охрану** — датчики активны | `ohrana on ok` |
| `ohrana off` | **Выключить охрану** — датчики не активны | `ohrana off ok` |
| `relay1 on` | Включить реле 1 | `relay1 on ok` |
| `relay1 off` | Выключить реле 1 | `relay1 off ok` |
| `relay2 on` | Включить реле 2 | `relay2 on ok` |
| `relay2 off` | Выключить реле 2 | `relay2 off ok` |
| `relay` | Состояние обоих реле | `relay:1on 2off` |
| `relay3 on` | Включить реле 3 | `relay3 on ok` |
| `relay3 off` | Выключить реле 3 | `relay3 off ok` |
| `relay4 on` | Включить реле 4 | `relay4 on ok` |
| `relay4 off` | Выключить реле 4 | `relay4 off ok` |
| `relay` | Состояние всех реле | `relay:1on 2off 3on 4off` |
| `status` | Показать состояние устройства | `status:armed temp:+23.5C hall:ok motion:trig bat:4.12V` |
| `ver` | Версия прошивки (дата сборки) | `build:Jul 21 2026 15:30:00` |
| `scan` | Измерить уровень шума в эфире | `noise:-112dBm` |
| `snr` | RSSI и SNR последнего принятого пакета | `rssi:-78dBm snr:+6.5dB` |
| `uptime` | Время работы устройства | `uptime:1d 3h 15m` |
| `kontrol <мин>` | Автоотправка статуса каждые N мин | `kontrol 60 min ok` |
| `kontrol off` | Отключить автоотправку статуса | `kontrol off` |
@@ -98,12 +103,13 @@ Security Node — LoRa mesh-устройство, которое следит з
## Реле
- **Реле 1** — управляется `ohrana on/off` и `relay1 on/off`.
Охрана включена (`ohrana on`): **замкнуто** (NC разомкнуты, NO замкнуты).
Охрана выключена (`ohrana off`): **разомкнуто**.
Все реле независимы, состояние каждого сохраняется при перезагрузке.
Логика: ON = высокий уровень (HIGH), OFF = низкий (LOW).
- **Реле 2** — независимое, только `relay2 on/off`.
Состояние сохраняется при перезагрузке.
- **Реле 1** (P0.20) — `relay1 on/off`
- **Реле 2** (P0.22) — `relay2 on/off`
- **Реле 3** (P0.24) — `relay3 on/off`
- **Реле 4** (P1.00) — `relay4 on/off`
---
@@ -112,9 +118,13 @@ Security Node — LoRa mesh-устройство, которое следит з
`kontrol 60` — устройство будет само отправлять `status` каждые 60 минут.
`kontrol off` — отключить. Интервал от 1 до 1440 минут (1 минута — 24 часа).
## Качество сигнала (`snr`)
`snr` — показывает RSSI (уровень сигнала в dBm) и SNR (соотношение сигнал/шум в dB) последнего принятого пакета. Полезно для оценки качества связи и при настройке антенны. Чем ближе RSSI к 0 и чем выше SNR — тем лучше.
## Синхронизация времени (`time`)
`time` — показать текущее время устройства.
`time` — показать текущее время устройства (МСК, UTC+3).
`time s 22.07.2026 11.00` — установить дату и время. Формат: `time s DD.MM.YYYY HH.MM`
Время используется для отметок в сообщениях. После перезагрузки сбрасывается (если нет внешнего RTC).
@@ -127,20 +137,6 @@ Security Node — LoRa mesh-устройство, которое следит з
`uptime` — показывает, сколько времени устройство работает без перезагрузки.
Пример: `uptime:1d 3h 15m` (1 день, 3 часа, 15 минут).
## Смена канала (`canal`)
По умолчанию канал формируется из пароля `"1234"`.
Чтобы сменить:
```
canal домашний 5674
```
Ответ: `canal домашний 5674 ok`
Через ~5 секунд устройство перезагрузится и начнёт работать на новом канале.
**Важно:** Все устройства должны быть на одном канале. После смены канала связь будет только с теми узлами, у которых такой же пароль. Канал сохраняется в энергонезависимой памяти и не сбрасывается после перезагрузки. Чтобы вернуть канал по умолчанию — используйте `canal default 1234`.
---
## Задержка ответа

View File

@@ -11,8 +11,10 @@
| 0 | **P0.08** | Геркон (reed switch) |
| 1 | **P0.06** | PIR датчик движения |
| 2 | **P0.17** | DS18B20 температура |
| 3 | **P0.20** | Реле 1 (охрана) |
| 3 | **P0.20** | Реле 1 |
| 4 | **P0.22** | Реле 2 |
| 5 | **P0.24** | Реле 3 |
| 6 | **P1.00** | Реле 4 |
| 10 | **P0.09** | SX1262 RST |
| 11 | **P0.10** | SX1262 DIO1 |
| 12 | **P1.11** | SX1262 SCK |
@@ -89,7 +91,9 @@ P0.17 ────┤
## Реле
### Реле 1 (охрана) — P0.20
Логика: ON = HIGH, OFF = LOW.
### Реле 1 — P0.20
```
P0.20 ── IN1 релейного модуля
@@ -100,7 +104,7 @@ GND ── GND
IN1 ── P0.20
```
> Реле 1 управляется `ohrana on/off` и `relay1 on/off`.
> Реле 1 управляется `relay1 on/off`. Состояние сохраняется.
### Реле 2 — P0.22
@@ -113,7 +117,33 @@ GND ── GND
IN2 ── P0.22
```
> Реле 2 управляется только `relay2 on/off`. Состояние сохраняется.
> Реле 2 управляется `relay2 on/off`. Состояние сохраняется.
### Реле 3 — P0.24
```
P0.24 ── IN3 релейного модуля
Релейный модуль:
VCC ── 5V
GND ── GND
IN3 ── P0.24
```
> Реле 3 управляется `relay3 on/off`. Состояние сохраняется.
### Реле 4 — P1.00
```
P1.00 ── IN4 релейного модуля
Релейный модуль:
VCC ── 5V
GND ── GND
IN4 ── P1.00
```
> Реле 4 управляется `relay4 on/off`. Состояние сохраняется.
---
@@ -140,7 +170,9 @@ IN2 ── P0.22
├──────┤ P0.13 POWER_EN │
│ │ │
Геркон ──┤ P0.08│ P0.20 ─── Реле 1 │
│ │ P0.22 ─── Реле 2 │
│ │ P0.22 ─── Реле 2 │
│ │ P0.24 ─── Реле 3 │
│ │ P1.00 ─── Реле 4 │
PIR ────┤ P0.06│ │
│ │ P0.15 ─── LED статуса│
DS18B20 ───┤ P0.17│ │

View File

@@ -39,13 +39,18 @@ DallasTemperature ds18b20(&oneWire);
static bool g_armed = false;
static bool g_hall_alert = false;
static bool g_motion_alert = false;
static bool g_relay1_state = false;
static bool g_relay2_state = false;
static bool g_relay3_state = false;
static bool g_relay4_state = false;
static bool g_temp_requested = false;
static unsigned long g_temp_last_request = 0;
static float g_last_temperature = -127.0f;
static unsigned long g_last_hall_alert = 0;
static unsigned long g_last_motion_alert = 0;
static const unsigned long ALERT_COOLDOWN_MS = 600000;
static const uint32_t TZ_OFFSET = 10800; // +3h (MSK)
static uint32_t date_to_epoch(int y, int m, int d, int h, int mi) {
const uint8_t mdays[] = {31,28,31,30,31,30,31,31,30,31,30,31};
uint32_t days = (y - 1970) * 365;
@@ -63,11 +68,11 @@ static bool g_startup_msg_sent = false;
static unsigned long g_auto_status_interval = 0;
static unsigned long g_last_auto_status = 0;
struct SecurityConfig { uint32_t magic; uint8_t armed; uint8_t relay2; };
static const uint32_t CFG_MAGIC = 0x53454355;
struct SecurityConfig { uint32_t magic; uint8_t armed; uint8_t relay1; uint8_t relay2; uint8_t relay3; uint8_t relay4; };
static const uint32_t CFG_MAGIC = 0x53454357;
bool saveSecurityConfig() {
SecurityConfig cfg = { CFG_MAGIC, g_armed ? 1 : 0, g_relay2_state ? 1 : 0 };
SecurityConfig cfg = { CFG_MAGIC, g_armed ? 1 : 0, g_relay1_state ? 1 : 0, g_relay2_state ? 1 : 0, g_relay3_state ? 1 : 0, g_relay4_state ? 1 : 0 };
File f = InternalFS.open(CONFIG_FILE, FILE_O_WRITE);
if (!f) return false;
bool ok = f.write((const uint8_t*)&cfg, sizeof(cfg)) == sizeof(cfg);
@@ -81,7 +86,7 @@ bool loadSecurityConfig() {
if (f.read(&cfg, sizeof(cfg)) != sizeof(cfg)) { f.close(); return false; }
f.close();
if (cfg.magic != CFG_MAGIC) return false;
g_armed = cfg.armed; g_relay2_state = cfg.relay2;
g_armed = cfg.armed; g_relay1_state = cfg.relay1; g_relay2_state = cfg.relay2; g_relay3_state = cfg.relay3; g_relay4_state = cfg.relay4;
return true;
}
@@ -110,6 +115,9 @@ public:
return 0;
}
float last_rssi = -127.0f;
float last_snr = 0.0f;
char pending_response[256];
unsigned long pending_at = 0;
bool pending = false;
@@ -145,6 +153,9 @@ public:
if (type != PAYLOAD_TYPE_GRP_TXT) return;
if (len < 5 || data[4] != 0) return;
last_rssi = radio_driver.getLastRSSI();
last_snr = pkt->getSNR();
for (int i = 0; i < 3; i++) { digitalWrite(PIN_LED_STATUS, HIGH); delay(50); digitalWrite(PIN_LED_STATUS, LOW); delay(50); }
int tlen = len - 5;
@@ -162,23 +173,33 @@ public:
while (*cmd == ' ') cmd++;
if (strcmp(cmd, "help") == 0) {
defer_response("help:ohrana on,ohrana off,relay1 on,relay1 off,relay2 on,relay2 off,relay,status,ver,scan,uptime,kontrol,time,reboot");
defer_response("help:ohrana on,ohrana off,relay1 on,relay1 off,relay2 on,relay2 off,relay3 on,relay3 off,relay4 on,relay4 off,relay,status,ver,scan,snr,uptime,kontrol,time,reboot");
} else if (strcmp(cmd, "ohrana on") == 0) {
g_armed = true; digitalWrite(PIN_RELAY_1, LOW); saveSecurityConfig(); defer_response("ohrana on ok");
g_armed = true; saveSecurityConfig(); defer_response("ohrana on ok");
} else if (strcmp(cmd, "ohrana off") == 0) {
g_armed = false; digitalWrite(PIN_RELAY_1, HIGH); saveSecurityConfig(); defer_response("ohrana off ok");
g_armed = false; saveSecurityConfig(); defer_response("ohrana off ok");
} else if (strcmp(cmd, "relay1 on") == 0) {
digitalWrite(PIN_RELAY_1, LOW); defer_response("relay1 on ok");
g_relay1_state = true; digitalWrite(PIN_RELAY_1, HIGH); saveSecurityConfig(); defer_response("relay1 on ok");
} else if (strcmp(cmd, "relay1 off") == 0) {
digitalWrite(PIN_RELAY_1, HIGH); defer_response("relay1 off ok");
g_relay1_state = false; digitalWrite(PIN_RELAY_1, LOW); saveSecurityConfig(); defer_response("relay1 off ok");
} else if (strcmp(cmd, "relay2 on") == 0) {
g_relay2_state = true; digitalWrite(PIN_RELAY_2, LOW); defer_response("relay2 on ok");
g_relay2_state = true; digitalWrite(PIN_RELAY_2, HIGH); saveSecurityConfig(); defer_response("relay2 on ok");
} else if (strcmp(cmd, "relay2 off") == 0) {
g_relay2_state = false; digitalWrite(PIN_RELAY_2, HIGH); defer_response("relay2 off ok");
g_relay2_state = false; digitalWrite(PIN_RELAY_2, LOW); saveSecurityConfig(); defer_response("relay2 off ok");
} else if (strcmp(cmd, "relay3 on") == 0) {
g_relay3_state = true; digitalWrite(PIN_RELAY_3, HIGH); saveSecurityConfig(); defer_response("relay3 on ok");
} else if (strcmp(cmd, "relay3 off") == 0) {
g_relay3_state = false; digitalWrite(PIN_RELAY_3, LOW); saveSecurityConfig(); defer_response("relay3 off ok");
} else if (strcmp(cmd, "relay4 on") == 0) {
g_relay4_state = true; digitalWrite(PIN_RELAY_4, HIGH); saveSecurityConfig(); defer_response("relay4 on ok");
} else if (strcmp(cmd, "relay4 off") == 0) {
g_relay4_state = false; digitalWrite(PIN_RELAY_4, LOW); saveSecurityConfig(); defer_response("relay4 off ok");
} else if (strcmp(cmd, "relay") == 0) {
char r[32]; snprintf(r, sizeof(r), "relay:1%s 2%s",
digitalRead(PIN_RELAY_1) == LOW ? "on" : "off",
g_relay2_state ? "on" : "off");
char r[48]; snprintf(r, sizeof(r), "relay:1%s 2%s 3%s 4%s",
g_relay1_state ? "on" : "off",
g_relay2_state ? "on" : "off",
g_relay3_state ? "on" : "off",
g_relay4_state ? "on" : "off");
defer_response(r);
} else if (strcmp(cmd, "status") == 0) {
char r[128]; char tb[16]; char vb[16]; float t = g_last_temperature;
@@ -221,7 +242,7 @@ public:
} else if (strncmp(cmd, "time", 4) == 0) {
const char* rest = cmd + 4; while (*rest == ' ') rest++;
if (*rest == 0) {
uint32_t ts = rtc_clock.getCurrentTime();
uint32_t ts = rtc_clock.getCurrentTime() + TZ_OFFSET;
if (ts < 100000) { defer_response("time not set"); return; }
uint32_t days = ts / 86400;
int h = (ts % 86400) / 3600;
@@ -252,10 +273,13 @@ public:
if (y < 2020 || y > 2099 || m < 1 || m > 12 || d < 1 || d > 31 || h > 23 || mi > 59) {
defer_response("bad date"); return;
}
rtc_clock.setCurrentTime(date_to_epoch(y, m, d, h, mi));
rtc_clock.setCurrentTime(date_to_epoch(y, m, d, h, mi) - TZ_OFFSET);
char r[64]; snprintf(r, sizeof(r), "time set %02d.%02d.%04d %02d.%02d", d, m, y, h, mi);
defer_response(r);
} else defer_response("time s DD.MM.YYYY HH.MM");
} else if (strcmp(cmd, "snr") == 0) {
char r[48]; snprintf(r, sizeof(r), "rssi:%.0fdBm snr:%.1fdB", last_rssi, last_snr);
defer_response(r);
} else if (strcmp(cmd, "reboot") == 0) {
send_text("rebooting");
delay(100);
@@ -293,13 +317,15 @@ void setup() {
NRF_WDT->TASKS_START = 1;
pinMode(PIN_REED, INPUT_PULLUP); pinMode(PIN_PIR, INPUT); ds18b20.begin();
pinMode(PIN_RELAY_1, OUTPUT); pinMode(PIN_RELAY_2, OUTPUT); pinMode(PIN_LED_STATUS, OUTPUT);
digitalWrite(PIN_RELAY_1, HIGH); digitalWrite(PIN_RELAY_2, HIGH); digitalWrite(PIN_LED_STATUS, LOW);
pinMode(PIN_RELAY_1, OUTPUT); pinMode(PIN_RELAY_2, OUTPUT); pinMode(PIN_RELAY_3, OUTPUT); pinMode(PIN_RELAY_4, OUTPUT); pinMode(PIN_LED_STATUS, OUTPUT);
digitalWrite(PIN_RELAY_1, LOW); digitalWrite(PIN_RELAY_2, LOW); digitalWrite(PIN_RELAY_3, LOW); digitalWrite(PIN_RELAY_4, LOW); digitalWrite(PIN_LED_STATUS, LOW);
InternalFS.begin();
loadSecurityConfig();
if (g_armed) digitalWrite(PIN_RELAY_1, LOW); else digitalWrite(PIN_RELAY_1, HIGH);
digitalWrite(PIN_RELAY_2, g_relay2_state ? LOW : HIGH);
digitalWrite(PIN_RELAY_1, g_relay1_state ? HIGH : LOW);
digitalWrite(PIN_RELAY_2, g_relay2_state ? HIGH : LOW);
digitalWrite(PIN_RELAY_3, g_relay3_state ? HIGH : LOW);
digitalWrite(PIN_RELAY_4, g_relay4_state ? HIGH : LOW);
if (!radio_init()) {
Serial.println("RADIO FAIL");

View File

@@ -98,6 +98,12 @@
#ifndef PIN_RELAY_2
#define PIN_RELAY_2 4
#endif
#ifndef PIN_RELAY_3
#define PIN_RELAY_3 5
#endif
#ifndef PIN_RELAY_4
#define PIN_RELAY_4 6
#endif
#ifndef PIN_LED_STATUS
#define PIN_LED_STATUS 22
#endif
@@ -108,6 +114,12 @@
#ifndef PIN_RELAY_2
#define PIN_RELAY_2 5
#endif
#ifndef PIN_RELAY_3
#define PIN_RELAY_3 6
#endif
#ifndef PIN_RELAY_4
#define PIN_RELAY_4 7
#endif
#ifndef PIN_LED_STATUS
#define PIN_LED_STATUS 13
#endif