Initial project: XIAO ESP32S3 + SX1262 LoRa sensor link hytte–hjem
- cabin_node: subscribes to local MQTT (ESPHome sensors), sends temperature, battery voltage/SOC and switch states over LoRa SF12 - cabin_gw: receives LoRa packets, publishes JSON to home MQTT broker - Bidirectional: gateway forwards ON/OFF commands from home HA to node - cabin_node always in RX mode (12V powered) — commands arrive instantly - ESPHome config for ESP32 on teknisk rom: Victron MPPT BLE + JBD BMS BLE + DS18B20 temperatures + GPIO switches for varme/VVB Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
#pragma once
|
||||
|
||||
// LoRa radio parameters — must match exactly on node and gateway
|
||||
#define LORA_FREQ 868.0 // MHz
|
||||
#define LORA_SF 12
|
||||
#define LORA_BW 125.0 // kHz
|
||||
#define LORA_CR 5
|
||||
#define LORA_SYNC_WORD 0xAB // distinct from ice-track (0x34)
|
||||
#define LORA_POWER 22 // dBm (SX1262 max)
|
||||
|
||||
// Wio-SX1262 pins for XIAO ESP32S3
|
||||
// Verify against https://wiki.seeedstudio.com/wio_sx1262_with_xiao_esp32s3
|
||||
#define LORA_NSS 44 // D7
|
||||
#define LORA_RST 43 // D6
|
||||
#define LORA_DIO1 2 // D1
|
||||
#define LORA_BUSY 1 // D0
|
||||
|
||||
// Send interval (node) — 30 min fills one packet; adjust 1–4x/hour
|
||||
#define SEND_INTERVAL_MS (30UL * 60UL * 1000UL)
|
||||
|
||||
// MQTT broker (home, shared with mitt_lora)
|
||||
#define MQTT_HOST "192.168.86.31"
|
||||
#define MQTT_PORT 1883
|
||||
#define MQTT_USER "mqtt"
|
||||
#ifndef MQTT_PASS
|
||||
#define MQTT_PASS ""
|
||||
#endif
|
||||
|
||||
// MQTT topics (cabin ESPHome → node subscribes to these)
|
||||
#define TOPIC_TEMP_IN "hytte/sensor/temp_inne"
|
||||
#define TOPIC_TEMP_OUT "hytte/sensor/temp_ute"
|
||||
#define TOPIC_BATT_MV "hytte/sensor/batt_mv"
|
||||
#define TOPIC_BATT_PCT "hytte/sensor/batt_pct"
|
||||
|
||||
// MQTT topic gateway publishes received packets to (home broker)
|
||||
#define TOPIC_GW_STATUS "hytte/lora/status"
|
||||
|
||||
// Command topics (home HA publishes → cabin_gw → LoRa → cabin_node → ESPHome)
|
||||
// Payload: "ON" or "OFF"
|
||||
#define TOPIC_CMD_VARME "hytte/cmd/varme"
|
||||
#define TOPIC_CMD_VVB "hytte/cmd/vvb"
|
||||
|
||||
// ESPHome publishes switch states here (cabin_node subscribes)
|
||||
#define TOPIC_STATE_VARME "hytte/switch/varme/state"
|
||||
#define TOPIC_STATE_VVB "hytte/switch/vvb/state"
|
||||
|
||||
// WiFi credentials
|
||||
#ifndef WIFI_SSID
|
||||
#define WIFI_SSID "your-ssid"
|
||||
#endif
|
||||
#ifndef WIFI_PASS
|
||||
#define WIFI_PASS "your-pass"
|
||||
#endif
|
||||
|
||||
// HMAC key — 32+ chars, keep secret
|
||||
#ifndef HMAC_KEY
|
||||
#define HMAC_KEY "hytte-link-hmac-key-replace-me"
|
||||
#endif
|
||||
|
||||
#if __has_include("secrets.h")
|
||||
#include "secrets.h"
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include "mbedtls/md.h"
|
||||
#include "config.h"
|
||||
|
||||
// Returns a 4-byte truncated HMAC-SHA256 over `data` of `len` bytes.
|
||||
inline uint32_t hmac_sig(const uint8_t *data, size_t len)
|
||||
{
|
||||
static const char *key = HMAC_KEY;
|
||||
uint8_t out[32];
|
||||
mbedtls_md_hmac(
|
||||
mbedtls_md_info_from_type(MBEDTLS_MD_SHA256),
|
||||
reinterpret_cast<const uint8_t *>(key), strlen(key),
|
||||
data, len, out);
|
||||
uint32_t sig;
|
||||
memcpy(&sig, out, 4);
|
||||
return sig;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#define CABIN_PACKET_MAGIC 0xCA
|
||||
#define CABIN_CMD_MAGIC 0xCB
|
||||
|
||||
// Command IDs
|
||||
#define CMD_VARME 0x01
|
||||
#define CMD_VVB 0x02 // varmtvannsbereder
|
||||
|
||||
// Wire format: 13 bytes total
|
||||
// At SF12 BW125: ~1.3s airtime
|
||||
// flags bits: 0=varme, 1=vvb (1=on, 0=off)
|
||||
#define CABIN_FLAG_VARME (1 << 0)
|
||||
#define CABIN_FLAG_VVB (1 << 1)
|
||||
|
||||
struct __attribute__((packed)) CabinPacket {
|
||||
uint8_t magic; // = CABIN_PACKET_MAGIC
|
||||
uint8_t seq; // rolling counter
|
||||
int16_t temp_in_x10; // indoor temp * 10 (213 = 21.3 °C), INT16_MIN = no data
|
||||
int16_t temp_out_x10; // outdoor temp * 10, INT16_MIN = no data
|
||||
uint16_t batt_mv; // battery voltage mV (12V system: ~10000–14400)
|
||||
uint8_t batt_pct; // SOC 0–100, 0xFF = no data
|
||||
uint8_t flags; // switch states: bit0=varme, bit1=vvb
|
||||
uint32_t sig; // truncated HMAC-SHA256
|
||||
};
|
||||
|
||||
// Command packet: home → gateway → node → ESPHome switch
|
||||
// 8 bytes total
|
||||
struct __attribute__((packed)) CabinCmdPacket {
|
||||
uint8_t magic; // = CABIN_CMD_MAGIC
|
||||
uint8_t seq;
|
||||
uint8_t cmd_id; // CMD_VARME, CMD_VVB, ...
|
||||
uint8_t value; // 0 = off, 1 = on
|
||||
uint32_t sig;
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
// Copy to secrets.h and fill in before building
|
||||
#define WIFI_SSID "your-wifi-ssid"
|
||||
#define WIFI_PASS "your-wifi-password"
|
||||
#define MQTT_PASS "your-mqtt-password"
|
||||
#define HMAC_KEY "your-secret-hmac-key-at-least-32-chars"
|
||||
Reference in New Issue
Block a user