Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7e978fcc9c | ||
|
|
9ca5530c73 | ||
|
|
1430bba3f4 | ||
|
|
e68a762e88 | ||
|
|
9b1c8f3497 | ||
|
|
0b01526a39 | ||
|
|
fb30065edd | ||
|
|
87ac515063 | ||
|
|
9deb046ae3 | ||
|
|
d49443f66c | ||
|
|
8b21bccac2 | ||
|
|
d487b84926 | ||
|
|
62cf8fc3f4 | ||
|
|
acc36cf3ad | ||
|
|
d3990516b5 | ||
|
|
dfdd6ab343 | ||
|
|
cb2a33c97e |
@@ -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: 1–1440 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`.
|
||||
|
||||
---
|
||||
|
||||
11
README.md
11
README.md
@@ -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` | Отключить автоотправку |
|
||||
|
||||
@@ -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`.
|
||||
|
||||
---
|
||||
|
||||
## Задержка ответа
|
||||
|
||||
40
WIRING.md
40
WIRING.md
@@ -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`. Состояние сохраняется.
|
||||
|
||||
---
|
||||
|
||||
@@ -141,6 +171,8 @@ IN2 ── P0.22
|
||||
│ │ │
|
||||
Геркон ──┤ P0.08│ P0.20 ─── Реле 1 │
|
||||
│ │ P0.22 ─── Реле 2 │
|
||||
│ │ P0.24 ─── Реле 3 │
|
||||
│ │ P1.00 ─── Реле 4 │
|
||||
PIR ────┤ P0.06│ │
|
||||
│ │ P0.15 ─── LED статуса│
|
||||
DS18B20 ───┤ P0.17│ │
|
||||
|
||||
66
src/main.cpp
66
src/main.cpp
@@ -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");
|
||||
|
||||
12
src/target.h
12
src/target.h
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user